Index: src/compiler/pipeline.cc |
diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc |
index e7c76aabc3934d7212c714197bd75ba34470b87a..b1e9156a4aaa5eb4b39b415f703dc95323c059c8 100644 |
--- a/src/compiler/pipeline.cc |
+++ b/src/compiler/pipeline.cc |
@@ -56,19 +56,33 @@ namespace v8 { |
namespace internal { |
namespace compiler { |
-class PipelineData { |
+namespace { |
+ |
+PipelineStatistics* NewPipelineStatistics(CompilationInfo* const info, |
+ ZonePool* const zone_pool) { |
+ if (FLAG_turbo_stats) { |
+ PipelineStatistics* pipeline_statistics = |
+ new PipelineStatistics(info, zone_pool); |
+ pipeline_statistics->BeginPhaseKind("initializing"); |
+ return pipeline_statistics; |
+ } |
+ return nullptr; |
+} |
+ |
+} // namespace |
+ |
+ |
+class PipelineData final { |
public: |
// For main entry point. |
- PipelineData(ZonePool* zone_pool, CompilationInfo* info, |
- PipelineStatistics* pipeline_statistics) |
+ explicit PipelineData(CompilationInfo* info) |
: isolate_(info->isolate()), |
info_(info), |
outer_zone_(info_->zone()), |
- zone_pool_(zone_pool), |
- pipeline_statistics_(pipeline_statistics), |
+ pipeline_statistics_(NewPipelineStatistics(info, zone_pool())), |
compilation_failed_(false), |
code_(Handle<Code>::null()), |
- graph_zone_scope_(zone_pool_), |
+ graph_zone_scope_(&zone_pool_), |
graph_zone_(graph_zone_scope_.zone()), |
graph_(nullptr), |
loop_assignment_(nullptr), |
@@ -77,16 +91,17 @@ class PipelineData { |
javascript_(nullptr), |
jsgraph_(nullptr), |
js_type_feedback_(nullptr), |
- typer_(nullptr), |
schedule_(nullptr), |
- instruction_zone_scope_(zone_pool_), |
+ linkage_(nullptr), |
+ profiler_data_(nullptr), |
+ instruction_zone_scope_(&zone_pool_), |
instruction_zone_(instruction_zone_scope_.zone()), |
sequence_(nullptr), |
frame_(nullptr), |
- register_allocation_zone_scope_(zone_pool_), |
+ register_allocation_zone_scope_(&zone_pool_), |
register_allocation_zone_(register_allocation_zone_scope_.zone()), |
register_allocation_data_(nullptr) { |
- PhaseScope scope(pipeline_statistics, "init pipeline data"); |
+ PhaseScope scope(pipeline_statistics(), "init pipeline data"); |
graph_ = new (graph_zone_) Graph(graph_zone_); |
source_positions_.Reset(new SourcePositionTable(graph_)); |
machine_ = new (graph_zone_) MachineOperatorBuilder( |
@@ -96,20 +111,17 @@ class PipelineData { |
javascript_ = new (graph_zone_) JSOperatorBuilder(graph_zone_); |
jsgraph_ = new (graph_zone_) |
JSGraph(isolate_, graph_, common_, javascript_, machine_); |
- typer_.Reset(new Typer(isolate_, graph_, info_->context())); |
} |
// For machine graph testing entry point. |
- PipelineData(ZonePool* zone_pool, CompilationInfo* info, Graph* graph, |
- Schedule* schedule) |
+ PipelineData(CompilationInfo* info, Graph* graph, Schedule* schedule) |
: isolate_(info->isolate()), |
info_(info), |
outer_zone_(nullptr), |
- zone_pool_(zone_pool), |
pipeline_statistics_(nullptr), |
compilation_failed_(false), |
code_(Handle<Code>::null()), |
- graph_zone_scope_(zone_pool_), |
+ graph_zone_scope_(&zone_pool_), |
graph_zone_(nullptr), |
graph_(graph), |
source_positions_(new SourcePositionTable(graph_)), |
@@ -119,27 +131,26 @@ class PipelineData { |
javascript_(nullptr), |
jsgraph_(nullptr), |
js_type_feedback_(nullptr), |
- typer_(nullptr), |
schedule_(schedule), |
- instruction_zone_scope_(zone_pool_), |
+ linkage_(nullptr), |
+ profiler_data_(nullptr), |
+ instruction_zone_scope_(&zone_pool_), |
instruction_zone_(instruction_zone_scope_.zone()), |
sequence_(nullptr), |
frame_(nullptr), |
- register_allocation_zone_scope_(zone_pool_), |
+ register_allocation_zone_scope_(&zone_pool_), |
register_allocation_zone_(register_allocation_zone_scope_.zone()), |
register_allocation_data_(nullptr) {} |
// For register allocation testing entry point. |
- PipelineData(ZonePool* zone_pool, CompilationInfo* info, |
- InstructionSequence* sequence) |
+ PipelineData(CompilationInfo* info, InstructionSequence* sequence) |
: isolate_(info->isolate()), |
info_(info), |
outer_zone_(nullptr), |
- zone_pool_(zone_pool), |
pipeline_statistics_(nullptr), |
compilation_failed_(false), |
code_(Handle<Code>::null()), |
- graph_zone_scope_(zone_pool_), |
+ graph_zone_scope_(&zone_pool_), |
graph_zone_(nullptr), |
graph_(nullptr), |
loop_assignment_(nullptr), |
@@ -148,13 +159,14 @@ class PipelineData { |
javascript_(nullptr), |
jsgraph_(nullptr), |
js_type_feedback_(nullptr), |
- typer_(nullptr), |
schedule_(nullptr), |
- instruction_zone_scope_(zone_pool_), |
+ linkage_(nullptr), |
+ profiler_data_(nullptr), |
+ instruction_zone_scope_(&zone_pool_), |
instruction_zone_(sequence->zone()), |
sequence_(sequence), |
frame_(nullptr), |
- register_allocation_zone_scope_(zone_pool_), |
+ register_allocation_zone_scope_(&zone_pool_), |
register_allocation_zone_(register_allocation_zone_scope_.zone()), |
register_allocation_data_(nullptr) {} |
@@ -166,8 +178,10 @@ class PipelineData { |
Isolate* isolate() const { return isolate_; } |
CompilationInfo* info() const { return info_; } |
- ZonePool* zone_pool() const { return zone_pool_; } |
- PipelineStatistics* pipeline_statistics() { return pipeline_statistics_; } |
+ ZonePool* zone_pool() { return &zone_pool_; } |
+ PipelineStatistics* pipeline_statistics() const { |
+ return pipeline_statistics_.get(); |
+ } |
bool compilation_failed() const { return compilation_failed_; } |
void set_compilation_failed() { compilation_failed_ = true; } |
Handle<Code> code() { return code_; } |
@@ -192,7 +206,6 @@ class PipelineData { |
void set_js_type_feedback(JSTypeFeedbackTable* js_type_feedback) { |
js_type_feedback_ = js_type_feedback; |
} |
- Typer* typer() const { return typer_.get(); } |
LoopAssignmentAnalysis* loop_assignment() const { return loop_assignment_; } |
void set_loop_assignment(LoopAssignmentAnalysis* loop_assignment) { |
@@ -210,6 +223,11 @@ class PipelineData { |
InstructionSequence* sequence() const { return sequence_; } |
Frame* frame() const { return frame_; } |
+ Linkage* linkage() const { return linkage_; } |
+ void set_linkage(Linkage* linkage) { linkage_ = linkage; } |
+ |
+ BasicBlockProfiler::Data* profiler_data() const { return profiler_data_; } |
+ |
Zone* register_allocation_zone() const { return register_allocation_zone_; } |
RegisterAllocationData* register_allocation_data() const { |
return register_allocation_data_; |
@@ -218,7 +236,6 @@ class PipelineData { |
void DeleteGraphZone() { |
// Destroy objects with destructors first. |
source_positions_.Reset(nullptr); |
- typer_.Reset(nullptr); |
if (graph_zone_ == nullptr) return; |
// Destroy zone and clear pointers. |
graph_zone_scope_.Destroy(); |
@@ -250,6 +267,10 @@ class PipelineData { |
void InitializeInstructionSequence() { |
DCHECK(sequence_ == nullptr); |
+ if (FLAG_turbo_profiling) { |
+ profiler_data_ = |
+ BasicBlockInstrumentor::Instrument(info(), graph(), schedule()); |
+ } |
InstructionBlocks* instruction_blocks = |
InstructionSequence::InstructionBlocksFor(instruction_zone(), |
schedule()); |
@@ -267,12 +288,16 @@ class PipelineData { |
sequence(), debug_name); |
} |
+ std::ostringstream& source_position_output() { |
+ return source_position_output_; |
+ } |
+ |
private: |
Isolate* isolate_; |
CompilationInfo* info_; |
Zone* outer_zone_; |
- ZonePool* const zone_pool_; |
- PipelineStatistics* pipeline_statistics_; |
+ ZonePool zone_pool_; |
+ SmartPointer<PipelineStatistics> pipeline_statistics_; |
bool compilation_failed_; |
Handle<Code> code_; |
@@ -290,8 +315,10 @@ class PipelineData { |
JSGraph* jsgraph_; |
JSTypeFeedbackTable* js_type_feedback_; |
// TODO(dcarney): make this into a ZoneObject. |
- SmartPointer<Typer> typer_; |
Schedule* schedule_; |
+ Linkage* linkage_; |
+ BasicBlockProfiler::Data* profiler_data_; |
+ std::ostringstream source_position_output_; |
// All objects in the following group of fields are allocated in |
// instruction_zone_. They are all set to NULL when the instruction_zone_ is |
@@ -450,19 +477,28 @@ class PipelineRunScope { |
} // namespace |
+Pipeline::Pipeline(CompilationInfo* info) : Pipeline(new PipelineData(info)) {} |
+ |
+ |
+Pipeline::~Pipeline() { delete data_; } |
+ |
+ |
+CompilationInfo* Pipeline::info() const { return data()->info(); } |
+ |
+ |
template <typename Phase> |
void Pipeline::Run() { |
- PipelineRunScope scope(this->data_, Phase::phase_name()); |
+ PipelineRunScope scope(data(), Phase::phase_name()); |
Phase phase; |
- phase.Run(this->data_, scope.zone()); |
+ phase.Run(data(), scope.zone()); |
} |
template <typename Phase, typename Arg0> |
void Pipeline::Run(Arg0 arg_0) { |
- PipelineRunScope scope(this->data_, Phase::phase_name()); |
+ PipelineRunScope scope(data(), Phase::phase_name()); |
Phase phase; |
- phase.Run(this->data_, scope.zone(), arg_0); |
+ phase.Run(data(), scope.zone(), arg_0); |
} |
@@ -522,7 +558,7 @@ struct InliningPhase { |
struct TyperPhase { |
static const char* phase_name() { return "typer"; } |
- void Run(PipelineData* data, Zone* temp_zone) { data->typer()->Run(); } |
+ void Run(PipelineData* data, Zone* temp_zone, Typer* typer) { typer->Run(); } |
}; |
@@ -702,10 +738,10 @@ struct ComputeSchedulePhase { |
struct InstructionSelectionPhase { |
static const char* phase_name() { return "select instructions"; } |
- void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) { |
+ void Run(PipelineData* data, Zone* temp_zone) { |
InstructionSelector selector( |
- temp_zone, data->graph()->NodeCount(), linkage, data->sequence(), |
- data->schedule(), data->source_positions(), |
+ temp_zone, data->graph()->NodeCount(), data->linkage(), |
+ data->sequence(), data->schedule(), data->source_positions(), |
data->info()->is_source_positions_enabled() |
? InstructionSelector::kAllSourcePositions |
: InstructionSelector::kCallSourcePositions); |
@@ -862,8 +898,8 @@ struct JumpThreadingPhase { |
struct GenerateCodePhase { |
static const char* phase_name() { return "generate code"; } |
- void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) { |
- CodeGenerator generator(data->frame(), linkage, data->sequence(), |
+ void Run(PipelineData* data, Zone* temp_zone) { |
+ CodeGenerator generator(data->frame(), data->linkage(), data->sequence(), |
data->info()); |
data->set_code(generator.GenerateCode()); |
} |
@@ -931,7 +967,7 @@ void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) { |
} |
-Handle<Code> Pipeline::GenerateCode() { |
+bool Pipeline::CreateGraph() { |
// TODO(mstarzinger): This is just a temporary hack to make TurboFan work, |
// the correct solution is to restore the context register after invoking |
// builtins from full-codegen. |
@@ -939,21 +975,13 @@ Handle<Code> Pipeline::GenerateCode() { |
for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) { |
Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i); |
Object* builtin = isolate()->js_builtins_object()->javascript_builtin(id); |
- if (*info()->closure() == builtin) return Handle<Code>::null(); |
+ if (*info()->closure() == builtin) return false; |
} |
// TODO(dslomov): support turbo optimization of subclass constructors. |
if (IsSubclassConstructor(shared->kind())) { |
shared->DisableOptimization(kSuperReference); |
- return Handle<Code>::null(); |
- } |
- |
- ZonePool zone_pool; |
- SmartPointer<PipelineStatistics> pipeline_statistics; |
- |
- if (FLAG_turbo_stats) { |
- pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool)); |
- pipeline_statistics->BeginPhaseKind("initializing"); |
+ return false; |
} |
if (FLAG_trace_turbo) { |
@@ -982,12 +1010,9 @@ Handle<Code> Pipeline::GenerateCode() { |
} |
} |
- PipelineData data(&zone_pool, info(), pipeline_statistics.get()); |
- this->data_ = &data; |
- |
if (info()->is_type_feedback_enabled()) { |
- data.set_js_type_feedback(new (data.graph_zone()) |
- JSTypeFeedbackTable(data.graph_zone())); |
+ data()->set_js_type_feedback(new (data()->graph_zone()) |
+ JSTypeFeedbackTable(data()->graph_zone())); |
} |
BeginPhaseKind("graph creation"); |
@@ -1001,14 +1026,14 @@ Handle<Code> Pipeline::GenerateCode() { |
tcf << AsC1VCompilation(info()); |
} |
- data.source_positions()->AddDecorator(); |
+ data()->source_positions()->AddDecorator(); |
if (FLAG_loop_assignment_analysis) { |
Run<LoopAssignmentAnalysisPhase>(); |
} |
Run<GraphBuilderPhase>(info()->is_context_specializing()); |
- if (data.compilation_failed()) return Handle<Code>::null(); |
+ if (data()->compilation_failed()) return false; |
RunPrintAndVerify("Initial untyped", true); |
Run<EarlyControlReductionPhase>(); |
@@ -1025,15 +1050,17 @@ Handle<Code> Pipeline::GenerateCode() { |
if (FLAG_print_turbo_replay) { |
// Print a replay of the initial graph. |
- GraphReplayPrinter::PrintReplay(data.graph()); |
+ GraphReplayPrinter::PrintReplay(data()->graph()); |
} |
// Bailout here in case target architecture is not supported. |
- if (!SupportedTarget()) return Handle<Code>::null(); |
+ if (!SupportedTarget()) return false; |
+ SmartPointer<Typer> typer; |
if (info()->is_typing_enabled()) { |
// Type the graph. |
- Run<TyperPhase>(); |
+ typer.Reset(new Typer(isolate(), data()->graph(), info()->context())); |
+ Run<TyperPhase>(typer.get()); |
RunPrintAndVerify("Typed"); |
} |
@@ -1079,7 +1106,7 @@ Handle<Code> Pipeline::GenerateCode() { |
} else { |
if (info()->is_osr()) { |
Run<OsrDeconstructionPhase>(); |
- if (info()->bailout_reason() != kNoReason) return Handle<Code>::null(); |
+ if (info()->bailout_reason() != kNoReason) return false; |
RunPrintAndVerify("OSR deconstruction"); |
} |
} |
@@ -1091,10 +1118,21 @@ Handle<Code> Pipeline::GenerateCode() { |
BeginPhaseKind("block building"); |
- data.source_positions()->RemoveDecorator(); |
+ data()->source_positions()->RemoveDecorator(); |
+ return true; |
+} |
+ |
+ |
+bool Pipeline::OptimizeGraph() { |
+ return ScheduleAndAllocateRegisters( |
+ Linkage::ComputeIncoming(data()->instruction_zone(), info())); |
+} |
+ |
+Handle<Code> Pipeline::GenerateCode() { |
+ if (!CreateGraph()) return Handle<Code>::null(); |
return ScheduleAndGenerateCode( |
- Linkage::ComputeIncoming(data.instruction_zone(), info())); |
+ Linkage::ComputeIncoming(data()->instruction_zone(), info())); |
} |
@@ -1122,17 +1160,15 @@ Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info, |
Graph* graph, |
Schedule* schedule) { |
// Construct a pipeline for scheduling and code generation. |
- ZonePool zone_pool; |
- PipelineData data(&zone_pool, info, graph, schedule); |
+ PipelineData* data = new PipelineData(info, graph, schedule); |
SmartPointer<PipelineStatistics> pipeline_statistics; |
if (FLAG_turbo_stats) { |
- pipeline_statistics.Reset(new PipelineStatistics(info, &zone_pool)); |
+ pipeline_statistics.Reset(new PipelineStatistics(info, data->zone_pool())); |
pipeline_statistics->BeginPhaseKind("test codegen"); |
} |
- Pipeline pipeline(info); |
- pipeline.data_ = &data; |
- if (data.schedule() == nullptr) { |
+ Pipeline pipeline(data); |
+ if (data->schedule() == nullptr) { |
// TODO(rossberg): Should this really be untyped? |
pipeline.RunPrintAndVerify("Machine", true); |
} |
@@ -1146,18 +1182,15 @@ bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config, |
bool run_verifier) { |
FakeStubForTesting stub(sequence->isolate()); |
CompilationInfo info(&stub, sequence->isolate(), sequence->zone()); |
- ZonePool zone_pool; |
- PipelineData data(&zone_pool, &info, sequence); |
- Pipeline pipeline(&info); |
- pipeline.data_ = &data; |
+ PipelineData* data = new PipelineData(&info, sequence); |
+ Pipeline pipeline(data); |
pipeline.AllocateRegisters(config, run_verifier); |
- return !data.compilation_failed(); |
+ return !data->compilation_failed(); |
} |
-Handle<Code> Pipeline::ScheduleAndGenerateCode( |
- CallDescriptor* call_descriptor) { |
- PipelineData* data = this->data_; |
+bool Pipeline::ScheduleAndAllocateRegisters(CallDescriptor* call_descriptor) { |
+ PipelineData* data = this->data(); |
DCHECK_NOT_NULL(data->graph()); |
CHECK(SupportedBackend()); |
@@ -1165,17 +1198,11 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode( |
if (data->schedule() == nullptr) Run<ComputeSchedulePhase>(); |
TraceSchedule(data->info(), data->schedule()); |
- BasicBlockProfiler::Data* profiler_data = NULL; |
- if (FLAG_turbo_profiling) { |
- profiler_data = BasicBlockInstrumentor::Instrument(info(), data->graph(), |
- data->schedule()); |
- } |
- |
data->InitializeInstructionSequence(); |
// Select and schedule instructions covering the scheduled graph. |
- Linkage linkage(call_descriptor); |
- Run<InstructionSelectionPhase>(&linkage); |
+ data->set_linkage(new (data->info()->zone()) Linkage(call_descriptor)); |
+ Run<InstructionSelectionPhase>(); |
if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { |
TurboCfgFile tcf(isolate()); |
@@ -1183,10 +1210,9 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode( |
data->sequence()); |
} |
- std::ostringstream source_position_output; |
if (FLAG_trace_turbo) { |
// Output source position information before the graph is deleted. |
- data_->source_positions()->Print(source_position_output); |
+ data->source_positions()->Print(data->source_position_output()); |
} |
data->DeleteGraphZone(); |
@@ -1198,7 +1224,7 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode( |
AllocateRegisters(RegisterConfiguration::ArchDefault(), run_verifier); |
if (data->compilation_failed()) { |
info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); |
- return Handle<Code>(); |
+ return false; |
} |
BeginPhaseKind("code generation"); |
@@ -1208,15 +1234,22 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode( |
Run<JumpThreadingPhase>(); |
} |
+ return true; |
+} |
+ |
+ |
+Handle<Code> Pipeline::DoGenerateCode() { |
+ PipelineData* data = this->data_; |
+ |
// Generate final machine code. |
- Run<GenerateCodePhase>(&linkage); |
+ Run<GenerateCodePhase>(); |
Handle<Code> code = data->code(); |
- if (profiler_data != NULL) { |
+ if (data->profiler_data()) { |
#if ENABLE_DISASSEMBLER |
std::ostringstream os; |
code->Disassemble(NULL, os); |
- profiler_data->SetCode(&os); |
+ data->profiler_data()->SetCode(&os); |
#endif |
} |
@@ -1239,7 +1272,7 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode( |
#endif // ENABLE_DISASSEMBLER |
json_of << "\"}\n],\n"; |
json_of << "\"nodePositions\":"; |
- json_of << source_position_output.str(); |
+ json_of << data->source_position_output().str(); |
json_of << "}"; |
fclose(json_file); |
} |
@@ -1253,9 +1286,18 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode( |
} |
+Handle<Code> Pipeline::ScheduleAndGenerateCode( |
+ CallDescriptor* call_descriptor) { |
+ if (!ScheduleAndAllocateRegisters(call_descriptor)) { |
+ return Handle<Code>::null(); |
+ } |
+ return DoGenerateCode(); |
+} |
+ |
+ |
void Pipeline::AllocateRegisters(const RegisterConfiguration* config, |
bool run_verifier) { |
- PipelineData* data = this->data_; |
+ PipelineData* data = this->data(); |
// Don't track usage for this zone in compiler stats. |
SmartPointer<Zone> verifier_zone; |