From 1fb6a7e697e8bc5b4af51647553741f966e00cdc Mon Sep 17 00:00:00 2001 From: rmcilroy Date: Tue, 16 Aug 2016 07:45:08 -0700 Subject: [PATCH] [Interpreter] Introduce InterpreterCompilationJob Adds InterpreterCompilationJob as a sub-class of CompilationJob, to enable off-thread bytecode generation. Currently only used in Interpreter::MakeBytecode. As part of this change, CompilationJob is modified to make it less specific to optimized compilation, renaming the phases as follows: - CreateGraph -> PrepareJob - OptimizeGraph -> ExecuteJob - GenerateCode -> FinalizeJob RegisterWeakObjectsInOptimizedCode is also moved out of CompilationJob and instead becomes a static function on Compiler. BUG=v8:5203 Review-Url: https://codereview.chromium.org/2240463002 Cr-Commit-Position: refs/heads/master@{#38662} --- .../optimizing-compile-dispatcher.cc | 2 +- src/compiler.cc | 114 +++++++++--------- src/compiler.h | 86 ++++++++----- src/compiler/pipeline.cc | 29 ++--- src/compiler/wasm-compiler.cc | 8 +- src/crankshaft/hydrogen.cc | 8 +- src/crankshaft/hydrogen.h | 6 +- src/crankshaft/lithium-codegen.h | 2 - src/interpreter/bytecode-generator.cc | 10 +- src/interpreter/bytecode-generator.h | 6 +- src/interpreter/interpreter.cc | 68 ++++++++--- test/cctest/wasm/wasm-run-utils.h | 4 +- 12 files changed, 199 insertions(+), 144 deletions(-) diff --git a/src/compiler-dispatcher/optimizing-compile-dispatcher.cc b/src/compiler-dispatcher/optimizing-compile-dispatcher.cc index c7b2f31b46..be81047976 100644 --- a/src/compiler-dispatcher/optimizing-compile-dispatcher.cc +++ b/src/compiler-dispatcher/optimizing-compile-dispatcher.cc @@ -107,7 +107,7 @@ void OptimizingCompileDispatcher::CompileNext(CompilationJob* job) { if (!job) return; // The function may have already been optimized by OSR. Simply continue. - CompilationJob::Status status = job->OptimizeGraph(); + CompilationJob::Status status = job->ExecuteJob(); USE(status); // Prevent an unused-variable error. // The function may have already been optimized by OSR. Simply continue. diff --git a/src/compiler.cc b/src/compiler.cc index 54ea359c65..9e5e3916c9 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -240,11 +240,11 @@ bool CompilationInfo::ExpectsJSReceiverAsReceiver() { // ---------------------------------------------------------------------------- // Implementation of CompilationJob -CompilationJob::Status CompilationJob::CreateGraph() { +CompilationJob::Status CompilationJob::PrepareJob() { + DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id())); DisallowJavascriptExecution no_js(isolate()); - DCHECK(info()->IsOptimizing()); - if (FLAG_trace_opt) { + if (FLAG_trace_opt && info()->IsOptimizing()) { OFStream os(stdout); os << "[compiling method " << Brief(*info()->closure()) << " using " << compiler_name_; @@ -253,34 +253,69 @@ CompilationJob::Status CompilationJob::CreateGraph() { } // Delegate to the underlying implementation. - DCHECK_EQ(SUCCEEDED, last_status()); - ScopedTimer t(&time_taken_to_create_graph_); - return SetLastStatus(CreateGraphImpl()); + DCHECK(state() == State::kReadyToPrepare); + ScopedTimer t(&time_taken_to_prepare_); + return UpdateState(PrepareJobImpl(), State::kReadyToExecute); } -CompilationJob::Status CompilationJob::OptimizeGraph() { +CompilationJob::Status CompilationJob::ExecuteJob() { DisallowHeapAllocation no_allocation; DisallowHandleAllocation no_handles; DisallowHandleDereference no_deref; DisallowCodeDependencyChange no_dependency_change; // Delegate to the underlying implementation. - DCHECK_EQ(SUCCEEDED, last_status()); - ScopedTimer t(&time_taken_to_optimize_); - return SetLastStatus(OptimizeGraphImpl()); + DCHECK(state() == State::kReadyToExecute); + ScopedTimer t(&time_taken_to_execute_); + return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize); } -CompilationJob::Status CompilationJob::GenerateCode() { +CompilationJob::Status CompilationJob::FinalizeJob() { + DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id())); DisallowCodeDependencyChange no_dependency_change; DisallowJavascriptExecution no_js(isolate()); DCHECK(!info()->dependencies()->HasAborted()); // Delegate to the underlying implementation. - DCHECK_EQ(SUCCEEDED, last_status()); - ScopedTimer t(&time_taken_to_codegen_); - return SetLastStatus(GenerateCodeImpl()); + DCHECK(state() == State::kReadyToFinalize); + ScopedTimer t(&time_taken_to_finalize_); + return UpdateState(FinalizeJobImpl(), State::kSucceeded); } +void CompilationJob::RecordOptimizationStats() { + DCHECK(info()->IsOptimizing()); + Handle function = info()->closure(); + if (!function->IsOptimized()) { + // Concurrent recompilation and OSR may race. Increment only once. + int opt_count = function->shared()->opt_count(); + function->shared()->set_opt_count(opt_count + 1); + } + double ms_creategraph = time_taken_to_prepare_.InMillisecondsF(); + double ms_optimize = time_taken_to_execute_.InMillisecondsF(); + double ms_codegen = time_taken_to_finalize_.InMillisecondsF(); + if (FLAG_trace_opt) { + PrintF("[optimizing "); + function->ShortPrint(); + PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize, + ms_codegen); + } + if (FLAG_trace_opt_stats) { + static double compilation_time = 0.0; + static int compiled_functions = 0; + static int code_size = 0; + + compilation_time += (ms_creategraph + ms_optimize + ms_codegen); + compiled_functions++; + code_size += function->shared()->SourceSize(); + PrintF("Compiled: %d functions with %d byte source size in %fms.\n", + compiled_functions, code_size, compilation_time); + } + if (FLAG_hydrogen_stats) { + isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_prepare_, + time_taken_to_execute_, + time_taken_to_finalize_); + } +} namespace { @@ -300,6 +335,7 @@ void AddWeakObjectToCodeDependency(Isolate* isolate, Handle object, } // namespace +// static void CompilationJob::RegisterWeakObjectsInOptimizedCode(Handle code) { // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies. Isolate* const isolate = code->GetIsolate(); @@ -340,42 +376,6 @@ void CompilationJob::RegisterWeakObjectsInOptimizedCode(Handle code) { code->set_can_have_weak_objects(true); } -void CompilationJob::RecordOptimizationStats() { - Handle function = info()->closure(); - if (!function->IsOptimized()) { - // Concurrent recompilation and OSR may race. Increment only once. - int opt_count = function->shared()->opt_count(); - function->shared()->set_opt_count(opt_count + 1); - } - double ms_creategraph = time_taken_to_create_graph_.InMillisecondsF(); - double ms_optimize = time_taken_to_optimize_.InMillisecondsF(); - double ms_codegen = time_taken_to_codegen_.InMillisecondsF(); - if (FLAG_trace_opt) { - PrintF("[optimizing "); - function->ShortPrint(); - PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize, - ms_codegen); - } - if (FLAG_trace_opt_stats) { - static double compilation_time = 0.0; - static int compiled_functions = 0; - static int code_size = 0; - - compilation_time += (ms_creategraph + ms_optimize + ms_codegen); - compiled_functions++; - code_size += function->shared()->SourceSize(); - PrintF("Compiled: %d functions with %d byte source size in %fms.\n", - compiled_functions, - code_size, - compilation_time); - } - if (FLAG_hydrogen_stats) { - isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_, - time_taken_to_optimize_, - time_taken_to_codegen_); - } -} - // ---------------------------------------------------------------------------- // Local helper methods that make up the compilation pipeline. @@ -672,9 +672,9 @@ bool GetOptimizedCodeNow(CompilationJob* job) { TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED( isolate, &tracing::TraceEventStatsTable::RecompileSynchronous); - if (job->CreateGraph() != CompilationJob::SUCCEEDED || - job->OptimizeGraph() != CompilationJob::SUCCEEDED || - job->GenerateCode() != CompilationJob::SUCCEEDED) { + if (job->PrepareJob() != CompilationJob::SUCCEEDED || + job->ExecuteJob() != CompilationJob::SUCCEEDED || + job->FinalizeJob() != CompilationJob::SUCCEEDED) { if (FLAG_trace_opt) { PrintF("[aborted optimizing "); info->closure()->ShortPrint(); @@ -735,7 +735,7 @@ bool GetOptimizedCodeLater(CompilationJob* job) { TRACE_EVENT_RUNTIME_CALL_STATS_TRACING_SCOPED( isolate, &tracing::TraceEventStatsTable::RecompileSynchronous); - if (job->CreateGraph() != CompilationJob::SUCCEEDED) return false; + if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false; isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); if (FLAG_trace_concurrent_recompilation) { @@ -1907,12 +1907,12 @@ void Compiler::FinalizeCompilationJob(CompilationJob* raw_job) { // Except when OSR already disabled optimization for some reason. // 3) The code may have already been invalidated due to dependency change. // 4) Code generation may have failed. - if (job->last_status() == CompilationJob::SUCCEEDED) { + if (job->state() == CompilationJob::State::kReadyToFinalize) { if (shared->optimization_disabled()) { job->RetryOptimization(kOptimizationDisabled); } else if (info->dependencies()->HasAborted()) { job->RetryOptimization(kBailedOutDueToDependencyChange); - } else if (job->GenerateCode() == CompilationJob::SUCCEEDED) { + } else if (job->FinalizeJob() == CompilationJob::SUCCEEDED) { job->RecordOptimizationStats(); RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info); if (shared->SearchOptimizedCodeMap(info->context()->native_context(), @@ -1929,7 +1929,7 @@ void Compiler::FinalizeCompilationJob(CompilationJob* raw_job) { } } - DCHECK(job->last_status() != CompilationJob::SUCCEEDED); + DCHECK(job->state() == CompilationJob::State::kFailed); if (FLAG_trace_opt) { PrintF("[aborted optimizing "); info->closure()->ShortPrint(); diff --git a/src/compiler.h b/src/compiler.h index b8b3a0bfb4..fcbbd4e389 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -537,62 +537,86 @@ class CompilationInfo final { // 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) CreateGraph: Runs on main thread. No major limitations. -// 2) OptimizeGraph: Runs concurrently. No heap allocation or handle derefs. -// 3) GenerateCode: Runs on main thread. No dependency changes. +// 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. Apart from their return -// value, the status of the phase last run can be checked using {last_status()} -// as well. When failing we distinguish between the following levels: -// a) AbortOptimization: Persistent failure, disable future optimization. -// b) RetryOptimzation: Transient failure, try again next time. +// 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 CompilationJob(CompilationInfo* info, const char* compiler_name) - : info_(info), compiler_name_(compiler_name), last_status_(SUCCEEDED) {} + enum Status { SUCCEEDED, FAILED }; + enum class State { + kReadyToPrepare, + kReadyToExecute, + kReadyToFinalize, + kSucceeded, + kFailed, + }; + + explicit CompilationJob(CompilationInfo* info, const char* compiler_name, + State initial_state = State::kReadyToPrepare) + : info_(info), compiler_name_(compiler_name), state_(initial_state) {} virtual ~CompilationJob() {} - enum Status { FAILED, SUCCEEDED }; + // Prepare the compile job. Must be called on the main thread. + MUST_USE_RESULT Status PrepareJob(); - MUST_USE_RESULT Status CreateGraph(); - MUST_USE_RESULT Status OptimizeGraph(); - MUST_USE_RESULT Status GenerateCode(); + // Executes the compile job. Can be called off the main thread. + MUST_USE_RESULT Status ExecuteJob(); - Status last_status() const { return last_status_; } - CompilationInfo* info() const { return info_; } - Isolate* isolate() const { return info()->isolate(); } + // 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(FAILED); + 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(FAILED); + state_ = State::kFailed; + return FAILED; } void RecordOptimizationStats(); - protected: - void RegisterWeakObjectsInOptimizedCode(Handle code); + // Registers weak object to optimized code dependencies. + // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies. + static void RegisterWeakObjectsInOptimizedCode(Handle code); + State state() const { return state_; } + CompilationInfo* info() const { return info_; } + Isolate* isolate() const { return info()->isolate(); } + + protected: // Overridden by the actual implementation. - virtual Status CreateGraphImpl() = 0; - virtual Status OptimizeGraphImpl() = 0; - virtual Status GenerateCodeImpl() = 0; + virtual Status PrepareJobImpl() = 0; + virtual Status ExecuteJobImpl() = 0; + virtual Status FinalizeJobImpl() = 0; private: CompilationInfo* info_; - base::TimeDelta time_taken_to_create_graph_; - base::TimeDelta time_taken_to_optimize_; - base::TimeDelta time_taken_to_codegen_; + base::TimeDelta time_taken_to_prepare_; + base::TimeDelta time_taken_to_execute_; + base::TimeDelta time_taken_to_finalize_; const char* compiler_name_; - Status last_status_; + State state_; - MUST_USE_RESULT Status SetLastStatus(Status status) { - last_status_ = status; - return last_status_; + MUST_USE_RESULT Status UpdateState(Status status, State next_state) { + if (status == SUCCEEDED) { + state_ = next_state; + } else { + state_ = State::kFailed; + } + return status; } }; diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc index 20a0db9813..ed4e19bf13 100644 --- a/src/compiler/pipeline.cc +++ b/src/compiler/pipeline.cc @@ -573,9 +573,9 @@ class PipelineCompilationJob final : public CompilationJob { linkage_(nullptr) {} protected: - Status CreateGraphImpl() final; - Status OptimizeGraphImpl() final; - Status GenerateCodeImpl() final; + Status PrepareJobImpl() final; + Status ExecuteJobImpl() final; + Status FinalizeJobImpl() final; private: Zone zone_; @@ -590,7 +590,7 @@ class PipelineCompilationJob final : public CompilationJob { DISALLOW_COPY_AND_ASSIGN(PipelineCompilationJob); }; -PipelineCompilationJob::Status PipelineCompilationJob::CreateGraphImpl() { +PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl() { if (info()->shared_info()->asm_function()) { if (info()->osr_frame()) info()->MarkAsFrameSpecializing(); info()->MarkAsFunctionContextSpecializing(); @@ -633,12 +633,12 @@ PipelineCompilationJob::Status PipelineCompilationJob::CreateGraphImpl() { return SUCCEEDED; } -PipelineCompilationJob::Status PipelineCompilationJob::OptimizeGraphImpl() { +PipelineCompilationJob::Status PipelineCompilationJob::ExecuteJobImpl() { if (!pipeline_.OptimizeGraph(linkage_)) return FAILED; return SUCCEEDED; } -PipelineCompilationJob::Status PipelineCompilationJob::GenerateCodeImpl() { +PipelineCompilationJob::Status PipelineCompilationJob::FinalizeJobImpl() { Handle code = pipeline_.GenerateCode(linkage_); if (code.is_null()) { if (info()->bailout_reason() == kNoReason) { @@ -650,7 +650,7 @@ PipelineCompilationJob::Status PipelineCompilationJob::GenerateCodeImpl() { info()->SetCode(code); if (info()->is_deoptimization_enabled()) { info()->context()->native_context()->AddOptimizedCode(*code); - RegisterWeakObjectsInOptimizedCode(code); + CompilationJob::RegisterWeakObjectsInOptimizedCode(code); } return SUCCEEDED; } @@ -660,16 +660,16 @@ class PipelineWasmCompilationJob final : public CompilationJob { explicit PipelineWasmCompilationJob(CompilationInfo* info, Graph* graph, CallDescriptor* descriptor, SourcePositionTable* source_positions) - : CompilationJob(info, "TurboFan"), + : CompilationJob(info, "TurboFan", State::kReadyToExecute), zone_pool_(info->isolate()->allocator()), data_(&zone_pool_, info, graph, source_positions), pipeline_(&data_), linkage_(descriptor) {} protected: - Status CreateGraphImpl() final; - Status OptimizeGraphImpl() final; - Status GenerateCodeImpl() final; + Status PrepareJobImpl() final; + Status ExecuteJobImpl() final; + Status FinalizeJobImpl() final; private: ZonePool zone_pool_; @@ -679,12 +679,13 @@ class PipelineWasmCompilationJob final : public CompilationJob { }; PipelineWasmCompilationJob::Status -PipelineWasmCompilationJob::CreateGraphImpl() { +PipelineWasmCompilationJob::PrepareJobImpl() { + UNREACHABLE(); // Prepare should always be skipped for WasmCompilationJob. return SUCCEEDED; } PipelineWasmCompilationJob::Status -PipelineWasmCompilationJob::OptimizeGraphImpl() { +PipelineWasmCompilationJob::ExecuteJobImpl() { if (FLAG_trace_turbo) { TurboJsonFile json_of(info(), std::ios_base::trunc); json_of << "{\"function\":\"" << info()->GetDebugName().get() @@ -698,7 +699,7 @@ PipelineWasmCompilationJob::OptimizeGraphImpl() { } PipelineWasmCompilationJob::Status -PipelineWasmCompilationJob::GenerateCodeImpl() { +PipelineWasmCompilationJob::FinalizeJobImpl() { pipeline_.GenerateCode(&linkage_); return SUCCEEDED; } diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc index b457efec4e..41da92641b 100644 --- a/src/compiler/wasm-compiler.cc +++ b/src/compiler/wasm-compiler.cc @@ -3165,11 +3165,7 @@ void WasmCompilationUnit::ExecuteCompilation() { } job_.reset(Pipeline::NewWasmCompilationJob(&info_, jsgraph_->graph(), descriptor, source_positions)); - - // The function name {OptimizeGraph()} is misleading but necessary because we - // want to use the CompilationJob interface. A better name would be - // ScheduleGraphAndSelectInstructions. - ok_ = job_->OptimizeGraph() == CompilationJob::SUCCEEDED; + ok_ = job_->ExecuteJob() == CompilationJob::SUCCEEDED; // TODO(bradnelson): Improve histogram handling of size_t. // TODO(ahaas): The counters are not thread-safe at the moment. // isolate_->counters()->wasm_compile_function_peak_memory_bytes() @@ -3201,7 +3197,7 @@ Handle WasmCompilationUnit::FinishCompilation() { return Handle::null(); } - if (job_->GenerateCode() != CompilationJob::SUCCEEDED) { + if (job_->FinalizeJob() != CompilationJob::SUCCEEDED) { return Handle::null(); } base::ElapsedTimer compile_timer; diff --git a/src/crankshaft/hydrogen.cc b/src/crankshaft/hydrogen.cc index ded0e99d91..f2cf5098a7 100644 --- a/src/crankshaft/hydrogen.cc +++ b/src/crankshaft/hydrogen.cc @@ -114,7 +114,7 @@ class HOptimizedGraphBuilderWithPositions : public HOptimizedGraphBuilder { #undef DEF_VISIT }; -HCompilationJob::Status HCompilationJob::CreateGraphImpl() { +HCompilationJob::Status HCompilationJob::PrepareJobImpl() { if (!isolate()->use_crankshaft() || info()->shared_info()->dont_crankshaft()) { // Crankshaft is entirely disabled. @@ -203,7 +203,7 @@ HCompilationJob::Status HCompilationJob::CreateGraphImpl() { return SUCCEEDED; } -HCompilationJob::Status HCompilationJob::OptimizeGraphImpl() { +HCompilationJob::Status HCompilationJob::ExecuteJobImpl() { DCHECK(graph_ != NULL); BailoutReason bailout_reason = kNoReason; @@ -217,7 +217,7 @@ HCompilationJob::Status HCompilationJob::OptimizeGraphImpl() { return FAILED; } -HCompilationJob::Status HCompilationJob::GenerateCodeImpl() { +HCompilationJob::Status HCompilationJob::FinalizeJobImpl() { DCHECK(chunk_ != NULL); DCHECK(graph_ != NULL); { @@ -233,7 +233,7 @@ HCompilationJob::Status HCompilationJob::GenerateCodeImpl() { } return FAILED; } - RegisterWeakObjectsInOptimizedCode(optimized_code); + CompilationJob::RegisterWeakObjectsInOptimizedCode(optimized_code); info()->SetCode(optimized_code); } // Add to the weak list of optimized code objects. diff --git a/src/crankshaft/hydrogen.h b/src/crankshaft/hydrogen.h index 3ac2af6f60..492fa9522b 100644 --- a/src/crankshaft/hydrogen.h +++ b/src/crankshaft/hydrogen.h @@ -44,9 +44,9 @@ class HCompilationJob final : public CompilationJob { chunk_(nullptr) {} protected: - virtual Status CreateGraphImpl(); - virtual Status OptimizeGraphImpl(); - virtual Status GenerateCodeImpl(); + virtual Status PrepareJobImpl(); + virtual Status ExecuteJobImpl(); + virtual Status FinalizeJobImpl(); private: Zone zone_; diff --git a/src/crankshaft/lithium-codegen.h b/src/crankshaft/lithium-codegen.h index c666e1b0af..fbf96924ee 100644 --- a/src/crankshaft/lithium-codegen.h +++ b/src/crankshaft/lithium-codegen.h @@ -54,8 +54,6 @@ class LCodeGenBase BASE_EMBEDDED { int GetNextEmittedBlock() const; - void RegisterWeakObjectsInOptimizedCode(Handle code); - void WriteTranslationFrame(LEnvironment* environment, Translation* translation); int DefineDeoptimizationLiteral(Handle literal); diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc index cb133c365e..b5d085cc5f 100644 --- a/src/interpreter/bytecode-generator.cc +++ b/src/interpreter/bytecode-generator.cc @@ -688,20 +688,16 @@ BytecodeGenerator::BytecodeGenerator(CompilationInfo* info) InitializeAstVisitor(isolate()->stack_guard()->real_climit()); } -Handle BytecodeGenerator::MakeBytecode() { +Handle BytecodeGenerator::FinalizeBytecode() { // Create an inner HandleScope to avoid unnecessarily canonicalizing handles // created as part of bytecode finalization. HandleScope scope(isolate()); - - GenerateBytecode(); - FinalizeBytecode(); - + AllocateDeferredConstants(); if (HasStackOverflow()) return Handle(); - return scope.CloseAndEscape(builder()->ToBytecodeArray()); } -void BytecodeGenerator::FinalizeBytecode() { +void BytecodeGenerator::AllocateDeferredConstants() { // Build global declaration pair arrays. for (GlobalDeclarationsBuilder* globals_builder : global_declarations_) { Handle declarations = diff --git a/src/interpreter/bytecode-generator.h b/src/interpreter/bytecode-generator.h index 573ad673ef..3b6b2894ab 100644 --- a/src/interpreter/bytecode-generator.h +++ b/src/interpreter/bytecode-generator.h @@ -24,7 +24,8 @@ class BytecodeGenerator final : public AstVisitor { public: explicit BytecodeGenerator(CompilationInfo* info); - Handle MakeBytecode(); + void GenerateBytecode(); + Handle FinalizeBytecode(); #define DECLARE_VISIT(type) void Visit##type(type* node); AST_NODE_LIST(DECLARE_VISIT) @@ -52,9 +53,8 @@ class BytecodeGenerator final : public AstVisitor { enum class TestFallthrough { kThen, kElse, kNone }; - void GenerateBytecode(); void GenerateBytecodeBody(); - void FinalizeBytecode(); + void AllocateDeferredConstants(); DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc index 761199766e..6be5fae9c9 100644 --- a/src/interpreter/interpreter.cc +++ b/src/interpreter/interpreter.cc @@ -30,6 +30,23 @@ typedef InterpreterAssembler::Arg Arg; #define __ assembler-> +class InterpreterCompilationJob final : public CompilationJob { + public: + explicit InterpreterCompilationJob(CompilationInfo* info); + + protected: + Status PrepareJobImpl() final; + Status ExecuteJobImpl() final; + Status FinalizeJobImpl() final; + + private: + BytecodeGenerator* generator() { return &generator_; } + + BytecodeGenerator generator_; + + DISALLOW_COPY_AND_ASSIGN(InterpreterCompilationJob); +}; + Interpreter::Interpreter(Isolate* isolate) : isolate_(isolate) { memset(dispatch_table_, 0, sizeof(dispatch_table_)); } @@ -132,6 +149,39 @@ int Interpreter::InterruptBudget() { return FLAG_interrupt_budget * kCodeSizeMultiplier; } +InterpreterCompilationJob::InterpreterCompilationJob(CompilationInfo* info) + : CompilationJob(info, "Ignition"), generator_(info) {} + +InterpreterCompilationJob::Status InterpreterCompilationJob::PrepareJobImpl() { + return SUCCEEDED; +} + +InterpreterCompilationJob::Status InterpreterCompilationJob::ExecuteJobImpl() { + generator()->GenerateBytecode(); + + if (generator()->HasStackOverflow()) { + return FAILED; + } + return SUCCEEDED; +} + +InterpreterCompilationJob::Status InterpreterCompilationJob::FinalizeJobImpl() { + Handle bytecodes = generator()->FinalizeBytecode(); + if (generator()->HasStackOverflow()) { + return FAILED; + } + + if (FLAG_print_bytecode) { + OFStream os(stdout); + bytecodes->Print(os); + os << std::flush; + } + + info()->SetBytecodeArray(bytecodes); + info()->SetCode(info()->isolate()->builtins()->InterpreterEntryTrampoline()); + return SUCCEEDED; +} + bool Interpreter::MakeBytecode(CompilationInfo* info) { RuntimeCallTimerScope runtimeTimer(info->isolate(), &RuntimeCallStats::CompileIgnition); @@ -156,20 +206,10 @@ bool Interpreter::MakeBytecode(CompilationInfo* info) { } #endif // DEBUG - BytecodeGenerator generator(info); - Handle bytecodes = generator.MakeBytecode(); - - if (generator.HasStackOverflow()) return false; - - if (FLAG_print_bytecode) { - OFStream os(stdout); - bytecodes->Print(os); - os << std::flush; - } - - info->SetBytecodeArray(bytecodes); - info->SetCode(info->isolate()->builtins()->InterpreterEntryTrampoline()); - return true; + InterpreterCompilationJob job(info); + if (job.PrepareJob() != CompilationJob::SUCCEEDED) return false; + if (job.ExecuteJob() != CompilationJob::SUCCEEDED) return false; + return job.FinalizeJob() == CompilationJob::SUCCEEDED; } bool Interpreter::IsDispatchTableInitialized() { diff --git a/test/cctest/wasm/wasm-run-utils.h b/test/cctest/wasm/wasm-run-utils.h index a9f70deadf..0a11fedfd1 100644 --- a/test/cctest/wasm/wasm-run-utils.h +++ b/test/cctest/wasm/wasm-run-utils.h @@ -549,8 +549,8 @@ class WasmFunctionCompiler : public HandleAndZoneScope, Code::ComputeFlags(Code::WASM_FUNCTION)); std::unique_ptr job(Pipeline::NewWasmCompilationJob( &info, graph(), desc, &source_position_table_)); - if (job->OptimizeGraph() != CompilationJob::SUCCEEDED || - job->GenerateCode() != CompilationJob::SUCCEEDED) + if (job->ExecuteJob() != CompilationJob::SUCCEEDED || + job->FinalizeJob() != CompilationJob::SUCCEEDED) return Handle::null(); Handle code = info.code();