Index: src/compiler/pipeline.cc |
diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc |
index 3e46d6f5194bd6abc0356231c627d67d0d97691e..c8569f28189aa34095d3c604379278a2a8781550 100644 |
--- a/src/compiler/pipeline.cc |
+++ b/src/compiler/pipeline.cc |
@@ -58,19 +58,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), |
@@ -80,14 +94,16 @@ class PipelineData { |
jsgraph_(nullptr), |
js_type_feedback_(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( |
@@ -100,16 +116,14 @@ class PipelineData { |
} |
// 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_)), |
@@ -120,25 +134,25 @@ class PipelineData { |
jsgraph_(nullptr), |
js_type_feedback_(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,11 +162,13 @@ class PipelineData { |
jsgraph_(nullptr), |
js_type_feedback_(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) {} |
@@ -164,8 +180,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_; } |
@@ -207,6 +225,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_; |
@@ -246,6 +269,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()); |
@@ -263,12 +290,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_; |
@@ -286,6 +317,9 @@ class PipelineData { |
JSGraph* jsgraph_; |
JSTypeFeedbackTable* js_type_feedback_; |
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 |
@@ -444,19 +478,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); |
} |
@@ -737,10 +780,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); |
@@ -897,8 +940,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()); |
} |
@@ -956,6 +999,13 @@ void Pipeline::BeginPhaseKind(const char* phase_kind_name) { |
} |
+void Pipeline::EndPhaseKind() { |
+ if (data_->pipeline_statistics() != NULL) { |
+ data_->pipeline_statistics()->EndPhaseKind(); |
+ } |
+} |
+ |
+ |
void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) { |
if (FLAG_trace_turbo) { |
Run<PrintGraphPhase>(phase); |
@@ -966,7 +1016,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. |
@@ -974,21 +1024,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) { |
@@ -1017,12 +1059,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"); |
@@ -1036,14 +1075,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>(); |
@@ -1063,16 +1102,16 @@ 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. |
- typer.Reset(new Typer(isolate(), data.graph(), info()->context())); |
+ typer.Reset(new Typer(isolate(), data()->graph(), info()->context())); |
Run<TyperPhase>(typer.get()); |
RunPrintAndVerify("Typed"); |
} |
@@ -1119,7 +1158,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", true); |
} |
} |
@@ -1129,19 +1168,28 @@ Handle<Code> Pipeline::GenerateCode() { |
// TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
RunPrintAndVerify("Lowered generic", true); |
+ EndPhaseKind(); |
+ |
+ data()->source_positions()->RemoveDecorator(); |
+ return true; |
+} |
+ |
+ |
+bool Pipeline::OptimizeGraph() { |
+ BeginPhaseKind("block building"); |
+ |
Run<LateGraphTrimmingPhase>(); |
// TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
RunPrintAndVerify("Late trimmed", true); |
- BeginPhaseKind("block building"); |
- |
- data.source_positions()->RemoveDecorator(); |
+ return ScheduleAndAllocateRegisters( |
+ Linkage::ComputeIncoming(data()->instruction_zone(), info())); |
+} |
- // Kill the Typer and thereby uninstall the decorator (if any). |
- typer.Reset(nullptr); |
- return ScheduleAndGenerateCode( |
- Linkage::ComputeIncoming(data.instruction_zone(), info())); |
+Handle<Code> Pipeline::GenerateCode() { |
+ if (!CreateGraph() || !OptimizeGraph()) return Handle<Code>::null(); |
+ return DoGenerateCode(); |
} |
@@ -1169,17 +1217,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); |
} |
@@ -1193,18 +1239,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()); |
@@ -1212,17 +1255,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()); |
@@ -1230,10 +1267,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(); |
@@ -1245,25 +1281,34 @@ Handle<Code> Pipeline::ScheduleAndGenerateCode( |
AllocateRegisters(RegisterConfiguration::ArchDefault(), run_verifier); |
if (data->compilation_failed()) { |
info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); |
- return Handle<Code>(); |
+ return false; |
} |
- BeginPhaseKind("code generation"); |
- |
// Optimimize jumps. |
if (FLAG_turbo_jt) { |
Run<JumpThreadingPhase>(); |
} |
+ EndPhaseKind(); |
+ |
+ return true; |
+} |
+ |
+ |
+Handle<Code> Pipeline::DoGenerateCode() { |
+ PipelineData* data = this->data_; |
+ |
+ BeginPhaseKind("code generation"); |
+ |
// 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 |
} |
@@ -1286,7 +1331,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); |
} |
@@ -1300,9 +1345,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; |