Index: src/compiler/pipeline.cc |
diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc |
index e940198ac3bf5ed724b7ab9320021fc8a5e89c5d..ca2acc77788a6b2167fb2b36c03ebf1d41c9ca03 100644 |
--- a/src/compiler/pipeline.cc |
+++ b/src/compiler/pipeline.cc |
@@ -43,39 +43,9 @@ namespace compiler { |
class PipelineData { |
public: |
- PipelineData(CompilationInfo* info, ZonePool* zone_pool, |
- PipelineStatistics* pipeline_statistics) |
+ explicit PipelineData(ZonePool* zone_pool, CompilationInfo* info) |
: isolate_(info->zone()->isolate()), |
info_(info), |
- outer_zone_(info->zone()), |
- zone_pool_(zone_pool), |
- pipeline_statistics_(pipeline_statistics), |
- compilation_failed_(false), |
- code_(Handle<Code>::null()), |
- 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( |
- graph_zone(), 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())), |
- context_node_(nullptr), |
- schedule_(nullptr), |
- instruction_zone_scope_(zone_pool_), |
- instruction_zone_(instruction_zone_scope_.zone()), |
- sequence_(nullptr), |
- frame_(nullptr) {} |
- |
- |
- // For machine graph testing only. |
- PipelineData(Graph* graph, Schedule* schedule, ZonePool* zone_pool) |
- : isolate_(graph->zone()->isolate()), |
- info_(nullptr), |
outer_zone_(nullptr), |
zone_pool_(zone_pool), |
pipeline_statistics_(nullptr), |
@@ -83,25 +53,57 @@ class PipelineData { |
code_(Handle<Code>::null()), |
graph_zone_scope_(zone_pool_), |
graph_zone_(nullptr), |
- graph_(graph), |
- source_positions_(new SourcePositionTable(graph)), |
+ graph_(nullptr), |
machine_(nullptr), |
common_(nullptr), |
javascript_(nullptr), |
jsgraph_(nullptr), |
typer_(nullptr), |
context_node_(nullptr), |
- schedule_(schedule), |
+ schedule_(nullptr), |
instruction_zone_scope_(zone_pool_), |
- instruction_zone_(instruction_zone_scope_.zone()), |
+ instruction_zone_(nullptr), |
sequence_(nullptr), |
- frame_(nullptr) {} |
+ frame_(nullptr), |
+ register_allocator_(nullptr) {} |
~PipelineData() { |
DeleteInstructionZone(); |
DeleteGraphZone(); |
} |
+ // For main entry point. |
+ void Initialize(PipelineStatistics* pipeline_statistics) { |
+ outer_zone_ = info()->zone(); |
+ pipeline_statistics_ = pipeline_statistics; |
+ graph_zone_ = graph_zone_scope_.zone(); |
+ graph_ = new (graph_zone()) Graph(graph_zone()); |
+ source_positions_.Reset(new SourcePositionTable(graph())); |
+ machine_ = new (graph_zone()) MachineOperatorBuilder( |
+ graph_zone(), 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_.Reset(new Typer(graph(), info()->context())); |
+ instruction_zone_ = instruction_zone_scope_.zone(); |
+ } |
+ |
+ // For machine graph testing entry point. |
+ void Initialize(Graph* graph, Schedule* schedule) { |
Benedikt Meurer
2014/11/17 11:35:28
append ForTesting to name.
|
+ graph_ = graph; |
+ source_positions_.Reset(new SourcePositionTable(graph)); |
+ schedule_ = schedule; |
+ instruction_zone_ = instruction_zone_scope_.zone(); |
+ } |
+ |
+ // For register allocation entry point. |
+ void Initialize(InstructionSequence* sequence) { |
+ instruction_zone_ = sequence->zone(); |
+ sequence_ = sequence; |
+ } |
+ |
Isolate* isolate() const { return isolate_; } |
CompilationInfo* info() const { return info_; } |
ZonePool* zone_pool() const { return zone_pool_; } |
@@ -142,15 +144,8 @@ class PipelineData { |
Zone* instruction_zone() const { return instruction_zone_; } |
InstructionSequence* sequence() const { return sequence_; } |
- void set_sequence(InstructionSequence* sequence) { |
- DCHECK_EQ(nullptr, sequence_); |
- sequence_ = sequence; |
- } |
Frame* frame() const { return frame_; } |
- void set_frame(Frame* frame) { |
- DCHECK_EQ(nullptr, frame_); |
- frame_ = frame; |
- } |
+ RegisterAllocator* register_allocator() const { return register_allocator_; } |
void DeleteGraphZone() { |
// Destroy objects with destructors first. |
@@ -175,13 +170,33 @@ class PipelineData { |
instruction_zone_ = nullptr; |
sequence_ = nullptr; |
frame_ = nullptr; |
+ register_allocator_ = nullptr; |
+ } |
+ |
+ void InitializeInstructionSequence() { |
+ DCHECK_EQ(nullptr, sequence_); |
+ InstructionBlocks* instruction_blocks = |
+ InstructionSequence::InstructionBlocksFor(instruction_zone(), |
+ schedule()); |
+ sequence_ = new (instruction_zone()) |
+ InstructionSequence(instruction_zone(), instruction_blocks); |
+ } |
+ |
+ void InitializeRegisterAllocator(Zone* local_zone, |
+ const RegisterConfiguration* config, |
+ const char* debug_name) { |
+ DCHECK_EQ(nullptr, register_allocator_); |
+ DCHECK_EQ(nullptr, frame_); |
+ frame_ = new (instruction_zone()) Frame(); |
+ register_allocator_ = new (instruction_zone()) |
+ RegisterAllocator(config, local_zone, frame(), sequence(), debug_name); |
} |
private: |
Isolate* isolate_; |
CompilationInfo* info_; |
Zone* outer_zone_; |
- ZonePool* zone_pool_; |
+ ZonePool* const zone_pool_; |
PipelineStatistics* pipeline_statistics_; |
bool compilation_failed_; |
Handle<Code> code_; |
@@ -209,6 +224,7 @@ class PipelineData { |
Zone* instruction_zone_; |
InstructionSequence* sequence_; |
Frame* frame_; |
+ RegisterAllocator* register_allocator_; |
DISALLOW_COPY_AND_ASSIGN(PipelineData); |
}; |
@@ -317,15 +333,6 @@ void Pipeline::Run(Arg0 arg_0) { |
} |
-// TODO(dcarney): this one should be unecessary. |
-template <typename Phase, typename Arg0, typename Arg1> |
-void Pipeline::Run(Arg0 arg_0, Arg1 arg_1) { |
- PipelineRunScope scope(this->data_, Phase::phase_name()); |
- Phase phase; |
- phase.Run(this->data_, scope.zone(), arg_0, arg_1); |
-} |
- |
- |
struct GraphBuilderPhase { |
static const char* phase_name() { return "graph builder"; } |
@@ -490,45 +497,74 @@ struct InstructionSelectionPhase { |
}; |
-// TODO(dcarney): break this up. |
-struct RegisterAllocationPhase { |
- static const char* phase_name() { return nullptr; } |
+struct MeetRegisterConstraintsPhase { |
+ static const char* phase_name() { return "meet register constraints"; } |
void Run(PipelineData* data, Zone* temp_zone) { |
- int node_count = data->sequence()->VirtualRegisterCount(); |
- if (node_count > UnallocatedOperand::kMaxVirtualRegisters) { |
- data->set_compilation_failed(); |
- return; |
- } |
+ data->register_allocator()->MeetRegisterConstraints(); |
+ } |
+}; |
- SmartArrayPointer<char> debug_name; |
-#ifdef DEBUG |
- if (data->info() != nullptr) { |
- debug_name = GetDebugName(data->info()); |
- } |
-#endif |
- RegisterAllocator allocator(RegisterConfiguration::ArchDefault(), temp_zone, |
- data->frame(), data->sequence(), |
- debug_name.get()); |
+struct ResolvePhisPhase { |
+ static const char* phase_name() { return "resolve phis"; } |
- if (!allocator.Allocate(data->pipeline_statistics())) { |
- data->set_compilation_failed(); |
- return; |
- } |
+ void Run(PipelineData* data, Zone* temp_zone) { |
+ data->register_allocator()->ResolvePhis(); |
+ } |
+}; |
- if (FLAG_trace_turbo) { |
- OFStream os(stdout); |
- PrintableInstructionSequence printable = { |
- RegisterConfiguration::ArchDefault(), data->sequence()}; |
- os << "----- Instruction sequence after register allocation -----\n" |
- << printable; |
- } |
- if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { |
- TurboCfgFile tcf(data->isolate()); |
- tcf << AsC1VAllocator("CodeGen", &allocator); |
- } |
+struct BuildLiveRangesPhase { |
+ static const char* phase_name() { return "build live ranges"; } |
+ |
+ void Run(PipelineData* data, Zone* temp_zone) { |
+ data->register_allocator()->BuildLiveRanges(); |
+ } |
+}; |
+ |
+ |
+struct AllocateGeneralRegistersPhase { |
+ static const char* phase_name() { return "allocate general registers"; } |
+ |
+ void Run(PipelineData* data, Zone* temp_zone) { |
+ data->register_allocator()->AllocateGeneralRegisters(); |
+ } |
+}; |
+ |
+ |
+struct AllocateDoubleRegistersPhase { |
+ static const char* phase_name() { return "allocate double registers"; } |
+ |
+ void Run(PipelineData* data, Zone* temp_zone) { |
+ data->register_allocator()->AllocateDoubleRegisters(); |
+ } |
+}; |
+ |
+ |
+struct PopulatePointerMapsPhase { |
+ static const char* phase_name() { return "populate pointer maps"; } |
+ |
+ void Run(PipelineData* data, Zone* temp_zone) { |
+ data->register_allocator()->PopulatePointerMaps(); |
+ } |
+}; |
+ |
+ |
+struct ConnectRangesPhase { |
+ static const char* phase_name() { return "connect ranges"; } |
+ |
+ void Run(PipelineData* data, Zone* temp_zone) { |
+ data->register_allocator()->ConnectRanges(); |
+ } |
+}; |
+ |
+ |
+struct ResolveControlFlowPhase { |
+ static const char* phase_name() { return "resolve control flow"; } |
+ |
+ void Run(PipelineData* data, Zone* temp_zone) { |
+ data->register_allocator()->ResolveControlFlow(); |
} |
}; |
@@ -536,9 +572,9 @@ struct RegisterAllocationPhase { |
struct GenerateCodePhase { |
static const char* phase_name() { return "generate code"; } |
- void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage, |
- CompilationInfo* info) { |
- CodeGenerator generator(data->frame(), linkage, data->sequence(), info); |
+ void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) { |
+ CodeGenerator generator(data->frame(), linkage, data->sequence(), |
+ data->info()); |
data->set_code(generator.GenerateCode()); |
} |
}; |
@@ -600,6 +636,13 @@ struct VerifyGraphPhase { |
}; |
+void Pipeline::BeginPhaseKind(const char* phase_kind_name) { |
+ if (data_->pipeline_statistics() != NULL) { |
+ data_->pipeline_statistics()->BeginPhaseKind("phase_kind_name"); |
+ } |
+} |
+ |
+ |
void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) { |
if (FLAG_trace_turbo) { |
Run<PrintGraphPhase>(phase); |
@@ -630,12 +673,14 @@ Handle<Code> Pipeline::GenerateCode() { |
if (FLAG_turbo_stats) { |
pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool)); |
- pipeline_statistics->BeginPhaseKind("graph creation"); |
} |
- PipelineData data(info(), &zone_pool, pipeline_statistics.get()); |
+ PipelineData data(&zone_pool, info()); |
this->data_ = &data; |
+ BeginPhaseKind("graph creation"); |
+ data.Initialize(pipeline_statistics.get()); |
+ |
if (FLAG_trace_turbo) { |
OFStream os(stdout); |
os << "---------------------------------------------------\n" |
@@ -679,9 +724,7 @@ Handle<Code> Pipeline::GenerateCode() { |
RunPrintAndVerify("Typed"); |
} |
- if (!pipeline_statistics.is_empty()) { |
- data.pipeline_statistics()->BeginPhaseKind("lowering"); |
- } |
+ BeginPhaseKind("lowering"); |
if (info()->is_typing_enabled()) { |
// Lower JSOperators where we can determine types. |
@@ -706,9 +749,7 @@ Handle<Code> Pipeline::GenerateCode() { |
// TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
RunPrintAndVerify("Lowered generic", true); |
- if (!pipeline_statistics.is_empty()) { |
- data.pipeline_statistics()->BeginPhaseKind("block building"); |
- } |
+ BeginPhaseKind("block building"); |
data.source_positions()->RemoveDecorator(); |
@@ -742,7 +783,8 @@ Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage, |
Schedule* schedule) { |
ZonePool zone_pool(isolate()); |
CHECK(SupportedBackend()); |
- PipelineData data(graph, schedule, &zone_pool); |
+ PipelineData data(&zone_pool, info()); |
+ data.Initialize(graph, schedule); |
this->data_ = &data; |
if (schedule == NULL) { |
// TODO(rossberg): Should this really be untyped? |
@@ -766,6 +808,20 @@ Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage, |
} |
+bool Pipeline::AllocateRegisters(const RegisterConfiguration* config, |
+ InstructionSequence* sequence, |
+ bool run_verifier) { |
+ CompilationInfo info(sequence->zone()->isolate(), sequence->zone()); |
+ ZonePool zone_pool(sequence->zone()->isolate()); |
+ PipelineData data(&zone_pool, &info); |
+ data.Initialize(sequence); |
+ Pipeline pipeline(&info); |
+ pipeline.data_ = &data; |
+ pipeline.AllocateRegisters(config, run_verifier); |
+ return !data.compilation_failed(); |
+} |
+ |
+ |
void Pipeline::GenerateCode(Linkage* linkage) { |
PipelineData* data = this->data_; |
@@ -780,11 +836,7 @@ void Pipeline::GenerateCode(Linkage* linkage) { |
data->schedule()); |
} |
- InstructionBlocks* instruction_blocks = |
- InstructionSequence::InstructionBlocksFor(data->instruction_zone(), |
- data->schedule()); |
- data->set_sequence(new (data->instruction_zone()) InstructionSequence( |
- data->instruction_zone(), instruction_blocks)); |
+ data->InitializeInstructionSequence(); |
// Select and schedule instructions covering the scheduled graph. |
Run<InstructionSelectionPhase>(linkage); |
@@ -797,36 +849,23 @@ void Pipeline::GenerateCode(Linkage* linkage) { |
data->DeleteGraphZone(); |
- if (data->pipeline_statistics() != NULL) { |
- data->pipeline_statistics()->BeginPhaseKind("register allocation"); |
- } |
+ BeginPhaseKind("register allocation"); |
+ bool run_verifier = false; |
#ifdef DEBUG |
- // Don't track usage for this zone in compiler stats. |
- Zone verifier_zone(info()->isolate()); |
- RegisterAllocatorVerifier verifier( |
- &verifier_zone, RegisterConfiguration::ArchDefault(), data->sequence()); |
+ run_verifier = true; |
#endif |
- |
// Allocate registers. |
- data->set_frame(new (data->instruction_zone()) Frame); |
- Run<RegisterAllocationPhase>(); |
+ AllocateRegisters(RegisterConfiguration::ArchDefault(), run_verifier); |
if (data->compilation_failed()) { |
info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); |
return; |
} |
-#ifdef DEBUG |
- verifier.VerifyAssignment(); |
- verifier.VerifyGapMoves(); |
-#endif |
- |
- if (data->pipeline_statistics() != NULL) { |
- data->pipeline_statistics()->BeginPhaseKind("code generation"); |
- } |
+ BeginPhaseKind("code generation"); |
// Generate native sequence. |
- Run<GenerateCodePhase>(linkage, info()); |
+ Run<GenerateCodePhase>(linkage); |
if (profiler_data != NULL) { |
#if ENABLE_DISASSEMBLER |
@@ -838,6 +877,77 @@ void Pipeline::GenerateCode(Linkage* linkage) { |
} |
+void Pipeline::AllocateRegisters(const RegisterConfiguration* config, |
+ bool run_verifier) { |
+ PipelineData* data = this->data_; |
+ |
+ int node_count = data->sequence()->VirtualRegisterCount(); |
+ if (node_count > UnallocatedOperand::kMaxVirtualRegisters) { |
+ data->set_compilation_failed(); |
+ return; |
+ } |
+ |
+ // Don't track usage for this zone in compiler stats. |
+ SmartPointer<Zone> verifier_zone; |
+ RegisterAllocatorVerifier* verifier = nullptr; |
+ if (run_verifier) { |
+ verifier_zone.Reset(new Zone(info()->isolate())); |
+ verifier = new (verifier_zone.get()) RegisterAllocatorVerifier( |
+ verifier_zone.get(), config, data->sequence()); |
+ } |
+ |
+ SmartArrayPointer<char> debug_name; |
+#ifdef DEBUG |
+ debug_name = GetDebugName(data->info()); |
+#endif |
+ |
+ ZonePool::Scope zone_scope(data->zone_pool()); |
+ data->InitializeRegisterAllocator(zone_scope.zone(), config, |
+ debug_name.get()); |
+ |
+ Run<MeetRegisterConstraintsPhase>(); |
+ Run<ResolvePhisPhase>(); |
+ Run<BuildLiveRangesPhase>(); |
+ if (FLAG_trace_turbo) { |
+ OFStream os(stdout); |
+ PrintableInstructionSequence printable = {config, data->sequence()}; |
+ os << "----- Instruction sequence before register allocation -----\n" |
+ << printable; |
+ } |
+ DCHECK(!data->register_allocator()->ExistsUseWithoutDefinition()); |
+ Run<AllocateGeneralRegistersPhase>(); |
+ if (!data->register_allocator()->AllocationOk()) { |
+ data->set_compilation_failed(); |
+ return; |
+ } |
+ Run<AllocateDoubleRegistersPhase>(); |
+ if (!data->register_allocator()->AllocationOk()) { |
+ data->set_compilation_failed(); |
+ return; |
+ } |
+ Run<PopulatePointerMapsPhase>(); |
+ Run<ConnectRangesPhase>(); |
+ Run<ResolveControlFlowPhase>(); |
+ |
+ if (FLAG_trace_turbo) { |
+ OFStream os(stdout); |
+ PrintableInstructionSequence printable = {config, data->sequence()}; |
+ os << "----- Instruction sequence after register allocation -----\n" |
+ << printable; |
+ } |
+ |
+ if (verifier != nullptr) { |
+ verifier->VerifyAssignment(); |
+ verifier->VerifyGapMoves(); |
+ } |
+ |
+ if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { |
+ TurboCfgFile tcf(data->isolate()); |
+ tcf << AsC1VAllocator("CodeGen", data->register_allocator()); |
+ } |
+} |
+ |
+ |
void Pipeline::SetUp() { |
InstructionOperand::SetUpCaches(); |
} |