// Copyright 2016 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_COMPILATION_INFO_H_ #define V8_COMPILATION_INFO_H_ #include <memory> #include "src/compilation-dependencies.h" #include "src/feedback-vector.h" #include "src/frames.h" #include "src/globals.h" #include "src/handles.h" #include "src/objects.h" #include "src/source-position-table.h" #include "src/utils.h" #include "src/vector.h" namespace v8 { namespace internal { class CoverageInfo; class DeclarationScope; class DeferredHandles; class FunctionLiteral; class Isolate; class JavaScriptFrame; class ParseInfo; class SourceRangeMap; class Zone; // CompilationInfo encapsulates some information known at compile time. It // is constructed based on the resources available at compile-time. // TODO(rmcilroy): Split CompilationInfo into two classes, one for unoptimized // compilation and one for optimized compilation, since they don't share much. class V8_EXPORT_PRIVATE CompilationInfo final { public: // Various configuration flags for a compilation, as well as some properties // of the compiled code produced by a compilation. enum Flag { kIsEval = 1 << 0, kIsNative = 1 << 1, kCollectTypeProfile = 1 << 2, kAccessorInliningEnabled = 1 << 3, kFunctionContextSpecializing = 1 << 4, kInliningEnabled = 1 << 5, kDisableFutureOptimization = 1 << 6, kSplittingEnabled = 1 << 7, kSourcePositionsEnabled = 1 << 8, kBailoutOnUninitialized = 1 << 9, kLoopPeelingEnabled = 1 << 10, kUntrustedCodeMitigations = 1 << 11, }; // TODO(mtrofin): investigate if this might be generalized outside wasm, with // the goal of better separating the compiler from where compilation lands. At // that point, the Handle<Code> member of CompilationInfo would also be // removed. struct WasmCodeDesc { CodeDesc code_desc; size_t safepoint_table_offset = 0; uint32_t frame_slot_count = 0; Handle<ByteArray> source_positions_table; MaybeHandle<HandlerTable> handler_table; }; // Construct a compilation info for unoptimized compilation. CompilationInfo(Zone* zone, ParseInfo* parse_info, FunctionLiteral* literal); // Construct a compilation info for optimized compilation. CompilationInfo(Zone* zone, Isolate* isolate, Handle<SharedFunctionInfo> shared, Handle<JSFunction> closure); // Construct a compilation info for stub compilation (or testing). CompilationInfo(Vector<const char> debug_name, Zone* zone, Code::Kind code_kind); ~CompilationInfo(); FunctionLiteral* literal() const { return literal_; } void set_literal(FunctionLiteral* literal) { DCHECK_NOT_NULL(literal); literal_ = literal; } bool has_source_range_map() const { return source_range_map_ != nullptr; } SourceRangeMap* source_range_map() const { return source_range_map_; } void set_source_range_map(SourceRangeMap* source_range_map) { source_range_map_ = source_range_map; } DeclarationScope* scope() const; Zone* zone() { return zone_; } bool is_osr() const { return !osr_offset_.IsNone(); } Handle<SharedFunctionInfo> shared_info() const { return shared_info_; } void set_shared_info(Handle<SharedFunctionInfo> shared_info) { shared_info_ = shared_info; } bool has_shared_info() const { return !shared_info().is_null(); } Handle<JSFunction> closure() const { return closure_; } Handle<Code> code() const { return code_; } Code::Kind code_kind() const { return code_kind_; } uint32_t stub_key() const { return stub_key_; } void set_stub_key(uint32_t stub_key) { stub_key_ = stub_key; } int32_t builtin_index() const { return builtin_index_; } void set_builtin_index(int32_t index) { builtin_index_ = index; } BailoutId osr_offset() const { return osr_offset_; } JavaScriptFrame* osr_frame() const { return osr_frame_; } int num_parameters() const; int num_parameters_including_this() const; bool is_this_defined() const; void set_parameter_count(int parameter_count) { DCHECK(IsStub()); parameter_count_ = parameter_count; } bool has_bytecode_array() const { return !bytecode_array_.is_null(); } Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; } bool has_asm_wasm_data() const { return !asm_wasm_data_.is_null(); } Handle<FixedArray> asm_wasm_data() const { return asm_wasm_data_; } // Flags used by unoptimized compilation. void MarkAsEval() { SetFlag(kIsEval); } bool is_eval() const { return GetFlag(kIsEval); } void MarkAsNative() { SetFlag(kIsNative); } bool is_native() const { return GetFlag(kIsNative); } void MarkAsCollectTypeProfile() { SetFlag(kCollectTypeProfile); } bool collect_type_profile() const { return GetFlag(kCollectTypeProfile); } // Flags used by optimized compilation. void MarkAsFunctionContextSpecializing() { SetFlag(kFunctionContextSpecializing); } bool is_function_context_specializing() const { return GetFlag(kFunctionContextSpecializing); } void MarkAsAccessorInliningEnabled() { SetFlag(kAccessorInliningEnabled); } bool is_accessor_inlining_enabled() const { return GetFlag(kAccessorInliningEnabled); } void MarkAsSourcePositionsEnabled() { SetFlag(kSourcePositionsEnabled); } bool is_source_positions_enabled() const { return GetFlag(kSourcePositionsEnabled); } void MarkAsInliningEnabled() { SetFlag(kInliningEnabled); } bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); } void MarkAsSplittingEnabled() { SetFlag(kSplittingEnabled); } bool is_splitting_enabled() const { return GetFlag(kSplittingEnabled); } void MarkAsBailoutOnUninitialized() { SetFlag(kBailoutOnUninitialized); } bool is_bailout_on_uninitialized() const { return GetFlag(kBailoutOnUninitialized); } void MarkAsLoopPeelingEnabled() { SetFlag(kLoopPeelingEnabled); } bool is_loop_peeling_enabled() const { return GetFlag(kLoopPeelingEnabled); } bool has_untrusted_code_mitigations() const { return GetFlag(kUntrustedCodeMitigations); } // Code getters and setters. void SetCode(Handle<Code> code) { code_ = code; } void SetBytecodeArray(Handle<BytecodeArray> bytecode_array) { bytecode_array_ = bytecode_array; } void SetAsmWasmData(Handle<FixedArray> asm_wasm_data) { asm_wasm_data_ = asm_wasm_data; } FeedbackVectorSpec* feedback_vector_spec() { return &feedback_vector_spec_; } bool has_context() const; Context* context() const; bool has_native_context() const; Context* native_context() const; bool has_global_object() const; JSGlobalObject* global_object() const; // Accessors for the different compilation modes. bool IsOptimizing() const { return mode_ == OPTIMIZE; } bool IsStub() const { return mode_ == STUB; } bool IsWasm() const { return code_kind() == Code::WASM_FUNCTION; } void SetOptimizingForOsr(BailoutId osr_offset, JavaScriptFrame* osr_frame) { DCHECK(IsOptimizing()); osr_offset_ = osr_offset; osr_frame_ = osr_frame; } void set_deferred_handles(std::shared_ptr<DeferredHandles> deferred_handles); void set_deferred_handles(DeferredHandles* deferred_handles); std::shared_ptr<DeferredHandles> deferred_handles() { return deferred_handles_; } void ReopenHandlesInNewHandleScope(); void AbortOptimization(BailoutReason reason) { DCHECK_NE(reason, BailoutReason::kNoReason); if (bailout_reason_ == BailoutReason::kNoReason) bailout_reason_ = reason; SetFlag(kDisableFutureOptimization); } void RetryOptimization(BailoutReason reason) { DCHECK_NE(reason, BailoutReason::kNoReason); if (GetFlag(kDisableFutureOptimization)) return; bailout_reason_ = reason; } BailoutReason bailout_reason() const { return bailout_reason_; } CompilationDependencies* dependencies() { return dependencies_.get(); } int optimization_id() const { DCHECK(IsOptimizing()); return optimization_id_; } bool has_simple_parameters(); struct InlinedFunctionHolder { Handle<SharedFunctionInfo> shared_info; InliningPosition position; InlinedFunctionHolder(Handle<SharedFunctionInfo> inlined_shared_info, SourcePosition pos) : shared_info(inlined_shared_info) { position.position = pos; // initialized when generating the deoptimization literals position.inlined_function_id = DeoptimizationData::kNotInlinedIndex; } void RegisterInlinedFunctionId(size_t inlined_function_id) { position.inlined_function_id = static_cast<int>(inlined_function_id); } }; typedef std::vector<InlinedFunctionHolder> InlinedFunctionList; InlinedFunctionList& inlined_functions() { return inlined_functions_; } // Returns the inlining id for source position tracking. int AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function, SourcePosition pos); std::unique_ptr<char[]> GetDebugName() const; StackFrame::Type GetOutputStackFrameType() const; int GetDeclareGlobalsFlags() const; SourcePositionTableBuilder::RecordingMode SourcePositionRecordingMode() const; bool has_coverage_info() const { return !coverage_info_.is_null(); } Handle<CoverageInfo> coverage_info() const { return coverage_info_; } void set_coverage_info(Handle<CoverageInfo> coverage_info) { coverage_info_ = coverage_info; } WasmCodeDesc* wasm_code_desc() { return &wasm_code_desc_; } private: // Compilation mode. // BASE is generated by the full codegen, optionally prepared for bailouts. // OPTIMIZE is optimized code generated by the Hydrogen-based backend. enum Mode { BASE, OPTIMIZE, STUB }; CompilationInfo(Vector<const char> debug_name, Code::Kind code_kind, Mode mode, Zone* zone); void SetMode(Mode mode) { mode_ = mode; } void SetFlag(Flag flag) { flags_ |= flag; } void SetFlag(Flag flag, bool value) { flags_ = value ? flags_ | flag : flags_ & ~flag; } bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; } FunctionLiteral* literal_; SourceRangeMap* source_range_map_; // Used when block coverage is enabled. unsigned flags_; Code::Kind code_kind_; uint32_t stub_key_; int32_t builtin_index_; Handle<SharedFunctionInfo> shared_info_; Handle<JSFunction> closure_; // The compiled code. Handle<Code> code_; WasmCodeDesc wasm_code_desc_; // Compilation mode flag and whether deoptimization is allowed. Mode mode_; BailoutId osr_offset_; // Holds the bytecode array generated by the interpreter. // TODO(rmcilroy/mstarzinger): Temporary work-around until compiler.cc is // refactored to avoid us needing to carry the BytcodeArray around. Handle<BytecodeArray> bytecode_array_; // Holds the asm_wasm array generated by the asmjs compiler. Handle<FixedArray> asm_wasm_data_; // Holds the feedback vector spec generated during compilation FeedbackVectorSpec feedback_vector_spec_; // The zone from which the compilation pipeline working on this // CompilationInfo allocates. Zone* zone_; std::shared_ptr<DeferredHandles> deferred_handles_; // Dependencies for this compilation, e.g. stable maps. std::unique_ptr<CompilationDependencies> dependencies_; BailoutReason bailout_reason_; InlinedFunctionList inlined_functions_; // Number of parameters used for compilation of stubs that require arguments. int parameter_count_; int optimization_id_; // The current OSR frame for specialization or {nullptr}. JavaScriptFrame* osr_frame_ = nullptr; Vector<const char> debug_name_; // Encapsulates coverage information gathered by the bytecode generator. // Needs to be stored on the shared function info once compilation completes. Handle<CoverageInfo> coverage_info_; DISALLOW_COPY_AND_ASSIGN(CompilationInfo); }; } // namespace internal } // namespace v8 #endif // V8_COMPILATION_INFO_H_