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) {
TRACE_EVENT0("v8", "V8.OptimizeCode");
bool use_turbofan = UseTurboFan(info);
OptimizedCompileJob* job = use_turbofan
? compiler::Pipeline::NewCompilationJob(info)
: new (info->zone()) HCompilationJob(info);
base::SmartPointer<OptimizedCompileJob> job(
use_turbofan ? compiler::Pipeline::NewCompilationJob(info)
: new HCompilationJob(info));
// Parsing is not required when optimizing from existing bytecode.
if (!use_turbofan || !info->shared_info()->HasBytecodeArray()) {
......@@ -755,9 +755,9 @@ bool GetOptimizedCodeLater(CompilationInfo* info) {
}
bool use_turbofan = UseTurboFan(info);
OptimizedCompileJob* job = use_turbofan
? compiler::Pipeline::NewCompilationJob(info)
: new (info->zone()) HCompilationJob(info);
base::SmartPointer<OptimizedCompileJob> job(
use_turbofan ? compiler::Pipeline::NewCompilationJob(info)
: new HCompilationJob(info));
// 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.
......@@ -778,7 +778,8 @@ bool GetOptimizedCodeLater(CompilationInfo* info) {
TRACE_EVENT0("v8", "V8.RecompileSynchronous");
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) {
PrintF(" ** Queued ");
......@@ -1725,7 +1726,7 @@ MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
void Compiler::FinalizeOptimizedCompileJob(OptimizedCompileJob* job) {
// 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());
Isolate* isolate = info->isolate();
......@@ -1761,6 +1762,7 @@ void Compiler::FinalizeOptimizedCompileJob(OptimizedCompileJob* job) {
PrintF("]\n");
}
info->closure()->ReplaceCode(*info->code());
delete job;
return;
}
}
......@@ -1772,6 +1774,7 @@ void Compiler::FinalizeOptimizedCompileJob(OptimizedCompileJob* job) {
PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
}
info->closure()->ReplaceCode(shared->code());
delete job;
}
void Compiler::PostInstantiation(Handle<JSFunction> function,
......
......@@ -571,7 +571,8 @@ class CompilationInfo {
// 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
// be checked using {last_status()} as well.
class OptimizedCompileJob: public ZoneObject {
// TODO(mstarzinger): Make CompilationInfo base embedded.
class OptimizedCompileJob {
public:
explicit OptimizedCompileJob(CompilationInfo* info, const char* compiler_name)
: info_(info), compiler_name_(compiler_name), last_status_(SUCCEEDED) {}
......
......@@ -60,11 +60,16 @@ class IA32OperandGenerator final : public OperandGenerator {
case IrOpcode::kRelocatableInt64Constant:
return true;
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
// the GC does not scan code objects when collecting the new generation.
Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node);
Isolate* isolate = value->GetIsolate();
return !isolate->heap()->InNewSpace(*value);
#endif
}
default:
return false;
......
......@@ -7,6 +7,8 @@
#include <string>
#include "src/base/platform/elapsed-timer.h"
#include "src/base/smart-pointers.h"
#include "src/compilation-statistics.h"
#include "src/compiler/zone-pool.h"
......@@ -22,6 +24,7 @@ class PipelineStatistics : public Malloced {
~PipelineStatistics();
void BeginPhaseKind(const char* phase_kind_name);
void EndPhaseKind();
private:
size_t OuterZoneSize() {
......@@ -43,7 +46,6 @@ class PipelineStatistics : public Malloced {
};
bool InPhaseKind() { return !phase_kind_stats_.scope_.is_empty(); }
void EndPhaseKind();
friend class PhaseScope;
bool InPhase() { return !phase_stats_.scope_.is_empty(); }
......
This diff is collapsed.
......@@ -15,7 +15,6 @@ namespace internal {
class CompilationInfo;
class OptimizedCompileJob;
class RegisterConfiguration;
class Zone;
namespace compiler {
......@@ -26,11 +25,19 @@ class Linkage;
class PipelineData;
class Schedule;
class SourcePositionTable;
class ZonePool;
class Pipeline {
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.
Handle<Code> GenerateCode();
......@@ -43,6 +50,10 @@ class Pipeline {
Code::Flags flags,
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
// {nullptr}, then compute a new schedule for code generation.
static Handle<Code> GenerateCodeForTesting(CompilationInfo* info,
......@@ -64,11 +75,13 @@ class Pipeline {
// Returns a new compilation job for the given compilation info.
static OptimizedCompileJob* NewCompilationJob(CompilationInfo* info);
void InitializeWasmCompilation(Zone* pipeline_zone, ZonePool* zone_pool,
Graph* graph,
SourcePositionTable* source_positions);
bool ExecuteWasmCompilation(CallDescriptor* descriptor);
Handle<Code> FinalizeWasmCompilation(CallDescriptor* descriptor);
// Returns a new compilation job for the WebAssembly compilation info.
static OptimizedCompileJob* NewWasmCompilationJob(
CompilationInfo* info, Graph* graph, CallDescriptor* descriptor,
SourcePositionTable* source_positions);
// TODO(mstarzinger, bmeurer): This shouldn't be public!
bool ScheduleAndSelectInstructions(Linkage* linkage);
private:
// Helpers for executing pipeline phases.
......@@ -80,17 +93,16 @@ class Pipeline {
void Run(Arg0 arg_0, Arg1 arg_1);
void BeginPhaseKind(const char* phase_kind);
void EndPhaseKind();
void RunPrintAndVerify(const char* phase, bool untyped = false);
Handle<Code> ScheduleAndGenerateCode(CallDescriptor* call_descriptor);
void AllocateRegisters(const RegisterConfiguration* config,
CallDescriptor* descriptor, bool run_verifier);
bool ScheduleGraph(CallDescriptor* call_descriptor);
Handle<Code> GenerateCode(CallDescriptor* descriptor);
Handle<Code> ScheduleAndGenerateCode(CallDescriptor* call_descriptor);
CompilationInfo* info() const { return info_; }
CompilationInfo* info() const;
Isolate* isolate() const;
CompilationInfo* const info_;
PipelineData* data_;
PipelineData* const data_;
DISALLOW_COPY_AND_ASSIGN(Pipeline);
};
......
......@@ -2968,15 +2968,12 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
}
}
CompilationInfo info(func_name, isolate, jsgraph->graph()->zone(), flags);
compiler::ZonePool::Scope pipeline_zone_scope(&zone_pool);
Pipeline pipeline(&info);
pipeline.InitializeWasmCompilation(pipeline_zone_scope.zone(), &zone_pool,
jsgraph->graph(), source_positions);
Handle<Code> code;
if (pipeline.ExecuteWasmCompilation(descriptor)) {
code = pipeline.FinalizeWasmCompilation(descriptor);
} else {
code = Handle<Code>::null();
base::SmartPointer<OptimizedCompileJob> job(Pipeline::NewWasmCompilationJob(
&info, jsgraph->graph(), descriptor, source_positions));
Handle<Code> code = Handle<Code>::null();
if (job->OptimizeGraph() == OptimizedCompileJob::SUCCEEDED &&
job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) {
code = info.code();
}
buffer.Dispose();
......
......@@ -23,6 +23,7 @@ void DisposeOptimizedCompileJob(OptimizedCompileJob* job,
Handle<JSFunction> function = info->closure();
function->ReplaceCode(function->shared()->code());
}
delete job;
delete info;
}
......
......@@ -194,8 +194,7 @@ class FunctionTester : public InitializedHandleScope {
CHECK(Compiler::Analyze(info.parse_info()));
CHECK(Compiler::EnsureDeoptimizationSupport(&info));
Pipeline pipeline(&info);
Handle<Code> code = pipeline.GenerateCode();
Handle<Code> code = Pipeline::GenerateCodeForTesting(&info);
CHECK(!code.is_null());
info.dependencies()->Commit(code);
info.context()->native_context()->AddOptimizedCode(*code);
......
......@@ -129,8 +129,7 @@ class BytecodeGraphTester {
compilation_info.SetOptimizing();
compilation_info.MarkAsDeoptimizationEnabled();
compilation_info.MarkAsOptimizeFromBytecode();
compiler::Pipeline pipeline(&compilation_info);
Handle<Code> code = pipeline.GenerateCode();
Handle<Code> code = Pipeline::GenerateCodeForTesting(&compilation_info);
function->ReplaceCode(*code);
return function;
......
......@@ -485,18 +485,14 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
}
CompilationInfo info(debug_name_, this->isolate(), this->zone(),
Code::ComputeFlags(Code::WASM_FUNCTION));
compiler::ZonePool zone_pool(this->isolate()->allocator());
compiler::ZonePool::Scope pipeline_zone_scope(&zone_pool);
Pipeline pipeline(&info);
pipeline.InitializeWasmCompilation(this->zone(), &zone_pool, this->graph(),
&source_position_table_);
Handle<Code> code;
if (pipeline.ExecuteWasmCompilation(desc)) {
code = pipeline.FinalizeWasmCompilation(desc);
} else {
code = Handle<Code>::null();
v8::base::SmartPointer<OptimizedCompileJob> job(
Pipeline::NewWasmCompilationJob(&info, graph(), desc,
&source_position_table_));
Handle<Code> code = Handle<Code>::null();
if (job->OptimizeGraph() == OptimizedCompileJob::SUCCEEDED &&
job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) {
code = info.code();
}
pipeline_zone_scope.Destroy();
#ifdef ENABLE_DISASSEMBLER
if (!code.is_null() && FLAG_print_opt_code) {
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