diff options
Diffstat (limited to 'deps/v8/src/compiler.h')
-rw-r--r-- | deps/v8/src/compiler.h | 296 |
1 files changed, 137 insertions, 159 deletions
diff --git a/deps/v8/src/compiler.h b/deps/v8/src/compiler.h index fa043995b4..55215733c1 100644 --- a/deps/v8/src/compiler.h +++ b/deps/v8/src/compiler.h @@ -5,10 +5,16 @@ #ifndef V8_COMPILER_H_ #define V8_COMPILER_H_ +#include <memory> + #include "src/allocation.h" -#include "src/ast/ast.h" #include "src/bailout-reason.h" #include "src/compilation-dependencies.h" +#include "src/contexts.h" +#include "src/frames.h" +#include "src/isolate.h" +#include "src/objects-inl.h" +#include "src/source-position-table.h" #include "src/source-position.h" #include "src/zone.h" @@ -17,8 +23,8 @@ namespace internal { // Forward declarations. class CompilationInfo; +class CompilationJob; class JavaScriptFrame; -class OptimizedCompileJob; class ParseInfo; class ScriptData; @@ -36,6 +42,7 @@ class Compiler : public AllStatic { public: enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION }; enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT }; + enum CompilationTier { INTERPRETED, BASELINE, OPTIMIZED }; // =========================================================================== // The following family of methods ensures a given function is compiled. The @@ -44,13 +51,14 @@ class Compiler : public AllStatic { // given function holds (except for live-edit, which compiles the world). static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag); + static bool CompileBaseline(Handle<JSFunction> function); static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode); static bool CompileDebugCode(Handle<JSFunction> function); static bool CompileDebugCode(Handle<SharedFunctionInfo> shared); - static void CompileForLiveEdit(Handle<Script> script); + static MaybeHandle<JSArray> CompileForLiveEdit(Handle<Script> script); - // Generate and install code from previously queued optimization job. - static void FinalizeOptimizedCompileJob(OptimizedCompileJob* job); + // Generate and install code from previously queued compilation job. + static void FinalizeCompilationJob(CompilationJob* job); // Give the compiler a chance to perform low-latency initialization tasks of // the given {function} on its instantiation. Note that only the runtime will @@ -63,6 +71,12 @@ class Compiler : public AllStatic { static bool Analyze(ParseInfo* info); // Adds deoptimization support, requires ParseAndAnalyze. static bool EnsureDeoptimizationSupport(CompilationInfo* info); + // Ensures that bytecode is generated, calls ParseAndAnalyze internally. + static bool EnsureBytecode(CompilationInfo* info); + + // The next compilation tier which the function should be compiled to for + // optimization. This is used as a hint by the runtime profiler. + static CompilationTier NextCompilationTier(JSFunction* function); // =========================================================================== // The following family of methods instantiates new functions for scripts or @@ -77,10 +91,16 @@ class Compiler : public AllStatic { MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval( Handle<String> source, Handle<SharedFunctionInfo> outer_info, Handle<Context> context, LanguageMode language_mode, - ParseRestriction restriction, int line_offset, int column_offset = 0, + ParseRestriction restriction, int eval_scope_position, int eval_position, + int line_offset = 0, int column_offset = 0, Handle<Object> script_name = Handle<Object>(), ScriptOriginOptions options = ScriptOriginOptions()); + // Create a (bound) function for a String source within a context for eval. + MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromString( + Handle<Context> context, Handle<String> source, + ParseRestriction restriction); + // Create a shared function info object for a String source within a context. static Handle<SharedFunctionInfo> GetSharedFunctionInfoForScript( Handle<String> source, Handle<Object> script_name, int line_offset, @@ -118,26 +138,10 @@ class Compiler : public AllStatic { JavaScriptFrame* osr_frame); }; -struct InlinedFunctionInfo { - InlinedFunctionInfo(int parent_id, SourcePosition inline_position, - int script_id, int start_position) - : parent_id(parent_id), - inline_position(inline_position), - script_id(script_id), - start_position(start_position) {} - int parent_id; - SourcePosition inline_position; - int script_id; - int start_position; - std::vector<size_t> deopt_pc_offsets; - - static const int kNoParentId = -1; -}; - // CompilationInfo encapsulates some information known at compile time. It // is constructed based on the resources available at compile-time. -class CompilationInfo { +class CompilationInfo final { public: // Various configuration flags for a compilation, as well as some properties // of the compiled code produced by a compilation. @@ -154,19 +158,20 @@ class CompilationInfo { kFrameSpecializing = 1 << 9, kNativeContextSpecializing = 1 << 10, kInliningEnabled = 1 << 11, - kTypingEnabled = 1 << 12, - kDisableFutureOptimization = 1 << 13, - kSplittingEnabled = 1 << 14, - kDeoptimizationEnabled = 1 << 16, - kSourcePositionsEnabled = 1 << 17, - kFirstCompile = 1 << 18, - kBailoutOnUninitialized = 1 << 19, + kDisableFutureOptimization = 1 << 12, + kSplittingEnabled = 1 << 13, + kDeoptimizationEnabled = 1 << 14, + kSourcePositionsEnabled = 1 << 15, + kBailoutOnUninitialized = 1 << 16, + kOptimizeFromBytecode = 1 << 17, + kTypeFeedbackEnabled = 1 << 18, + kAccessorInliningEnabled = 1 << 19, }; - explicit CompilationInfo(ParseInfo* parse_info); - CompilationInfo(const char* debug_name, Isolate* isolate, Zone* zone, + CompilationInfo(ParseInfo* parse_info, Handle<JSFunction> closure); + CompilationInfo(Vector<const char> debug_name, Isolate* isolate, Zone* zone, Code::Flags code_flags = Code::ComputeFlags(Code::STUB)); - virtual ~CompilationInfo(); + ~CompilationInfo(); ParseInfo* parse_info() const { return parse_info_; } @@ -174,19 +179,11 @@ class CompilationInfo { // TODO(titzer): inline and delete accessors of ParseInfo // ----------------------------------------------------------- Handle<Script> script() const; - bool is_eval() const; - bool is_native() const; - bool is_module() const; - LanguageMode language_mode() const; - Handle<JSFunction> closure() const; FunctionLiteral* literal() const; - Scope* scope() const; + DeclarationScope* scope() const; Handle<Context> context() const; Handle<SharedFunctionInfo> shared_info() const; bool has_shared_info() const; - bool has_context() const; - bool has_literal() const; - bool has_scope() const; // ----------------------------------------------------------- Isolate* isolate() const { @@ -194,14 +191,14 @@ class CompilationInfo { } Zone* zone() { return zone_; } bool is_osr() const { return !osr_ast_id_.IsNone(); } + Handle<JSFunction> closure() const { return closure_; } Handle<Code> code() const { return code_; } Code::Flags code_flags() const { return code_flags_; } BailoutId osr_ast_id() const { return osr_ast_id_; } - int opt_count() const { return opt_count_; } + JavaScriptFrame* osr_frame() const { return osr_frame_; } int num_parameters() const; int num_parameters_including_this() const; bool is_this_defined() const; - int num_heap_slots() const; void set_parameter_count(int parameter_count) { DCHECK(IsStub()); @@ -211,11 +208,6 @@ class CompilationInfo { bool has_bytecode_array() const { return !bytecode_array_.is_null(); } Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; } - Handle<AbstractCode> abstract_code() const { - return has_bytecode_array() ? Handle<AbstractCode>::cast(bytecode_array()) - : Handle<AbstractCode>::cast(code()); - } - bool is_tracking_positions() const { return track_positions_; } bool is_calling() const { @@ -284,6 +276,18 @@ class CompilationInfo { return GetFlag(kDeoptimizationEnabled); } + void MarkAsTypeFeedbackEnabled() { SetFlag(kTypeFeedbackEnabled); } + + bool is_type_feedback_enabled() const { + return GetFlag(kTypeFeedbackEnabled); + } + + void MarkAsAccessorInliningEnabled() { SetFlag(kAccessorInliningEnabled); } + + bool is_accessor_inlining_enabled() const { + return GetFlag(kAccessorInliningEnabled); + } + void MarkAsSourcePositionsEnabled() { SetFlag(kSourcePositionsEnabled); } bool is_source_positions_enabled() const { @@ -294,26 +298,22 @@ class CompilationInfo { bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); } - void MarkAsTypingEnabled() { SetFlag(kTypingEnabled); } - - bool is_typing_enabled() const { return GetFlag(kTypingEnabled); } - void MarkAsSplittingEnabled() { SetFlag(kSplittingEnabled); } bool is_splitting_enabled() const { return GetFlag(kSplittingEnabled); } - void MarkAsFirstCompile() { SetFlag(kFirstCompile); } - - void MarkAsCompiled() { SetFlag(kFirstCompile, false); } - - bool is_first_compile() const { return GetFlag(kFirstCompile); } - void MarkAsBailoutOnUninitialized() { SetFlag(kBailoutOnUninitialized); } bool is_bailout_on_uninitialized() const { return GetFlag(kBailoutOnUninitialized); } + void MarkAsOptimizeFromBytecode() { SetFlag(kOptimizeFromBytecode); } + + bool is_optimizing_from_bytecode() const { + return GetFlag(kOptimizeFromBytecode); + } + bool GeneratePreagedPrologue() const { // Generate a pre-aged prologue if we are optimizing for size, which // will make code flushing more aggressive. Only apply to Code::FUNCTION, @@ -357,9 +357,10 @@ class CompilationInfo { code_flags_ = Code::KindField::update(code_flags_, Code::OPTIMIZED_FUNCTION); } - void SetOptimizingForOsr(BailoutId osr_ast_id) { + void SetOptimizingForOsr(BailoutId osr_ast_id, JavaScriptFrame* osr_frame) { SetOptimizing(); osr_ast_id_ = osr_ast_id; + osr_frame_ = osr_frame; } // Deoptimization support. @@ -383,7 +384,7 @@ class CompilationInfo { } void ReopenHandlesInNewHandleScope() { - // Empty for now but will be needed once fields move from ParseInfo. + closure_ = Handle<JSFunction>(*closure_); } void AbortOptimization(BailoutReason reason) { @@ -410,23 +411,8 @@ class CompilationInfo { prologue_offset_ = prologue_offset; } - int start_position_for(uint32_t inlining_id) { - return inlined_function_infos_.at(inlining_id).start_position; - } - const std::vector<InlinedFunctionInfo>& inlined_function_infos() { - return inlined_function_infos_; - } - - void LogDeoptCallPosition(int pc_offset, int inlining_id); - int TraceInlinedFunction(Handle<SharedFunctionInfo> shared, - SourcePosition position, int pareint_id); - CompilationDependencies* dependencies() { return &dependencies_; } - bool HasSameOsrEntry(Handle<JSFunction> function, BailoutId osr_ast_id) { - return osr_ast_id_ == osr_ast_id && function.is_identical_to(closure()); - } - int optimization_id() const { return optimization_id_; } int osr_expr_stack_height() { return osr_expr_stack_height_; } @@ -434,12 +420,6 @@ class CompilationInfo { DCHECK(height >= 0); osr_expr_stack_height_ = height; } - JavaScriptFrame* osr_frame() const { return osr_frame_; } - void set_osr_frame(JavaScriptFrame* osr_frame) { osr_frame_ = osr_frame; } - -#if DEBUG - void PrintAstForTesting(); -#endif bool has_simple_parameters(); @@ -466,7 +446,7 @@ class CompilationInfo { inlined_functions_.push_back(InlinedFunctionHolder(inlined_function)); } - base::SmartArrayPointer<char> GetDebugName() const; + std::unique_ptr<char[]> GetDebugName() const; Code::Kind output_code_kind() const { return Code::ExtractKindFromFlags(code_flags_); @@ -474,26 +454,9 @@ class CompilationInfo { StackFrame::Type GetOutputStackFrameType() const; - protected: - ParseInfo* parse_info_; + int GetDeclareGlobalsFlags() const; - void DisableFutureOptimization() { - if (GetFlag(kDisableFutureOptimization) && has_shared_info()) { - // If Crankshaft tried to optimize this function, bailed out, and - // doesn't want to try again, then use TurboFan next time. - if (!shared_info()->dont_crankshaft() && - bailout_reason() != kOptimizedTooManyTimes) { - shared_info()->set_dont_crankshaft(true); - if (FLAG_trace_opt) { - PrintF("[disabled Crankshaft for "); - shared_info()->ShortPrint(); - PrintF(", reason: %s]\n", GetBailoutReason(bailout_reason())); - } - } else { - shared_info()->DisableOptimization(bailout_reason()); - } - } - } + SourcePositionTableBuilder::RecordingMode SourcePositionRecordingMode() const; private: // Compilation mode. @@ -505,10 +468,11 @@ class CompilationInfo { STUB }; - CompilationInfo(ParseInfo* parse_info, const char* debug_name, + CompilationInfo(ParseInfo* parse_info, Vector<const char> debug_name, Code::Flags code_flags, Mode mode, Isolate* isolate, Zone* zone); + ParseInfo* parse_info_; Isolate* isolate_; void SetMode(Mode mode) { @@ -527,6 +491,8 @@ class CompilationInfo { Code::Flags code_flags_; + Handle<JSFunction> closure_; + // The compiled code. Handle<Code> code_; @@ -552,15 +518,10 @@ class CompilationInfo { int prologue_offset_; - std::vector<InlinedFunctionInfo> inlined_function_infos_; bool track_positions_; InlinedFunctionList inlined_functions_; - // A copy of shared_info()->opt_count() to avoid handle deref - // during graph optimization. - int opt_count_; - // Number of parameters used for compilation of stubs that require arguments. int parameter_count_; @@ -571,78 +532,95 @@ class CompilationInfo { // The current OSR frame for specialization or {nullptr}. JavaScriptFrame* osr_frame_ = nullptr; - const char* debug_name_; + Vector<const char> debug_name_; DISALLOW_COPY_AND_ASSIGN(CompilationInfo); }; - -class HGraph; -class LChunk; - -// A helper class that calls the three compilation phases in -// Crankshaft and keeps track of its state. The three phases -// CreateGraph, OptimizeGraph and GenerateAndInstallCode can either -// fail, bail-out to the full code generator or succeed. Apart from -// their return value, the status of the phase last run can be checked -// using last_status(). -class OptimizedCompileJob: public ZoneObject { +// A base class for compilation jobs intended to run concurrent to the main +// thread. The job is split into three phases which are called in sequence on +// different threads and with different limitations: +// 1) PrepareJob: Runs on main thread. No major limitations. +// 2) ExecuteJob: Runs concurrently. No heap allocation or handle derefs. +// 3) FinalizeJob: Runs on main thread. No dependency changes. +// +// Each of the three phases can either fail or succeed. The current state of +// the job can be checked using {state()}. +class CompilationJob { public: - explicit OptimizedCompileJob(CompilationInfo* info) - : info_(info), graph_(NULL), chunk_(NULL), last_status_(FAILED) {} - - enum Status { - FAILED, BAILED_OUT, SUCCEEDED + enum Status { SUCCEEDED, FAILED }; + enum class State { + kReadyToPrepare, + kReadyToExecute, + kReadyToFinalize, + kSucceeded, + kFailed, }; - MUST_USE_RESULT Status CreateGraph(); - MUST_USE_RESULT Status OptimizeGraph(); - MUST_USE_RESULT Status GenerateCode(); + explicit CompilationJob(CompilationInfo* info, const char* compiler_name, + State initial_state = State::kReadyToPrepare) + : info_(info), compiler_name_(compiler_name), state_(initial_state) {} + virtual ~CompilationJob() {} - Status last_status() const { return last_status_; } - CompilationInfo* info() const { return info_; } - Isolate* isolate() const { return info()->isolate(); } + // Prepare the compile job. Must be called on the main thread. + MUST_USE_RESULT Status PrepareJob(); + + // Executes the compile job. Can be called off the main thread. + MUST_USE_RESULT Status ExecuteJob(); + + // Finalizes the compile job. Must be called on the main thread. + MUST_USE_RESULT Status FinalizeJob(); + // Report a transient failure, try again next time. Should only be called on + // optimization compilation jobs. Status RetryOptimization(BailoutReason reason) { + DCHECK(info_->IsOptimizing()); info_->RetryOptimization(reason); - return SetLastStatus(BAILED_OUT); + state_ = State::kFailed; + return FAILED; } + // Report a persistent failure, disable future optimization on the function. + // Should only be called on optimization compilation jobs. Status AbortOptimization(BailoutReason reason) { + DCHECK(info_->IsOptimizing()); info_->AbortOptimization(reason); - return SetLastStatus(BAILED_OUT); + state_ = State::kFailed; + return FAILED; } - private: - CompilationInfo* info_; - HGraph* graph_; - LChunk* chunk_; - base::TimeDelta time_taken_to_create_graph_; - base::TimeDelta time_taken_to_optimize_; - base::TimeDelta time_taken_to_codegen_; - Status last_status_; - - MUST_USE_RESULT Status SetLastStatus(Status status) { - last_status_ = status; - return last_status_; - } void RecordOptimizationStats(); - struct Timer { - Timer(OptimizedCompileJob* job, base::TimeDelta* location) - : job_(job), location_(location) { - DCHECK(location_ != NULL); - timer_.Start(); - } + State state() const { return state_; } + CompilationInfo* info() const { return info_; } + Isolate* isolate() const { return info()->isolate(); } - ~Timer() { - *location_ += timer_.Elapsed(); - } + protected: + // Overridden by the actual implementation. + virtual Status PrepareJobImpl() = 0; + virtual Status ExecuteJobImpl() = 0; + virtual Status FinalizeJobImpl() = 0; - OptimizedCompileJob* job_; - base::ElapsedTimer timer_; - base::TimeDelta* location_; - }; + // Registers weak object to optimized code dependencies. + // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies. + void RegisterWeakObjectsInOptimizedCode(Handle<Code> code); + + private: + CompilationInfo* info_; + base::TimeDelta time_taken_to_prepare_; + base::TimeDelta time_taken_to_execute_; + base::TimeDelta time_taken_to_finalize_; + const char* compiler_name_; + State state_; + + MUST_USE_RESULT Status UpdateState(Status status, State next_state) { + if (status == SUCCEEDED) { + state_ = next_state; + } else { + state_ = State::kFailed; + } + return status; + } }; } // namespace internal |