Index: src/compiler/pipeline.cc |
diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc |
index c59ce2ec786c1b9d246df81ba6bd16ec1eeef641..b44fe9b71ec80d0c639edc3cf004f765b2dd5b6c 100644 |
--- a/src/compiler/pipeline.cc |
+++ b/src/compiler/pipeline.cc |
@@ -40,6 +40,128 @@ namespace v8 { |
namespace internal { |
namespace compiler { |
+class PipelineData { |
+ public: |
+ explicit PipelineData(CompilationInfo* info, ZonePool* zone_pool, |
+ PipelineStatistics* pipeline_statistics) |
+ : isolate_(info->zone()->isolate()), |
+ outer_zone_(info->zone()), |
+ zone_pool_(zone_pool), |
+ pipeline_statistics_(pipeline_statistics), |
+ graph_zone_scope_(zone_pool_), |
+ graph_zone_(graph_zone_scope_.zone()), |
+ graph_(new (graph_zone()) Graph(graph_zone())), |
+ source_positions_(new SourcePositionTable(graph())), |
+ machine_(new (graph_zone()) MachineOperatorBuilder( |
+ kMachPtr, InstructionSelector::SupportedMachineOperatorFlags())), |
+ common_(new (graph_zone()) CommonOperatorBuilder(graph_zone())), |
+ javascript_(new (graph_zone()) JSOperatorBuilder(graph_zone())), |
+ jsgraph_(new (graph_zone()) |
+ JSGraph(graph(), common(), javascript(), machine())), |
+ typer_(new Typer(graph(), info->context())), |
+ schedule_(NULL), |
+ instruction_zone_scope_(zone_pool_), |
+ instruction_zone_(instruction_zone_scope_.zone()) {} |
+ |
+ // For machine graph testing only. |
+ PipelineData(Graph* graph, Schedule* schedule, ZonePool* zone_pool) |
+ : isolate_(graph->zone()->isolate()), |
+ outer_zone_(NULL), |
+ zone_pool_(zone_pool), |
+ pipeline_statistics_(NULL), |
+ graph_zone_scope_(zone_pool_), |
+ graph_zone_(NULL), |
+ graph_(graph), |
+ source_positions_(new SourcePositionTable(graph)), |
+ machine_(NULL), |
+ common_(NULL), |
+ javascript_(NULL), |
+ jsgraph_(NULL), |
+ typer_(NULL), |
+ schedule_(schedule), |
+ instruction_zone_scope_(zone_pool_), |
+ instruction_zone_(instruction_zone_scope_.zone()) {} |
+ |
+ ~PipelineData() { |
+ DeleteInstructionZone(); |
+ DeleteGraphZone(); |
+ } |
+ |
+ Isolate* isolate() const { return isolate_; } |
+ ZonePool* zone_pool() const { return zone_pool_; } |
+ PipelineStatistics* pipeline_statistics() { return pipeline_statistics_; } |
+ |
+ Zone* graph_zone() const { return graph_zone_; } |
+ Graph* graph() const { return graph_; } |
+ SourcePositionTable* source_positions() const { |
+ return source_positions_.get(); |
+ } |
+ MachineOperatorBuilder* machine() const { return machine_; } |
+ CommonOperatorBuilder* common() const { return common_; } |
+ JSOperatorBuilder* javascript() const { return javascript_; } |
+ JSGraph* jsgraph() const { return jsgraph_; } |
+ Typer* typer() const { return typer_.get(); } |
+ Schedule* schedule() const { return schedule_; } |
+ void set_schedule(Schedule* schedule) { |
+ DCHECK_EQ(NULL, schedule_); |
+ schedule_ = schedule; |
+ } |
+ |
+ Zone* instruction_zone() const { return instruction_zone_; } |
+ |
+ void DeleteGraphZone() { |
+ // Destroy objects with destructors first. |
+ source_positions_.Reset(NULL); |
+ typer_.Reset(NULL); |
+ if (graph_zone_ == NULL) return; |
+ // Destroy zone and clear pointers. |
+ graph_zone_scope_.Destroy(); |
+ graph_zone_ = NULL; |
+ graph_ = NULL; |
+ machine_ = NULL; |
+ common_ = NULL; |
+ javascript_ = NULL; |
+ jsgraph_ = NULL; |
+ schedule_ = NULL; |
+ } |
+ |
+ void DeleteInstructionZone() { |
+ if (instruction_zone_ == NULL) return; |
+ instruction_zone_scope_.Destroy(); |
+ instruction_zone_ = NULL; |
+ } |
+ |
+ private: |
+ Isolate* isolate_; |
+ Zone* outer_zone_; |
+ ZonePool* zone_pool_; |
+ PipelineStatistics* pipeline_statistics_; |
+ |
+ ZonePool::Scope graph_zone_scope_; |
+ Zone* graph_zone_; |
+ // All objects in the following group of fields are allocated in graph_zone_. |
+ // They are all set to NULL when the graph_zone_ is destroyed. |
+ Graph* graph_; |
+ // TODO(dcarney): make this into a ZoneObject. |
+ SmartPointer<SourcePositionTable> source_positions_; |
+ MachineOperatorBuilder* machine_; |
+ CommonOperatorBuilder* common_; |
+ JSOperatorBuilder* javascript_; |
+ JSGraph* jsgraph_; |
+ // TODO(dcarney): make this into a ZoneObject. |
+ SmartPointer<Typer> typer_; |
+ Schedule* schedule_; |
+ |
+ // All objects in the following group of fields are allocated in |
+ // instruction_zone_. They are all set to NULL when the instruction_zone_ is |
+ // destroyed. |
+ ZonePool::Scope instruction_zone_scope_; |
+ Zone* instruction_zone_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(PipelineData); |
+}; |
+ |
+ |
static inline bool VerifyGraphs() { |
#ifdef DEBUG |
return true; |
@@ -170,32 +292,24 @@ Handle<Code> Pipeline::GenerateCode() { |
tcf << AsC1VCompilation(info()); |
} |
- // Build the graph. |
- Graph graph(zone()); |
- SourcePositionTable source_positions(&graph); |
- source_positions.AddDecorator(); |
- // TODO(turbofan): there is no need to type anything during initial graph |
- // construction. This is currently only needed for the node cache, which the |
- // typer could sweep over later. |
- Typer typer(&graph, info()->context()); |
- MachineOperatorBuilder machine( |
- kMachPtr, InstructionSelector::SupportedMachineOperatorFlags()); |
- CommonOperatorBuilder common(zone()); |
- JSOperatorBuilder javascript(zone()); |
- JSGraph jsgraph(&graph, &common, &javascript, &machine); |
+ // Initialize the graph and builders. |
+ PipelineData data(info(), &zone_pool, pipeline_statistics.get()); |
+ |
+ data.source_positions()->AddDecorator(); |
+ |
Node* context_node; |
{ |
PhaseScope phase_scope(pipeline_statistics.get(), "graph builder"); |
- ZonePool::Scope zone_scope(&zone_pool); |
- AstGraphBuilderWithPositions graph_builder(zone_scope.zone(), info(), |
- &jsgraph, &source_positions); |
+ ZonePool::Scope zone_scope(data.zone_pool()); |
+ AstGraphBuilderWithPositions graph_builder( |
+ zone_scope.zone(), info(), data.jsgraph(), data.source_positions()); |
graph_builder.CreateGraph(); |
context_node = graph_builder.GetFunctionContext(); |
} |
{ |
PhaseScope phase_scope(pipeline_statistics.get(), "phi reduction"); |
PhiReducer phi_reducer; |
- GraphReducer graph_reducer(&graph); |
+ GraphReducer graph_reducer(data.graph()); |
graph_reducer.AddReducer(&phi_reducer); |
graph_reducer.ReduceGraph(); |
// TODO(mstarzinger): Running reducer once ought to be enough for everyone. |
@@ -203,30 +317,30 @@ Handle<Code> Pipeline::GenerateCode() { |
graph_reducer.ReduceGraph(); |
} |
- VerifyAndPrintGraph(&graph, "Initial untyped", true); |
+ VerifyAndPrintGraph(data.graph(), "Initial untyped", true); |
if (info()->is_context_specializing()) { |
- SourcePositionTable::Scope pos(&source_positions, |
+ SourcePositionTable::Scope pos(data.source_positions(), |
SourcePosition::Unknown()); |
// Specialize the code to the context as aggressively as possible. |
- JSContextSpecializer spec(info(), &jsgraph, context_node); |
+ JSContextSpecializer spec(info(), data.jsgraph(), context_node); |
spec.SpecializeToContext(); |
- VerifyAndPrintGraph(&graph, "Context specialized", true); |
+ VerifyAndPrintGraph(data.graph(), "Context specialized", true); |
} |
if (info()->is_inlining_enabled()) { |
PhaseScope phase_scope(pipeline_statistics.get(), "inlining"); |
- SourcePositionTable::Scope pos(&source_positions, |
+ SourcePositionTable::Scope pos(data.source_positions(), |
SourcePosition::Unknown()); |
- ZonePool::Scope zone_scope(&zone_pool); |
- JSInliner inliner(zone_scope.zone(), info(), &jsgraph); |
+ ZonePool::Scope zone_scope(data.zone_pool()); |
+ JSInliner inliner(zone_scope.zone(), info(), data.jsgraph()); |
inliner.Inline(); |
- VerifyAndPrintGraph(&graph, "Inlined", true); |
+ VerifyAndPrintGraph(data.graph(), "Inlined", true); |
} |
// Print a replay of the initial graph. |
if (FLAG_print_turbo_replay) { |
- GraphReplayPrinter::PrintReplay(&graph); |
+ GraphReplayPrinter::PrintReplay(data.graph()); |
} |
// Bailout here in case target architecture is not supported. |
@@ -236,8 +350,8 @@ Handle<Code> Pipeline::GenerateCode() { |
{ |
// Type the graph. |
PhaseScope phase_scope(pipeline_statistics.get(), "typer"); |
- typer.Run(); |
- VerifyAndPrintGraph(&graph, "Typed"); |
+ data.typer()->Run(); |
+ VerifyAndPrintGraph(data.graph(), "Typed"); |
} |
} |
@@ -249,46 +363,46 @@ Handle<Code> Pipeline::GenerateCode() { |
{ |
// Lower JSOperators where we can determine types. |
PhaseScope phase_scope(pipeline_statistics.get(), "typed lowering"); |
- SourcePositionTable::Scope pos(&source_positions, |
+ SourcePositionTable::Scope pos(data.source_positions(), |
SourcePosition::Unknown()); |
- ValueNumberingReducer vn_reducer(zone()); |
- JSTypedLowering lowering(&jsgraph); |
- SimplifiedOperatorReducer simple_reducer(&jsgraph); |
- GraphReducer graph_reducer(&graph); |
+ ValueNumberingReducer vn_reducer(data.graph_zone()); |
+ JSTypedLowering lowering(data.jsgraph()); |
+ SimplifiedOperatorReducer simple_reducer(data.jsgraph()); |
+ GraphReducer graph_reducer(data.graph()); |
graph_reducer.AddReducer(&vn_reducer); |
graph_reducer.AddReducer(&lowering); |
graph_reducer.AddReducer(&simple_reducer); |
graph_reducer.ReduceGraph(); |
- VerifyAndPrintGraph(&graph, "Lowered typed"); |
+ VerifyAndPrintGraph(data.graph(), "Lowered typed"); |
} |
{ |
// Lower simplified operators and insert changes. |
PhaseScope phase_scope(pipeline_statistics.get(), "simplified lowering"); |
- SourcePositionTable::Scope pos(&source_positions, |
+ SourcePositionTable::Scope pos(data.source_positions(), |
SourcePosition::Unknown()); |
- SimplifiedLowering lowering(&jsgraph); |
+ SimplifiedLowering lowering(data.jsgraph()); |
lowering.LowerAllNodes(); |
- ValueNumberingReducer vn_reducer(zone()); |
- SimplifiedOperatorReducer simple_reducer(&jsgraph); |
- GraphReducer graph_reducer(&graph); |
+ ValueNumberingReducer vn_reducer(data.graph_zone()); |
+ SimplifiedOperatorReducer simple_reducer(data.jsgraph()); |
+ GraphReducer graph_reducer(data.graph()); |
graph_reducer.AddReducer(&vn_reducer); |
graph_reducer.AddReducer(&simple_reducer); |
graph_reducer.ReduceGraph(); |
- VerifyAndPrintGraph(&graph, "Lowered simplified"); |
+ VerifyAndPrintGraph(data.graph(), "Lowered simplified"); |
} |
{ |
// Lower changes that have been inserted before. |
PhaseScope phase_scope(pipeline_statistics.get(), "change lowering"); |
- SourcePositionTable::Scope pos(&source_positions, |
+ SourcePositionTable::Scope pos(data.source_positions(), |
SourcePosition::Unknown()); |
Linkage linkage(info()); |
- ValueNumberingReducer vn_reducer(zone()); |
- SimplifiedOperatorReducer simple_reducer(&jsgraph); |
- ChangeLowering lowering(&jsgraph, &linkage); |
- MachineOperatorReducer mach_reducer(&jsgraph); |
- GraphReducer graph_reducer(&graph); |
+ ValueNumberingReducer vn_reducer(data.graph_zone()); |
+ SimplifiedOperatorReducer simple_reducer(data.jsgraph()); |
+ ChangeLowering lowering(data.jsgraph(), &linkage); |
+ MachineOperatorReducer mach_reducer(data.jsgraph()); |
+ GraphReducer graph_reducer(data.graph()); |
// TODO(titzer): Figure out if we should run all reducers at once here. |
graph_reducer.AddReducer(&vn_reducer); |
graph_reducer.AddReducer(&simple_reducer); |
@@ -297,53 +411,49 @@ Handle<Code> Pipeline::GenerateCode() { |
graph_reducer.ReduceGraph(); |
// TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
- VerifyAndPrintGraph(&graph, "Lowered changes", true); |
+ VerifyAndPrintGraph(data.graph(), "Lowered changes", true); |
} |
{ |
PhaseScope phase_scope(pipeline_statistics.get(), "control reduction"); |
- SourcePositionTable::Scope pos(&source_positions, |
+ SourcePositionTable::Scope pos(data.source_positions(), |
SourcePosition::Unknown()); |
- ZonePool::Scope zone_scope(&zone_pool); |
- ControlReducer::ReduceGraph(zone_scope.zone(), &jsgraph, &common); |
+ ZonePool::Scope zone_scope(data.zone_pool()); |
+ ControlReducer::ReduceGraph(zone_scope.zone(), data.jsgraph(), |
+ data.common()); |
- VerifyAndPrintGraph(&graph, "Control reduced"); |
+ VerifyAndPrintGraph(data.graph(), "Control reduced"); |
} |
} |
{ |
// Lower any remaining generic JSOperators. |
PhaseScope phase_scope(pipeline_statistics.get(), "generic lowering"); |
- SourcePositionTable::Scope pos(&source_positions, |
+ SourcePositionTable::Scope pos(data.source_positions(), |
SourcePosition::Unknown()); |
- JSGenericLowering lowering(info(), &jsgraph); |
- GraphReducer graph_reducer(&graph); |
+ JSGenericLowering lowering(info(), data.jsgraph()); |
+ GraphReducer graph_reducer(data.graph()); |
graph_reducer.AddReducer(&lowering); |
graph_reducer.ReduceGraph(); |
// TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
- VerifyAndPrintGraph(&graph, "Lowered generic", true); |
+ VerifyAndPrintGraph(data.graph(), "Lowered generic", true); |
} |
if (!pipeline_statistics.is_empty()) { |
pipeline_statistics->BeginPhaseKind("block building"); |
} |
- source_positions.RemoveDecorator(); |
+ data.source_positions()->RemoveDecorator(); |
- Schedule* schedule; |
- { |
- PhaseScope phase_scope(pipeline_statistics.get(), "scheduling"); |
- // Compute a schedule. |
- schedule = ComputeSchedule(&zone_pool, &graph); |
- } |
+ // Compute a schedule. |
+ ComputeSchedule(&data); |
Handle<Code> code = Handle<Code>::null(); |
{ |
// Generate optimized code. |
Linkage linkage(info()); |
- code = GenerateCode(pipeline_statistics.get(), &zone_pool, &linkage, &graph, |
- schedule, &source_positions); |
+ code = GenerateCode(&linkage, &data); |
info()->SetCode(code); |
} |
@@ -362,11 +472,13 @@ Handle<Code> Pipeline::GenerateCode() { |
} |
-Schedule* Pipeline::ComputeSchedule(ZonePool* zone_pool, Graph* graph) { |
- Schedule* schedule = Scheduler::ComputeSchedule(zone_pool, graph); |
+void Pipeline::ComputeSchedule(PipelineData* data) { |
+ PhaseScope phase_scope(data->pipeline_statistics(), "scheduling"); |
+ Schedule* schedule = |
+ Scheduler::ComputeSchedule(data->zone_pool(), data->graph()); |
TraceSchedule(schedule); |
if (VerifyGraphs()) ScheduleVerifier::Run(schedule); |
- return schedule; |
+ data->set_schedule(schedule); |
} |
@@ -375,16 +487,16 @@ Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage, |
Schedule* schedule) { |
ZonePool zone_pool(isolate()); |
CHECK(SupportedBackend()); |
+ PipelineData data(graph, schedule, &zone_pool); |
if (schedule == NULL) { |
// TODO(rossberg): Should this really be untyped? |
VerifyAndPrintGraph(graph, "Machine", true); |
- schedule = ComputeSchedule(&zone_pool, graph); |
+ ComputeSchedule(&data); |
+ } else { |
+ TraceSchedule(schedule); |
} |
- TraceSchedule(schedule); |
- SourcePositionTable source_positions(graph); |
- Handle<Code> code = GenerateCode(NULL, &zone_pool, linkage, graph, schedule, |
- &source_positions); |
+ Handle<Code> code = GenerateCode(linkage, &data); |
#if ENABLE_DISASSEMBLER |
if (!code.is_null() && FLAG_print_opt_code) { |
CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); |
@@ -396,29 +508,27 @@ Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage, |
} |
-Handle<Code> Pipeline::GenerateCode(PipelineStatistics* pipeline_statistics, |
- ZonePool* zone_pool, Linkage* linkage, |
- Graph* graph, Schedule* schedule, |
- SourcePositionTable* source_positions) { |
- DCHECK_NOT_NULL(graph); |
+Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) { |
DCHECK_NOT_NULL(linkage); |
- DCHECK_NOT_NULL(schedule); |
+ DCHECK_NOT_NULL(data->graph()); |
+ DCHECK_NOT_NULL(data->schedule()); |
CHECK(SupportedBackend()); |
BasicBlockProfiler::Data* profiler_data = NULL; |
if (FLAG_turbo_profiling) { |
- profiler_data = BasicBlockInstrumentor::Instrument(info_, graph, schedule); |
+ profiler_data = BasicBlockInstrumentor::Instrument(info(), data->graph(), |
+ data->schedule()); |
} |
- Zone* instruction_zone = schedule->zone(); |
- InstructionSequence sequence(instruction_zone, graph, schedule); |
+ InstructionSequence sequence(data->instruction_zone(), data->graph(), |
+ data->schedule()); |
// Select and schedule instructions covering the scheduled graph. |
{ |
- PhaseScope phase_scope(pipeline_statistics, "select instructions"); |
- ZonePool::Scope zone_scope(zone_pool); |
+ PhaseScope phase_scope(data->pipeline_statistics(), "select instructions"); |
+ ZonePool::Scope zone_scope(data->zone_pool()); |
InstructionSelector selector(zone_scope.zone(), linkage, &sequence, |
- schedule, source_positions); |
+ data->schedule(), data->source_positions()); |
selector.SelectInstructions(); |
} |
@@ -427,25 +537,28 @@ Handle<Code> Pipeline::GenerateCode(PipelineStatistics* pipeline_statistics, |
os << "----- Instruction sequence before register allocation -----\n" |
<< sequence; |
TurboCfgFile tcf(isolate()); |
- tcf << AsC1V("CodeGen", schedule, source_positions, &sequence); |
+ tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(), |
+ &sequence); |
} |
- if (pipeline_statistics != NULL) { |
- pipeline_statistics->BeginPhaseKind("register allocation"); |
+ data->DeleteGraphZone(); |
+ |
+ if (data->pipeline_statistics() != NULL) { |
+ data->pipeline_statistics()->BeginPhaseKind("register allocation"); |
} |
// Allocate registers. |
Frame frame; |
{ |
- int node_count = graph->NodeCount(); |
+ int node_count = sequence.VirtualRegisterCount(); |
if (node_count > UnallocatedOperand::kMaxVirtualRegisters) { |
linkage->info()->AbortOptimization(kNotEnoughVirtualRegistersForValues); |
return Handle<Code>::null(); |
} |
- ZonePool::Scope zone_scope(zone_pool); |
+ ZonePool::Scope zone_scope(data->zone_pool()); |
RegisterAllocator allocator(zone_scope.zone(), &frame, linkage->info(), |
&sequence); |
- if (!allocator.Allocate(pipeline_statistics)) { |
+ if (!allocator.Allocate(data->pipeline_statistics())) { |
linkage->info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); |
return Handle<Code>::null(); |
} |
@@ -461,14 +574,14 @@ Handle<Code> Pipeline::GenerateCode(PipelineStatistics* pipeline_statistics, |
<< sequence; |
} |
- if (pipeline_statistics != NULL) { |
- pipeline_statistics->BeginPhaseKind("code generation"); |
+ if (data->pipeline_statistics() != NULL) { |
+ data->pipeline_statistics()->BeginPhaseKind("code generation"); |
} |
// Generate native sequence. |
Handle<Code> code; |
{ |
- PhaseScope phase_scope(pipeline_statistics, "generate code"); |
+ PhaseScope phase_scope(data->pipeline_statistics(), "generate code"); |
CodeGenerator generator(&frame, linkage, &sequence); |
code = generator.GenerateCode(); |
} |