Commit ff19726d authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Enable concurrent (re)compilation.

Refactor the TurboFan pipeline to allow for concurrent recompilation in
the same way that Crankshaft does it. For now we limit the concurrent
phases to scheduling, instruction selection, register allocation and
jump threading.

R=mstarzinger@chromium.org, ahaas@chromium.org, jarin@chromium.org

Review URL: https://codereview.chromium.org/1179393008

Cr-Commit-Position: refs/heads/master@{#35818}
parent 7f3954c5
...@@ -706,9 +706,9 @@ bool GetOptimizedCodeNow(CompilationInfo* info) { ...@@ -706,9 +706,9 @@ bool GetOptimizedCodeNow(CompilationInfo* info) {
TRACE_EVENT0("v8", "V8.OptimizeCode"); TRACE_EVENT0("v8", "V8.OptimizeCode");
bool use_turbofan = UseTurboFan(info); bool use_turbofan = UseTurboFan(info);
OptimizedCompileJob* job = use_turbofan base::SmartPointer<OptimizedCompileJob> job(
? compiler::Pipeline::NewCompilationJob(info) use_turbofan ? compiler::Pipeline::NewCompilationJob(info)
: new (info->zone()) HCompilationJob(info); : new HCompilationJob(info));
// Parsing is not required when optimizing from existing bytecode. // Parsing is not required when optimizing from existing bytecode.
if (!use_turbofan || !info->shared_info()->HasBytecodeArray()) { if (!use_turbofan || !info->shared_info()->HasBytecodeArray()) {
...@@ -755,9 +755,9 @@ bool GetOptimizedCodeLater(CompilationInfo* info) { ...@@ -755,9 +755,9 @@ bool GetOptimizedCodeLater(CompilationInfo* info) {
} }
bool use_turbofan = UseTurboFan(info); bool use_turbofan = UseTurboFan(info);
OptimizedCompileJob* job = use_turbofan base::SmartPointer<OptimizedCompileJob> job(
? compiler::Pipeline::NewCompilationJob(info) use_turbofan ? compiler::Pipeline::NewCompilationJob(info)
: new (info->zone()) HCompilationJob(info); : new HCompilationJob(info));
// All handles below this point will be allocated in a deferred handle scope // All handles below this point will be allocated in a deferred handle scope
// that is detached and handed off to the background thread when we return. // that is detached and handed off to the background thread when we return.
...@@ -778,7 +778,8 @@ bool GetOptimizedCodeLater(CompilationInfo* info) { ...@@ -778,7 +778,8 @@ bool GetOptimizedCodeLater(CompilationInfo* info) {
TRACE_EVENT0("v8", "V8.RecompileSynchronous"); TRACE_EVENT0("v8", "V8.RecompileSynchronous");
if (job->CreateGraph() != OptimizedCompileJob::SUCCEEDED) return false; if (job->CreateGraph() != OptimizedCompileJob::SUCCEEDED) return false;
isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); isolate->optimizing_compile_dispatcher()->QueueForOptimization(job.get());
job.Detach(); // The background recompile job owns this now.
if (FLAG_trace_concurrent_recompilation) { if (FLAG_trace_concurrent_recompilation) {
PrintF(" ** Queued "); PrintF(" ** Queued ");
...@@ -1725,7 +1726,7 @@ MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function, ...@@ -1725,7 +1726,7 @@ MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
void Compiler::FinalizeOptimizedCompileJob(OptimizedCompileJob* job) { void Compiler::FinalizeOptimizedCompileJob(OptimizedCompileJob* job) {
// Take ownership of compilation info. Deleting compilation info // Take ownership of compilation info. Deleting compilation info
// also tears down the zone and the recompile job. // also tears down the zone.
base::SmartPointer<CompilationInfo> info(job->info()); base::SmartPointer<CompilationInfo> info(job->info());
Isolate* isolate = info->isolate(); Isolate* isolate = info->isolate();
...@@ -1761,6 +1762,7 @@ void Compiler::FinalizeOptimizedCompileJob(OptimizedCompileJob* job) { ...@@ -1761,6 +1762,7 @@ void Compiler::FinalizeOptimizedCompileJob(OptimizedCompileJob* job) {
PrintF("]\n"); PrintF("]\n");
} }
info->closure()->ReplaceCode(*info->code()); info->closure()->ReplaceCode(*info->code());
delete job;
return; return;
} }
} }
...@@ -1772,6 +1774,7 @@ void Compiler::FinalizeOptimizedCompileJob(OptimizedCompileJob* job) { ...@@ -1772,6 +1774,7 @@ void Compiler::FinalizeOptimizedCompileJob(OptimizedCompileJob* job) {
PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason())); PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
} }
info->closure()->ReplaceCode(shared->code()); info->closure()->ReplaceCode(shared->code());
delete job;
} }
void Compiler::PostInstantiation(Handle<JSFunction> function, void Compiler::PostInstantiation(Handle<JSFunction> function,
......
...@@ -571,7 +571,8 @@ class CompilationInfo { ...@@ -571,7 +571,8 @@ class CompilationInfo {
// Each of the three phases can either fail, bail-out to full code generator or // Each of the three phases can either fail, bail-out to full code generator or
// succeed. Apart from their return value, the status of the phase last run can // succeed. Apart from their return value, the status of the phase last run can
// be checked using {last_status()} as well. // be checked using {last_status()} as well.
class OptimizedCompileJob: public ZoneObject { // TODO(mstarzinger): Make CompilationInfo base embedded.
class OptimizedCompileJob {
public: public:
explicit OptimizedCompileJob(CompilationInfo* info, const char* compiler_name) explicit OptimizedCompileJob(CompilationInfo* info, const char* compiler_name)
: info_(info), compiler_name_(compiler_name), last_status_(SUCCEEDED) {} : info_(info), compiler_name_(compiler_name), last_status_(SUCCEEDED) {}
......
...@@ -60,11 +60,16 @@ class IA32OperandGenerator final : public OperandGenerator { ...@@ -60,11 +60,16 @@ class IA32OperandGenerator final : public OperandGenerator {
case IrOpcode::kRelocatableInt64Constant: case IrOpcode::kRelocatableInt64Constant:
return true; return true;
case IrOpcode::kHeapConstant: { case IrOpcode::kHeapConstant: {
// TODO(bmeurer): We must not dereference handles concurrently. If we
// really have to this here, then we need to find a way to put this
// information on the HeapConstant node already.
#if 0
// Constants in new space cannot be used as immediates in V8 because // Constants in new space cannot be used as immediates in V8 because
// the GC does not scan code objects when collecting the new generation. // the GC does not scan code objects when collecting the new generation.
Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node); Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node);
Isolate* isolate = value->GetIsolate(); Isolate* isolate = value->GetIsolate();
return !isolate->heap()->InNewSpace(*value); return !isolate->heap()->InNewSpace(*value);
#endif
} }
default: default:
return false; return false;
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <string> #include <string>
#include "src/base/platform/elapsed-timer.h"
#include "src/base/smart-pointers.h"
#include "src/compilation-statistics.h" #include "src/compilation-statistics.h"
#include "src/compiler/zone-pool.h" #include "src/compiler/zone-pool.h"
...@@ -22,6 +24,7 @@ class PipelineStatistics : public Malloced { ...@@ -22,6 +24,7 @@ class PipelineStatistics : public Malloced {
~PipelineStatistics(); ~PipelineStatistics();
void BeginPhaseKind(const char* phase_kind_name); void BeginPhaseKind(const char* phase_kind_name);
void EndPhaseKind();
private: private:
size_t OuterZoneSize() { size_t OuterZoneSize() {
...@@ -43,7 +46,6 @@ class PipelineStatistics : public Malloced { ...@@ -43,7 +46,6 @@ class PipelineStatistics : public Malloced {
}; };
bool InPhaseKind() { return !phase_kind_stats_.scope_.is_empty(); } bool InPhaseKind() { return !phase_kind_stats_.scope_.is_empty(); }
void EndPhaseKind();
friend class PhaseScope; friend class PhaseScope;
bool InPhase() { return !phase_stats_.scope_.is_empty(); } bool InPhase() { return !phase_stats_.scope_.is_empty(); }
......
This diff is collapsed.
...@@ -15,7 +15,6 @@ namespace internal { ...@@ -15,7 +15,6 @@ namespace internal {
class CompilationInfo; class CompilationInfo;
class OptimizedCompileJob; class OptimizedCompileJob;
class RegisterConfiguration; class RegisterConfiguration;
class Zone;
namespace compiler { namespace compiler {
...@@ -26,11 +25,19 @@ class Linkage; ...@@ -26,11 +25,19 @@ class Linkage;
class PipelineData; class PipelineData;
class Schedule; class Schedule;
class SourcePositionTable; class SourcePositionTable;
class ZonePool;
class Pipeline { class Pipeline {
public: public:
explicit Pipeline(CompilationInfo* info) : info_(info), data_(nullptr) {} explicit Pipeline(PipelineData* data) : data_(data) {}
// Run the graph creation and initial optimization passes.
bool CreateGraph();
// Run the concurrent optimization passes.
bool OptimizeGraph(Linkage* linkage);
// Perform the actual code generation and return handle to a code object.
Handle<Code> GenerateCode(Linkage* linkage);
// Run the entire pipeline and generate a handle to a code object. // Run the entire pipeline and generate a handle to a code object.
Handle<Code> GenerateCode(); Handle<Code> GenerateCode();
...@@ -43,6 +50,10 @@ class Pipeline { ...@@ -43,6 +50,10 @@ class Pipeline {
Code::Flags flags, Code::Flags flags,
const char* debug_name); const char* debug_name);
// Run the entire pipeline and generate a handle to a code object suitable for
// testing.
static Handle<Code> GenerateCodeForTesting(CompilationInfo* info);
// Run the pipeline on a machine graph and generate code. If {schedule} is // Run the pipeline on a machine graph and generate code. If {schedule} is
// {nullptr}, then compute a new schedule for code generation. // {nullptr}, then compute a new schedule for code generation.
static Handle<Code> GenerateCodeForTesting(CompilationInfo* info, static Handle<Code> GenerateCodeForTesting(CompilationInfo* info,
...@@ -64,11 +75,13 @@ class Pipeline { ...@@ -64,11 +75,13 @@ class Pipeline {
// Returns a new compilation job for the given compilation info. // Returns a new compilation job for the given compilation info.
static OptimizedCompileJob* NewCompilationJob(CompilationInfo* info); static OptimizedCompileJob* NewCompilationJob(CompilationInfo* info);
void InitializeWasmCompilation(Zone* pipeline_zone, ZonePool* zone_pool, // Returns a new compilation job for the WebAssembly compilation info.
Graph* graph, static OptimizedCompileJob* NewWasmCompilationJob(
SourcePositionTable* source_positions); CompilationInfo* info, Graph* graph, CallDescriptor* descriptor,
bool ExecuteWasmCompilation(CallDescriptor* descriptor); SourcePositionTable* source_positions);
Handle<Code> FinalizeWasmCompilation(CallDescriptor* descriptor);
// TODO(mstarzinger, bmeurer): This shouldn't be public!
bool ScheduleAndSelectInstructions(Linkage* linkage);
private: private:
// Helpers for executing pipeline phases. // Helpers for executing pipeline phases.
...@@ -80,17 +93,16 @@ class Pipeline { ...@@ -80,17 +93,16 @@ class Pipeline {
void Run(Arg0 arg_0, Arg1 arg_1); void Run(Arg0 arg_0, Arg1 arg_1);
void BeginPhaseKind(const char* phase_kind); void BeginPhaseKind(const char* phase_kind);
void EndPhaseKind();
void RunPrintAndVerify(const char* phase, bool untyped = false); void RunPrintAndVerify(const char* phase, bool untyped = false);
Handle<Code> ScheduleAndGenerateCode(CallDescriptor* call_descriptor);
void AllocateRegisters(const RegisterConfiguration* config, void AllocateRegisters(const RegisterConfiguration* config,
CallDescriptor* descriptor, bool run_verifier); CallDescriptor* descriptor, bool run_verifier);
bool ScheduleGraph(CallDescriptor* call_descriptor);
Handle<Code> GenerateCode(CallDescriptor* descriptor); CompilationInfo* info() const;
Handle<Code> ScheduleAndGenerateCode(CallDescriptor* call_descriptor);
CompilationInfo* info() const { return info_; }
Isolate* isolate() const; Isolate* isolate() const;
CompilationInfo* const info_; PipelineData* const data_;
PipelineData* data_;
DISALLOW_COPY_AND_ASSIGN(Pipeline); DISALLOW_COPY_AND_ASSIGN(Pipeline);
}; };
......
...@@ -2968,15 +2968,12 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate, ...@@ -2968,15 +2968,12 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
} }
} }
CompilationInfo info(func_name, isolate, jsgraph->graph()->zone(), flags); CompilationInfo info(func_name, isolate, jsgraph->graph()->zone(), flags);
compiler::ZonePool::Scope pipeline_zone_scope(&zone_pool); base::SmartPointer<OptimizedCompileJob> job(Pipeline::NewWasmCompilationJob(
Pipeline pipeline(&info); &info, jsgraph->graph(), descriptor, source_positions));
pipeline.InitializeWasmCompilation(pipeline_zone_scope.zone(), &zone_pool, Handle<Code> code = Handle<Code>::null();
jsgraph->graph(), source_positions); if (job->OptimizeGraph() == OptimizedCompileJob::SUCCEEDED &&
Handle<Code> code; job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) {
if (pipeline.ExecuteWasmCompilation(descriptor)) { code = info.code();
code = pipeline.FinalizeWasmCompilation(descriptor);
} else {
code = Handle<Code>::null();
} }
buffer.Dispose(); buffer.Dispose();
......
...@@ -23,6 +23,7 @@ void DisposeOptimizedCompileJob(OptimizedCompileJob* job, ...@@ -23,6 +23,7 @@ void DisposeOptimizedCompileJob(OptimizedCompileJob* job,
Handle<JSFunction> function = info->closure(); Handle<JSFunction> function = info->closure();
function->ReplaceCode(function->shared()->code()); function->ReplaceCode(function->shared()->code());
} }
delete job;
delete info; delete info;
} }
......
...@@ -194,8 +194,7 @@ class FunctionTester : public InitializedHandleScope { ...@@ -194,8 +194,7 @@ class FunctionTester : public InitializedHandleScope {
CHECK(Compiler::Analyze(info.parse_info())); CHECK(Compiler::Analyze(info.parse_info()));
CHECK(Compiler::EnsureDeoptimizationSupport(&info)); CHECK(Compiler::EnsureDeoptimizationSupport(&info));
Pipeline pipeline(&info); Handle<Code> code = Pipeline::GenerateCodeForTesting(&info);
Handle<Code> code = pipeline.GenerateCode();
CHECK(!code.is_null()); CHECK(!code.is_null());
info.dependencies()->Commit(code); info.dependencies()->Commit(code);
info.context()->native_context()->AddOptimizedCode(*code); info.context()->native_context()->AddOptimizedCode(*code);
......
...@@ -129,8 +129,7 @@ class BytecodeGraphTester { ...@@ -129,8 +129,7 @@ class BytecodeGraphTester {
compilation_info.SetOptimizing(); compilation_info.SetOptimizing();
compilation_info.MarkAsDeoptimizationEnabled(); compilation_info.MarkAsDeoptimizationEnabled();
compilation_info.MarkAsOptimizeFromBytecode(); compilation_info.MarkAsOptimizeFromBytecode();
compiler::Pipeline pipeline(&compilation_info); Handle<Code> code = Pipeline::GenerateCodeForTesting(&compilation_info);
Handle<Code> code = pipeline.GenerateCode();
function->ReplaceCode(*code); function->ReplaceCode(*code);
return function; return function;
......
...@@ -485,18 +485,14 @@ class WasmFunctionCompiler : public HandleAndZoneScope, ...@@ -485,18 +485,14 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
} }
CompilationInfo info(debug_name_, this->isolate(), this->zone(), CompilationInfo info(debug_name_, this->isolate(), this->zone(),
Code::ComputeFlags(Code::WASM_FUNCTION)); Code::ComputeFlags(Code::WASM_FUNCTION));
compiler::ZonePool zone_pool(this->isolate()->allocator()); v8::base::SmartPointer<OptimizedCompileJob> job(
compiler::ZonePool::Scope pipeline_zone_scope(&zone_pool); Pipeline::NewWasmCompilationJob(&info, graph(), desc,
Pipeline pipeline(&info); &source_position_table_));
pipeline.InitializeWasmCompilation(this->zone(), &zone_pool, this->graph(), Handle<Code> code = Handle<Code>::null();
&source_position_table_); if (job->OptimizeGraph() == OptimizedCompileJob::SUCCEEDED &&
Handle<Code> code; job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) {
if (pipeline.ExecuteWasmCompilation(desc)) { code = info.code();
code = pipeline.FinalizeWasmCompilation(desc);
} else {
code = Handle<Code>::null();
} }
pipeline_zone_scope.Destroy();
#ifdef ENABLE_DISASSEMBLER #ifdef ENABLE_DISASSEMBLER
if (!code.is_null() && FLAG_print_opt_code) { if (!code.is_null() && FLAG_print_opt_code) {
OFStream os(stdout); OFStream os(stdout);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment