| Index: src/compiler.cc
|
| diff --git a/src/compiler.cc b/src/compiler.cc
|
| index 7977bd04d3da23c6ef018fd343906bd241a27e86..8e9095bc1b1ae918c5e77866a2318838de0519f3 100644
|
| --- a/src/compiler.cc
|
| +++ b/src/compiler.cc
|
| @@ -15,13 +15,10 @@
|
| #include "src/compilation-cache.h"
|
| #include "src/compiler/pipeline.h"
|
| #include "src/crankshaft/hydrogen.h"
|
| -#include "src/crankshaft/lithium.h"
|
| -#include "src/crankshaft/typing.h"
|
| #include "src/debug/debug.h"
|
| #include "src/debug/liveedit.h"
|
| #include "src/deoptimizer.h"
|
| #include "src/full-codegen/full-codegen.h"
|
| -#include "src/gdb-jit.h"
|
| #include "src/interpreter/interpreter.h"
|
| #include "src/isolate-inl.h"
|
| #include "src/log-inl.h"
|
| @@ -102,6 +99,19 @@ class CompilationInfoWithZone : public CompilationInfo {
|
| Zone zone_;
|
| };
|
|
|
| +// Helper that times a scoped region and records the elapsed time.
|
| +struct ScopedTimer {
|
| + explicit ScopedTimer(base::TimeDelta* location) : location_(location) {
|
| + DCHECK(location_ != NULL);
|
| + timer_.Start();
|
| + }
|
| +
|
| + ~ScopedTimer() { *location_ += timer_.Elapsed(); }
|
| +
|
| + base::ElapsedTimer timer_;
|
| + base::TimeDelta* location_;
|
| +};
|
| +
|
| // ----------------------------------------------------------------------------
|
| // Implementation of CompilationInfo
|
|
|
| @@ -306,51 +316,6 @@ void CompilationInfo::PrintAstForTesting() {
|
| // ----------------------------------------------------------------------------
|
| // Implementation of OptimizedCompileJob
|
|
|
| -class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder {
|
| - public:
|
| - explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info)
|
| - : HOptimizedGraphBuilder(info) {
|
| - }
|
| -
|
| -#define DEF_VISIT(type) \
|
| - void Visit##type(type* node) override { \
|
| - SourcePosition old_position = SourcePosition::Unknown(); \
|
| - if (node->position() != RelocInfo::kNoPosition) { \
|
| - old_position = source_position(); \
|
| - SetSourcePosition(node->position()); \
|
| - } \
|
| - HOptimizedGraphBuilder::Visit##type(node); \
|
| - if (!old_position.IsUnknown()) { \
|
| - set_source_position(old_position); \
|
| - } \
|
| - }
|
| - EXPRESSION_NODE_LIST(DEF_VISIT)
|
| -#undef DEF_VISIT
|
| -
|
| -#define DEF_VISIT(type) \
|
| - void Visit##type(type* node) override { \
|
| - SourcePosition old_position = SourcePosition::Unknown(); \
|
| - if (node->position() != RelocInfo::kNoPosition) { \
|
| - old_position = source_position(); \
|
| - SetSourcePosition(node->position()); \
|
| - } \
|
| - HOptimizedGraphBuilder::Visit##type(node); \
|
| - if (!old_position.IsUnknown()) { \
|
| - set_source_position(old_position); \
|
| - } \
|
| - }
|
| - STATEMENT_NODE_LIST(DEF_VISIT)
|
| -#undef DEF_VISIT
|
| -
|
| -#define DEF_VISIT(type) \
|
| - void Visit##type(type* node) override { \
|
| - HOptimizedGraphBuilder::Visit##type(node); \
|
| - }
|
| - DECLARATION_NODE_LIST(DEF_VISIT)
|
| -#undef DEF_VISIT
|
| -};
|
| -
|
| -
|
| OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() {
|
| DCHECK(info()->IsOptimizing());
|
|
|
| @@ -393,126 +358,10 @@ OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() {
|
| DCHECK(info()->shared_info()->has_deoptimization_support());
|
| DCHECK(!info()->is_first_compile());
|
|
|
| - bool optimization_disabled = info()->shared_info()->optimization_disabled();
|
| - bool dont_crankshaft = info()->shared_info()->dont_crankshaft();
|
| -
|
| - // Check the enabling conditions for Turbofan.
|
| - // 1. "use asm" code.
|
| - bool is_turbofanable_asm = FLAG_turbo_asm &&
|
| - info()->shared_info()->asm_function() &&
|
| - !optimization_disabled;
|
| -
|
| - // 2. Fallback for features unsupported by Crankshaft.
|
| - bool is_unsupported_by_crankshaft_but_turbofanable =
|
| - dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 &&
|
| - !optimization_disabled;
|
| -
|
| - // 3. Explicitly enabled by the command-line filter.
|
| - bool passes_turbo_filter =
|
| - info()->shared_info()->PassesFilter(FLAG_turbo_filter);
|
| -
|
| - // If this is OSR request, OSR must be enabled by Turbofan.
|
| - bool passes_osr_test = FLAG_turbo_osr || !info()->is_osr();
|
| -
|
| - if ((is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable ||
|
| - passes_turbo_filter) &&
|
| - passes_osr_test) {
|
| - // Use TurboFan for the compilation.
|
| - if (FLAG_trace_opt) {
|
| - OFStream os(stdout);
|
| - os << "[compiling method " << Brief(*info()->closure())
|
| - << " using TurboFan";
|
| - if (info()->is_osr()) os << " OSR";
|
| - os << "]" << std::endl;
|
| - }
|
| -
|
| - if (info()->shared_info()->asm_function()) {
|
| - if (info()->osr_frame()) info()->MarkAsFrameSpecializing();
|
| - info()->MarkAsFunctionContextSpecializing();
|
| - } else {
|
| - if (!FLAG_always_opt) {
|
| - info()->MarkAsBailoutOnUninitialized();
|
| - }
|
| - if (FLAG_native_context_specialization) {
|
| - info()->MarkAsNativeContextSpecializing();
|
| - info()->MarkAsTypingEnabled();
|
| - }
|
| - }
|
| - if (!info()->shared_info()->asm_function() ||
|
| - FLAG_turbo_asm_deoptimization) {
|
| - info()->MarkAsDeoptimizationEnabled();
|
| - }
|
| -
|
| - Timer t(this, &time_taken_to_create_graph_);
|
| - compiler::Pipeline pipeline(info());
|
| - pipeline.GenerateCode();
|
| - if (!info()->code().is_null()) {
|
| - return SetLastStatus(SUCCEEDED);
|
| - }
|
| - }
|
| -
|
| - if (!isolate()->use_crankshaft() || dont_crankshaft) {
|
| - // Crankshaft is entirely disabled.
|
| - return SetLastStatus(FAILED);
|
| - }
|
| -
|
| - Scope* scope = info()->scope();
|
| - if (LUnallocated::TooManyParameters(scope->num_parameters())) {
|
| - // Crankshaft would require too many Lithium operands.
|
| - return AbortOptimization(kTooManyParameters);
|
| - }
|
| -
|
| - if (info()->is_osr() &&
|
| - LUnallocated::TooManyParametersOrStackSlots(scope->num_parameters(),
|
| - scope->num_stack_slots())) {
|
| - // Crankshaft would require too many Lithium operands.
|
| - return AbortOptimization(kTooManyParametersLocals);
|
| - }
|
| -
|
| - if (FLAG_trace_opt) {
|
| - OFStream os(stdout);
|
| - os << "[compiling method " << Brief(*info()->closure())
|
| - << " using Crankshaft";
|
| - if (info()->is_osr()) os << " OSR";
|
| - os << "]" << std::endl;
|
| - }
|
| -
|
| - if (FLAG_trace_hydrogen) {
|
| - isolate()->GetHTracer()->TraceCompilation(info());
|
| - }
|
| -
|
| - // Type-check the function.
|
| - AstTyper(info()->isolate(), info()->zone(), info()->closure(),
|
| - info()->scope(), info()->osr_ast_id(), info()->literal())
|
| - .Run();
|
| -
|
| - // Optimization could have been disabled by the parser. Note that this check
|
| - // is only needed because the Hydrogen graph builder is missing some bailouts.
|
| - if (info()->shared_info()->optimization_disabled()) {
|
| - return AbortOptimization(
|
| - info()->shared_info()->disable_optimization_reason());
|
| - }
|
| -
|
| - HOptimizedGraphBuilder* graph_builder =
|
| - (info()->is_tracking_positions() || FLAG_trace_ic)
|
| - ? new (info()->zone()) HOptimizedGraphBuilderWithPositions(info())
|
| - : new (info()->zone()) HOptimizedGraphBuilder(info());
|
| -
|
| - Timer t(this, &time_taken_to_create_graph_);
|
| - graph_ = graph_builder->CreateGraph();
|
| -
|
| - if (isolate()->has_pending_exception()) {
|
| - return SetLastStatus(FAILED);
|
| - }
|
| -
|
| - if (graph_ == NULL) return SetLastStatus(BAILED_OUT);
|
| -
|
| - if (info()->dependencies()->HasAborted()) {
|
| - // Dependency has changed during graph creation. Let's try again later.
|
| - return RetryOptimization(kBailedOutDueToDependencyChange);
|
| - }
|
| -
|
| - return SetLastStatus(SUCCEEDED);
|
| + // Delegate to the underlying implementation.
|
| + DCHECK_EQ(SUCCEEDED, last_status());
|
| + ScopedTimer t(&time_taken_to_create_graph_);
|
| + return SetLastStatus(CreateGraphImpl());
|
| }
|
|
|
|
|
| @@ -522,24 +371,21 @@ OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() {
|
| DisallowHandleDereference no_deref;
|
| DisallowCodeDependencyChange no_dependency_change;
|
|
|
| - DCHECK(last_status() == SUCCEEDED);
|
| - // TODO(turbofan): Currently everything is done in the first phase.
|
| - if (!info()->code().is_null()) {
|
| - return last_status();
|
| - }
|
| -
|
| - Timer t(this, &time_taken_to_optimize_);
|
| - DCHECK(graph_ != NULL);
|
| - BailoutReason bailout_reason = kNoReason;
|
| + // Delegate to the underlying implementation.
|
| + DCHECK_EQ(SUCCEEDED, last_status());
|
| + ScopedTimer t(&time_taken_to_optimize_);
|
| + return SetLastStatus(OptimizeGraphImpl());
|
| +}
|
|
|
| - if (graph_->Optimize(&bailout_reason)) {
|
| - chunk_ = LChunk::NewChunk(graph_);
|
| - if (chunk_ != NULL) return SetLastStatus(SUCCEEDED);
|
| - } else if (bailout_reason != kNoReason) {
|
| - info_->AbortOptimization(bailout_reason);
|
| - }
|
| +OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() {
|
| + DisallowCodeDependencyChange no_dependency_change;
|
| + DisallowJavascriptExecution no_js(isolate());
|
| + DCHECK(!info()->dependencies()->HasAborted());
|
|
|
| - return SetLastStatus(BAILED_OUT);
|
| + // Delegate to the underlying implementation.
|
| + DCHECK_EQ(SUCCEEDED, last_status());
|
| + ScopedTimer t(&time_taken_to_codegen_);
|
| + return SetLastStatus(GenerateCodeImpl());
|
| }
|
|
|
|
|
| @@ -554,8 +400,10 @@ void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object,
|
| heap->AddWeakObjectToCodeDependency(object, dep);
|
| }
|
|
|
| +} // namespace
|
|
|
| -void RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
|
| +void OptimizedCompileJob::RegisterWeakObjectsInOptimizedCode(
|
| + Handle<Code> code) {
|
| // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies.
|
| Isolate* const isolate = code->GetIsolate();
|
| DCHECK(code->is_optimized_code());
|
| @@ -595,51 +443,6 @@ void RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
|
| code->set_can_have_weak_objects(true);
|
| }
|
|
|
| -} // namespace
|
| -
|
| -
|
| -OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() {
|
| - DCHECK(last_status() == SUCCEEDED);
|
| - // TODO(turbofan): Currently everything is done in the first phase.
|
| - if (!info()->code().is_null()) {
|
| - info()->dependencies()->Commit(info()->code());
|
| - if (info()->is_deoptimization_enabled()) {
|
| - info()->parse_info()->context()->native_context()->AddOptimizedCode(
|
| - *info()->code());
|
| - RegisterWeakObjectsInOptimizedCode(info()->code());
|
| - }
|
| - RecordOptimizationStats();
|
| - return last_status();
|
| - }
|
| -
|
| - DCHECK(!info()->dependencies()->HasAborted());
|
| - DisallowCodeDependencyChange no_dependency_change;
|
| - DisallowJavascriptExecution no_js(isolate());
|
| - { // Scope for timer.
|
| - Timer timer(this, &time_taken_to_codegen_);
|
| - DCHECK(chunk_ != NULL);
|
| - DCHECK(graph_ != NULL);
|
| - // Deferred handles reference objects that were accessible during
|
| - // graph creation. To make sure that we don't encounter inconsistencies
|
| - // between graph creation and code generation, we disallow accessing
|
| - // objects through deferred handles during the latter, with exceptions.
|
| - DisallowDeferredHandleDereference no_deferred_handle_deref;
|
| - Handle<Code> optimized_code = chunk_->Codegen();
|
| - if (optimized_code.is_null()) {
|
| - if (info()->bailout_reason() == kNoReason) {
|
| - return AbortOptimization(kCodeGenerationFailed);
|
| - }
|
| - return SetLastStatus(BAILED_OUT);
|
| - }
|
| - RegisterWeakObjectsInOptimizedCode(optimized_code);
|
| - info()->SetCode(optimized_code);
|
| - }
|
| - RecordOptimizationStats();
|
| - // Add to the weak list of optimized code objects.
|
| - info()->context()->native_context()->AddOptimizedCode(*info()->code());
|
| - return SetLastStatus(SUCCEEDED);
|
| -}
|
| -
|
|
|
| void OptimizedCompileJob::RecordOptimizationStats() {
|
| Handle<JSFunction> function = info()->closure();
|
| @@ -937,6 +740,34 @@ bool Renumber(ParseInfo* parse_info) {
|
| return true;
|
| }
|
|
|
| +bool UseTurboFan(CompilationInfo* info) {
|
| + bool optimization_disabled = info->shared_info()->optimization_disabled();
|
| + bool dont_crankshaft = info->shared_info()->dont_crankshaft();
|
| +
|
| + // Check the enabling conditions for Turbofan.
|
| + // 1. "use asm" code.
|
| + bool is_turbofanable_asm = FLAG_turbo_asm &&
|
| + info->shared_info()->asm_function() &&
|
| + !optimization_disabled;
|
| +
|
| + // 2. Fallback for features unsupported by Crankshaft.
|
| + bool is_unsupported_by_crankshaft_but_turbofanable =
|
| + dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 &&
|
| + !optimization_disabled;
|
| +
|
| + // 3. Explicitly enabled by the command-line filter.
|
| + bool passes_turbo_filter =
|
| + info->shared_info()->PassesFilter(FLAG_turbo_filter);
|
| +
|
| + // If this is OSR request, OSR must be enabled by Turbofan.
|
| + bool passes_osr_test = FLAG_turbo_osr || !info->is_osr();
|
| +
|
| + return (is_turbofanable_asm ||
|
| + is_unsupported_by_crankshaft_but_turbofanable ||
|
| + passes_turbo_filter) &&
|
| + passes_osr_test;
|
| +}
|
| +
|
| bool GetOptimizedCodeNow(CompilationInfo* info) {
|
| Isolate* isolate = info->isolate();
|
| CanonicalHandleScope canonical(isolate);
|
| @@ -948,10 +779,12 @@ bool GetOptimizedCodeNow(CompilationInfo* info) {
|
| TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
|
| TRACE_EVENT0("v8", "V8.RecompileSynchronous");
|
|
|
| - OptimizedCompileJob job(info);
|
| - if (job.CreateGraph() != OptimizedCompileJob::SUCCEEDED ||
|
| - job.OptimizeGraph() != OptimizedCompileJob::SUCCEEDED ||
|
| - job.GenerateCode() != OptimizedCompileJob::SUCCEEDED) {
|
| + OptimizedCompileJob* job = UseTurboFan(info)
|
| + ? compiler::Pipeline::NewCompilationJob(info)
|
| + : new (info->zone()) HCompilationJob(info);
|
| + if (job->CreateGraph() != OptimizedCompileJob::SUCCEEDED ||
|
| + job->OptimizeGraph() != OptimizedCompileJob::SUCCEEDED ||
|
| + job->GenerateCode() != OptimizedCompileJob::SUCCEEDED) {
|
| if (FLAG_trace_opt) {
|
| PrintF("[aborted optimizing ");
|
| info->closure()->ShortPrint();
|
| @@ -961,6 +794,7 @@ bool GetOptimizedCodeNow(CompilationInfo* info) {
|
| }
|
|
|
| // Success!
|
| + job->RecordOptimizationStats();
|
| DCHECK(!isolate->has_pending_exception());
|
| InsertCodeIntoOptimizedCodeMap(info);
|
| RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info,
|
| @@ -993,7 +827,9 @@ bool GetOptimizedCodeLater(CompilationInfo* info) {
|
| TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
|
| TRACE_EVENT0("v8", "V8.RecompileSynchronous");
|
|
|
| - OptimizedCompileJob* job = new (info->zone()) OptimizedCompileJob(info);
|
| + OptimizedCompileJob* job = UseTurboFan(info)
|
| + ? compiler::Pipeline::NewCompilationJob(info)
|
| + : new (info->zone()) HCompilationJob(info);
|
| OptimizedCompileJob::Status status = job->CreateGraph();
|
| if (status != OptimizedCompileJob::SUCCEEDED) return false;
|
| isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
|
| @@ -1843,6 +1679,7 @@ void Compiler::FinalizeOptimizedCompileJob(OptimizedCompileJob* job) {
|
| } else if (info->dependencies()->HasAborted()) {
|
| job->RetryOptimization(kBailedOutDueToDependencyChange);
|
| } else if (job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) {
|
| + job->RecordOptimizationStats();
|
| RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info.get(), shared);
|
| if (shared->SearchOptimizedCodeMap(info->context()->native_context(),
|
| info->osr_ast_id()).code == nullptr) {
|
|
|