summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler.h')
-rw-r--r--deps/v8/src/compiler.h296
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