Chromium Code Reviews| Index: src/compiler/pipeline.cc |
| diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc |
| index a05e2b3e382657ebbe83e1e1ed0bdd7e333ad48a..e940198ac3bf5ed724b7ab9320021fc8a5e89c5d 100644 |
| --- a/src/compiler/pipeline.cc |
| +++ b/src/compiler/pipeline.cc |
| @@ -43,12 +43,15 @@ namespace compiler { |
| class PipelineData { |
| public: |
| - explicit PipelineData(CompilationInfo* info, ZonePool* zone_pool, |
| - PipelineStatistics* pipeline_statistics) |
| + PipelineData(CompilationInfo* info, ZonePool* zone_pool, |
| + PipelineStatistics* pipeline_statistics) |
| : 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())), |
| @@ -61,28 +64,38 @@ class PipelineData { |
| jsgraph_(new (graph_zone()) |
| JSGraph(graph(), common(), javascript(), machine())), |
| typer_(new Typer(graph(), info->context())), |
| - schedule_(NULL), |
| + context_node_(nullptr), |
| + schedule_(nullptr), |
| instruction_zone_scope_(zone_pool_), |
| - instruction_zone_(instruction_zone_scope_.zone()) {} |
| + 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()), |
| - outer_zone_(NULL), |
| + info_(nullptr), |
| + outer_zone_(nullptr), |
| zone_pool_(zone_pool), |
| - pipeline_statistics_(NULL), |
| + pipeline_statistics_(nullptr), |
| + compilation_failed_(false), |
| + code_(Handle<Code>::null()), |
| graph_zone_scope_(zone_pool_), |
| - graph_zone_(NULL), |
| + graph_zone_(nullptr), |
| graph_(graph), |
| source_positions_(new SourcePositionTable(graph)), |
| - machine_(NULL), |
| - common_(NULL), |
| - javascript_(NULL), |
| - jsgraph_(NULL), |
| - typer_(NULL), |
| + machine_(nullptr), |
| + common_(nullptr), |
| + javascript_(nullptr), |
| + jsgraph_(nullptr), |
| + typer_(nullptr), |
| + context_node_(nullptr), |
| schedule_(schedule), |
| instruction_zone_scope_(zone_pool_), |
| - instruction_zone_(instruction_zone_scope_.zone()) {} |
| + instruction_zone_(instruction_zone_scope_.zone()), |
| + sequence_(nullptr), |
| + frame_(nullptr) {} |
| ~PipelineData() { |
| DeleteInstructionZone(); |
| @@ -90,8 +103,19 @@ 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_; } |
| + bool compilation_failed() const { return compilation_failed_; } |
| + void set_compilation_failed() { compilation_failed_ = true; } |
| + Handle<Code> code() { return code_; } |
| + void set_code(Handle<Code> code) { |
| + DCHECK(code_.is_null()); |
| + code_ = code; |
| + } |
| + |
| + // RawMachineAssembler generally produces graphs which cannot be verified. |
| + bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; } |
| Zone* graph_zone() const { return graph_zone_; } |
| Graph* graph() const { return graph_; } |
| @@ -103,43 +127,64 @@ class PipelineData { |
| JSOperatorBuilder* javascript() const { return javascript_; } |
| JSGraph* jsgraph() const { return jsgraph_; } |
| Typer* typer() const { return typer_.get(); } |
| + |
| + Node* context_node() const { return context_node_; } |
| + void set_context_node(Node* context_node) { |
| + DCHECK_EQ(nullptr, context_node_); |
| + context_node_ = context_node; |
| + } |
| + |
| Schedule* schedule() const { return schedule_; } |
| void set_schedule(Schedule* schedule) { |
| - DCHECK_EQ(NULL, schedule_); |
| + DCHECK_EQ(nullptr, schedule_); |
| schedule_ = schedule; |
| } |
| Zone* instruction_zone() const { return instruction_zone_; } |
| - // RawMachineAssembler generally produces graphs which cannot be verified. |
| - bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; } |
| + 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; |
| + } |
| void DeleteGraphZone() { |
| // Destroy objects with destructors first. |
| - source_positions_.Reset(NULL); |
| - typer_.Reset(NULL); |
| - if (graph_zone_ == NULL) return; |
| + source_positions_.Reset(nullptr); |
| + typer_.Reset(nullptr); |
| + if (graph_zone_ == nullptr) 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; |
| + graph_zone_ = nullptr; |
| + graph_ = nullptr; |
| + machine_ = nullptr; |
| + common_ = nullptr; |
| + javascript_ = nullptr; |
| + jsgraph_ = nullptr; |
| + context_node_ = nullptr; |
| + schedule_ = nullptr; |
| } |
| void DeleteInstructionZone() { |
| - if (instruction_zone_ == NULL) return; |
| + if (instruction_zone_ == nullptr) return; |
| instruction_zone_scope_.Destroy(); |
| - instruction_zone_ = NULL; |
| + instruction_zone_ = nullptr; |
| + sequence_ = nullptr; |
| + frame_ = nullptr; |
| } |
| private: |
| Isolate* isolate_; |
| + CompilationInfo* info_; |
| Zone* outer_zone_; |
| ZonePool* zone_pool_; |
| PipelineStatistics* pipeline_statistics_; |
| + bool compilation_failed_; |
| + Handle<Code> code_; |
| ZonePool::Scope graph_zone_scope_; |
| Zone* graph_zone_; |
| @@ -154,6 +199,7 @@ class PipelineData { |
| JSGraph* jsgraph_; |
| // TODO(dcarney): make this into a ZoneObject. |
| SmartPointer<Typer> typer_; |
| + Node* context_node_; |
| Schedule* schedule_; |
| // All objects in the following group of fields are allocated in |
| @@ -161,6 +207,8 @@ class PipelineData { |
| // destroyed. |
| ZonePool::Scope instruction_zone_scope_; |
| Zone* instruction_zone_; |
| + InstructionSequence* sequence_; |
| + Frame* frame_; |
| DISALLOW_COPY_AND_ASSIGN(PipelineData); |
| }; |
| @@ -182,18 +230,335 @@ struct TurboCfgFile : public std::ofstream { |
| }; |
| -void Pipeline::VerifyAndPrintGraph( |
| - Graph* graph, const char* phase, bool untyped) { |
| - if (FLAG_trace_turbo) { |
| +static void TraceSchedule(Schedule* schedule) { |
| + if (!FLAG_trace_turbo) return; |
| + OFStream os(stdout); |
| + os << "-- Schedule --------------------------------------\n" << *schedule; |
| +} |
| + |
| + |
| +static SmartArrayPointer<char> GetDebugName(CompilationInfo* info) { |
| + SmartArrayPointer<char> name; |
| + if (info->IsStub()) { |
| + if (info->code_stub() != NULL) { |
| + CodeStub::Major major_key = info->code_stub()->MajorKey(); |
| + const char* major_name = CodeStub::MajorName(major_key, false); |
| + size_t len = strlen(major_name); |
| + name.Reset(new char[len]); |
| + memcpy(name.get(), major_name, len); |
| + } |
| + } else { |
| + AllowHandleDereference allow_deref; |
| + name = info->function()->debug_name()->ToCString(); |
| + } |
| + return name; |
| +} |
| + |
| + |
| +class AstGraphBuilderWithPositions : public AstGraphBuilder { |
| + public: |
| + explicit AstGraphBuilderWithPositions(Zone* local_zone, CompilationInfo* info, |
| + JSGraph* jsgraph, |
| + SourcePositionTable* source_positions) |
| + : AstGraphBuilder(local_zone, info, jsgraph), |
| + source_positions_(source_positions) {} |
| + |
| + bool CreateGraph() { |
| + SourcePositionTable::Scope pos(source_positions_, |
| + SourcePosition::Unknown()); |
| + return AstGraphBuilder::CreateGraph(); |
| + } |
| + |
| +#define DEF_VISIT(type) \ |
| + virtual void Visit##type(type* node) OVERRIDE { \ |
| + SourcePositionTable::Scope pos(source_positions_, \ |
| + SourcePosition(node->position())); \ |
| + AstGraphBuilder::Visit##type(node); \ |
| + } |
| + AST_NODE_LIST(DEF_VISIT) |
| +#undef DEF_VISIT |
| + |
| + Node* GetFunctionContext() { return AstGraphBuilder::GetFunctionContext(); } |
| + |
| + private: |
| + SourcePositionTable* source_positions_; |
| +}; |
| + |
| + |
| +class PipelineRunScope { |
| + public: |
| + PipelineRunScope(PipelineData* data, const char* phase_name) |
| + : phase_scope_( |
| + phase_name == nullptr ? nullptr : data->pipeline_statistics(), |
| + phase_name), |
| + zone_scope_(data->zone_pool()) {} |
| + |
| + Zone* zone() { return zone_scope_.zone(); } |
| + |
| + private: |
| + PhaseScope phase_scope_; |
| + ZonePool::Scope zone_scope_; |
| +}; |
| + |
| + |
| +template <typename Phase> |
| +void Pipeline::Run() { |
| + PipelineRunScope scope(this->data_, Phase::phase_name()); |
| + Phase phase; |
| + phase.Run(this->data_, scope.zone()); |
| +} |
| + |
| + |
| +template <typename Phase, typename Arg0> |
| +void Pipeline::Run(Arg0 arg_0) { |
| + PipelineRunScope scope(this->data_, Phase::phase_name()); |
| + Phase phase; |
| + phase.Run(this->data_, scope.zone(), 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"; } |
|
titzer
2014/11/14 16:07:47
You can just make these static fields.
|
| + |
| + void Run(PipelineData* data, Zone* temp_zone) { |
| + AstGraphBuilderWithPositions graph_builder( |
| + temp_zone, data->info(), data->jsgraph(), data->source_positions()); |
| + if (graph_builder.CreateGraph()) { |
| + data->set_context_node(graph_builder.GetFunctionContext()); |
| + } else { |
| + data->set_compilation_failed(); |
| + } |
| + } |
| +}; |
| + |
| + |
| +struct ContextSpecializerPhase { |
| + static const char* phase_name() { return nullptr; } |
| + |
| + void Run(PipelineData* data, Zone* temp_zone) { |
| + SourcePositionTable::Scope pos(data->source_positions(), |
| + SourcePosition::Unknown()); |
| + JSContextSpecializer spec(data->info(), data->jsgraph(), |
| + data->context_node()); |
| + spec.SpecializeToContext(); |
| + } |
| +}; |
| + |
| + |
| +struct InliningPhase { |
| + static const char* phase_name() { return "inlining"; } |
| + |
| + void Run(PipelineData* data, Zone* temp_zone) { |
| + SourcePositionTable::Scope pos(data->source_positions(), |
| + SourcePosition::Unknown()); |
| + JSInliner inliner(temp_zone, data->info(), data->jsgraph()); |
| + inliner.Inline(); |
| + } |
| +}; |
| + |
| + |
| +struct TyperPhase { |
| + static const char* phase_name() { return "typer"; } |
| + |
| + void Run(PipelineData* data, Zone* temp_zone) { data->typer()->Run(); } |
| +}; |
| + |
| + |
| +struct TypedLoweringPhase { |
| + static const char* phase_name() { return "typed lowering"; } |
| + |
| + void Run(PipelineData* data, Zone* temp_zone) { |
| + SourcePositionTable::Scope pos(data->source_positions(), |
| + SourcePosition::Unknown()); |
| + 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(); |
| + } |
| +}; |
| + |
| + |
| +struct SimplifiedLoweringPhase { |
| + static const char* phase_name() { return "simplified lowering"; } |
| + |
| + void Run(PipelineData* data, Zone* temp_zone) { |
| + SourcePositionTable::Scope pos(data->source_positions(), |
| + SourcePosition::Unknown()); |
| + SimplifiedLowering lowering(data->jsgraph()); |
| + lowering.LowerAllNodes(); |
| + 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(); |
| + } |
| +}; |
| + |
| + |
| +struct ChangeLoweringPhase { |
| + static const char* phase_name() { return "change lowering"; } |
| + |
| + void Run(PipelineData* data, Zone* temp_zone) { |
| + SourcePositionTable::Scope pos(data->source_positions(), |
| + SourcePosition::Unknown()); |
| + Linkage linkage(data->graph_zone(), data->info()); |
| + 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); |
| + graph_reducer.AddReducer(&lowering); |
| + graph_reducer.AddReducer(&mach_reducer); |
| + graph_reducer.ReduceGraph(); |
| + } |
| +}; |
| + |
| + |
| +struct ControlReductionPhase { |
| + void Run(PipelineData* data, Zone* temp_zone) { |
| + SourcePositionTable::Scope pos(data->source_positions(), |
| + SourcePosition::Unknown()); |
| + ControlReducer::ReduceGraph(temp_zone, data->jsgraph(), data->common()); |
| + } |
| +}; |
| + |
| + |
| +struct EarlyControlReductionPhase : ControlReductionPhase { |
| + static const char* phase_name() { return "early control reduction"; } |
| +}; |
| + |
| + |
| +struct LateControlReductionPhase : ControlReductionPhase { |
| + static const char* phase_name() { return "late control reduction"; } |
| +}; |
| + |
| + |
| +struct GenericLoweringPhase { |
| + static const char* phase_name() { return "generic lowering"; } |
| + |
| + void Run(PipelineData* data, Zone* temp_zone) { |
| + SourcePositionTable::Scope pos(data->source_positions(), |
| + SourcePosition::Unknown()); |
| + JSGenericLowering generic(data->info(), data->jsgraph()); |
| + SelectLowering select(data->jsgraph()->graph(), data->jsgraph()->common()); |
| + GraphReducer graph_reducer(data->graph()); |
| + graph_reducer.AddReducer(&generic); |
| + graph_reducer.AddReducer(&select); |
| + graph_reducer.ReduceGraph(); |
| + } |
| +}; |
| + |
| + |
| +struct ComputeSchedulePhase { |
| + static const char* phase_name() { return "scheduling"; } |
| + |
| + void Run(PipelineData* data, Zone* temp_zone) { |
| + Schedule* schedule = Scheduler::ComputeSchedule(temp_zone, data->graph()); |
| + TraceSchedule(schedule); |
| + if (VerifyGraphs()) ScheduleVerifier::Run(schedule); |
| + data->set_schedule(schedule); |
| + } |
| +}; |
| + |
| + |
| +struct InstructionSelectionPhase { |
| + static const char* phase_name() { return "select instructions"; } |
| + |
| + void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) { |
| + InstructionSelector selector(temp_zone, data->graph(), linkage, |
| + data->sequence(), data->schedule(), |
| + data->source_positions()); |
| + selector.SelectInstructions(); |
| + } |
| +}; |
| + |
| + |
| +// TODO(dcarney): break this up. |
| +struct RegisterAllocationPhase { |
| + static const char* phase_name() { return nullptr; } |
| + |
| + void Run(PipelineData* data, Zone* temp_zone) { |
| + int node_count = data->sequence()->VirtualRegisterCount(); |
| + if (node_count > UnallocatedOperand::kMaxVirtualRegisters) { |
| + data->set_compilation_failed(); |
| + return; |
| + } |
| + |
| + 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()); |
| + |
| + if (!allocator.Allocate(data->pipeline_statistics())) { |
| + data->set_compilation_failed(); |
| + return; |
| + } |
| + |
| + 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 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); |
| + data->set_code(generator.GenerateCode()); |
| + } |
| +}; |
| + |
| + |
| +struct PrintGraphPhase { |
| + static const char* phase_name() { return nullptr; } |
| + |
| + void Run(PipelineData* data, Zone* temp_zone, const char* phase) { |
| + CompilationInfo* info = data->info(); |
| + Graph* graph = data->graph(); |
| char buffer[256]; |
| Vector<char> filename(buffer, sizeof(buffer)); |
| SmartArrayPointer<char> functionname; |
| - if (!info_->shared_info().is_null()) { |
| - functionname = info_->shared_info()->DebugName()->ToCString(); |
| + if (!info->shared_info().is_null()) { |
| + functionname = info->shared_info()->DebugName()->ToCString(); |
| if (strlen(functionname.get()) > 0) { |
| SNPrintF(filename, "turbo-%s-%s", functionname.get(), phase); |
| } else { |
| - SNPrintF(filename, "turbo-%p-%s", static_cast<void*>(info_), phase); |
| + SNPrintF(filename, "turbo-%p-%s", static_cast<void*>(info), phase); |
| } |
| } else { |
| SNPrintF(filename, "turbo-none-%s", phase); |
| @@ -221,63 +586,27 @@ void Pipeline::VerifyAndPrintGraph( |
| os << "-- " << phase << " graph printed to file " << filename.start() |
| << "\n"; |
| } |
| - if (VerifyGraphs()) { |
| - Verifier::Run(graph, |
| - FLAG_turbo_types && !untyped ? Verifier::TYPED : Verifier::UNTYPED); |
| - } |
| -} |
| +}; |
| -class AstGraphBuilderWithPositions : public AstGraphBuilder { |
| - public: |
| - explicit AstGraphBuilderWithPositions(Zone* local_zone, CompilationInfo* info, |
| - JSGraph* jsgraph, |
| - SourcePositionTable* source_positions) |
| - : AstGraphBuilder(local_zone, info, jsgraph), |
| - source_positions_(source_positions) {} |
| +struct VerifyGraphPhase { |
| + static const char* phase_name() { return nullptr; } |
| - bool CreateGraph() { |
| - SourcePositionTable::Scope pos(source_positions_, |
| - SourcePosition::Unknown()); |
| - return AstGraphBuilder::CreateGraph(); |
| - } |
| - |
| -#define DEF_VISIT(type) \ |
| - virtual void Visit##type(type* node) OVERRIDE { \ |
| - SourcePositionTable::Scope pos(source_positions_, \ |
| - SourcePosition(node->position())); \ |
| - AstGraphBuilder::Visit##type(node); \ |
| + void Run(PipelineData* data, Zone* temp_zone, const bool untyped) { |
| + Verifier::Run(data->graph(), FLAG_turbo_types && !untyped |
| + ? Verifier::TYPED |
| + : Verifier::UNTYPED); |
| } |
| - AST_NODE_LIST(DEF_VISIT) |
| -#undef DEF_VISIT |
| - |
| - private: |
| - SourcePositionTable* source_positions_; |
| }; |
| -static void TraceSchedule(Schedule* schedule) { |
| - if (!FLAG_trace_turbo) return; |
| - OFStream os(stdout); |
| - os << "-- Schedule --------------------------------------\n" << *schedule; |
| -} |
| - |
| - |
| -static SmartArrayPointer<char> GetDebugName(CompilationInfo* info) { |
| - SmartArrayPointer<char> name; |
| - if (info->IsStub()) { |
| - if (info->code_stub() != NULL) { |
| - CodeStub::Major major_key = info->code_stub()->MajorKey(); |
| - const char* major_name = CodeStub::MajorName(major_key, false); |
| - size_t len = strlen(major_name); |
| - name.Reset(new char[len]); |
| - memcpy(name.get(), major_name, len); |
| - } |
| - } else { |
| - AllowHandleDereference allow_deref; |
| - name = info->function()->debug_name()->ToCString(); |
| +void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) { |
| + if (FLAG_trace_turbo) { |
| + Run<PrintGraphPhase>(phase); |
| + } |
| + if (VerifyGraphs()) { |
| + Run<VerifyGraphPhase>(untyped); |
| } |
| - return name; |
| } |
| @@ -297,13 +626,16 @@ Handle<Code> Pipeline::GenerateCode() { |
| } |
| ZonePool zone_pool(isolate()); |
| - |
| SmartPointer<PipelineStatistics> pipeline_statistics; |
| + |
| 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()); |
| + this->data_ = &data; |
| + |
| if (FLAG_trace_turbo) { |
| OFStream os(stdout); |
| os << "---------------------------------------------------\n" |
| @@ -313,56 +645,28 @@ Handle<Code> Pipeline::GenerateCode() { |
| tcf << AsC1VCompilation(info()); |
| } |
| - // 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(data.zone_pool()); |
| - AstGraphBuilderWithPositions graph_builder( |
| - zone_scope.zone(), info(), data.jsgraph(), data.source_positions()); |
| - if (!graph_builder.CreateGraph()) return Handle<Code>::null(); |
| - context_node = graph_builder.GetFunctionContext(); |
| - } |
| - |
| - VerifyAndPrintGraph(data.graph(), "Initial untyped", true); |
| + Run<GraphBuilderPhase>(); |
| + if (data.compilation_failed()) return Handle<Code>::null(); |
| + RunPrintAndVerify("Initial untyped", true); |
| - { |
| - PhaseScope phase_scope(pipeline_statistics.get(), |
| - "early control reduction"); |
| - SourcePositionTable::Scope pos(data.source_positions(), |
| - SourcePosition::Unknown()); |
| - ZonePool::Scope zone_scope(data.zone_pool()); |
| - ControlReducer::ReduceGraph(zone_scope.zone(), data.jsgraph(), |
| - data.common()); |
| - |
| - VerifyAndPrintGraph(data.graph(), "Early Control reduced", true); |
| - } |
| + Run<EarlyControlReductionPhase>(); |
| + RunPrintAndVerify("Early Control reduced", true); |
| if (info()->is_context_specializing()) { |
| - SourcePositionTable::Scope pos(data.source_positions(), |
| - SourcePosition::Unknown()); |
| // Specialize the code to the context as aggressively as possible. |
| - JSContextSpecializer spec(info(), data.jsgraph(), context_node); |
| - spec.SpecializeToContext(); |
| - VerifyAndPrintGraph(data.graph(), "Context specialized", true); |
| + Run<ContextSpecializerPhase>(); |
| + RunPrintAndVerify("Context specialized", true); |
| } |
| if (info()->is_inlining_enabled()) { |
| - PhaseScope phase_scope(pipeline_statistics.get(), "inlining"); |
| - SourcePositionTable::Scope pos(data.source_positions(), |
| - SourcePosition::Unknown()); |
| - ZonePool::Scope zone_scope(data.zone_pool()); |
| - JSInliner inliner(zone_scope.zone(), info(), data.jsgraph()); |
| - inliner.Inline(); |
| - VerifyAndPrintGraph(data.graph(), "Inlined", true); |
| + Run<InliningPhase>(); |
| + RunPrintAndVerify("Inlined", true); |
| } |
| - // Print a replay of the initial graph. |
| if (FLAG_print_turbo_replay) { |
| + // Print a replay of the initial graph. |
| GraphReplayPrinter::PrintReplay(data.graph()); |
| } |
| @@ -370,118 +674,54 @@ Handle<Code> Pipeline::GenerateCode() { |
| if (!SupportedTarget()) return Handle<Code>::null(); |
| if (info()->is_typing_enabled()) { |
| - { |
| - // Type the graph. |
| - PhaseScope phase_scope(pipeline_statistics.get(), "typer"); |
| - data.typer()->Run(); |
| - VerifyAndPrintGraph(data.graph(), "Typed"); |
| - } |
| + // Type the graph. |
| + Run<TyperPhase>(); |
| + RunPrintAndVerify("Typed"); |
| } |
| if (!pipeline_statistics.is_empty()) { |
| - pipeline_statistics->BeginPhaseKind("lowering"); |
| + data.pipeline_statistics()->BeginPhaseKind("lowering"); |
| } |
| if (info()->is_typing_enabled()) { |
| - { |
| - // Lower JSOperators where we can determine types. |
| - PhaseScope phase_scope(pipeline_statistics.get(), "typed lowering"); |
| - SourcePositionTable::Scope pos(data.source_positions(), |
| - SourcePosition::Unknown()); |
| - 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(data.graph(), "Lowered typed"); |
| - } |
| - { |
| - // Lower simplified operators and insert changes. |
| - PhaseScope phase_scope(pipeline_statistics.get(), "simplified lowering"); |
| - SourcePositionTable::Scope pos(data.source_positions(), |
| - SourcePosition::Unknown()); |
| - SimplifiedLowering lowering(data.jsgraph()); |
| - lowering.LowerAllNodes(); |
| - 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(data.graph(), "Lowered simplified"); |
| - } |
| - { |
| - // Lower changes that have been inserted before. |
| - PhaseScope phase_scope(pipeline_statistics.get(), "change lowering"); |
| - SourcePositionTable::Scope pos(data.source_positions(), |
| - SourcePosition::Unknown()); |
| - Linkage linkage(data.graph_zone(), info()); |
| - 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); |
| - graph_reducer.AddReducer(&lowering); |
| - graph_reducer.AddReducer(&mach_reducer); |
| - graph_reducer.ReduceGraph(); |
| - |
| - // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
| - VerifyAndPrintGraph(data.graph(), "Lowered changes", true); |
| - } |
| + // Lower JSOperators where we can determine types. |
| + Run<TypedLoweringPhase>(); |
| + RunPrintAndVerify("Lowered typed"); |
| - { |
| - PhaseScope phase_scope(pipeline_statistics.get(), |
| - "late control reduction"); |
| - SourcePositionTable::Scope pos(data.source_positions(), |
| - SourcePosition::Unknown()); |
| - ZonePool::Scope zone_scope(data.zone_pool()); |
| - ControlReducer::ReduceGraph(zone_scope.zone(), data.jsgraph(), |
| - data.common()); |
| - |
| - VerifyAndPrintGraph(data.graph(), "Late Control reduced"); |
| - } |
| - } |
| + // Lower simplified operators and insert changes. |
| + Run<SimplifiedLoweringPhase>(); |
| + RunPrintAndVerify("Lowered simplified"); |
| - { |
| - // Lower any remaining generic JSOperators. |
| - PhaseScope phase_scope(pipeline_statistics.get(), "generic lowering"); |
| - SourcePositionTable::Scope pos(data.source_positions(), |
| - SourcePosition::Unknown()); |
| - JSGenericLowering generic(info(), data.jsgraph()); |
| - SelectLowering select(data.jsgraph()->graph(), data.jsgraph()->common()); |
| - GraphReducer graph_reducer(data.graph()); |
| - graph_reducer.AddReducer(&generic); |
| - graph_reducer.AddReducer(&select); |
| - graph_reducer.ReduceGraph(); |
| + // Lower changes that have been inserted before. |
| + Run<ChangeLoweringPhase>(); |
| + // // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
| + RunPrintAndVerify("Lowered changes", true); |
| - // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
| - VerifyAndPrintGraph(data.graph(), "Lowered generic", true); |
| + Run<LateControlReductionPhase>(); |
| + RunPrintAndVerify("Late Control reduced"); |
| } |
| + // Lower any remaining generic JSOperators. |
| + Run<GenericLoweringPhase>(); |
| + // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
| + RunPrintAndVerify("Lowered generic", true); |
| + |
| if (!pipeline_statistics.is_empty()) { |
| - pipeline_statistics->BeginPhaseKind("block building"); |
| + data.pipeline_statistics()->BeginPhaseKind("block building"); |
| } |
| data.source_positions()->RemoveDecorator(); |
| // Compute a schedule. |
| - ComputeSchedule(&data); |
| + Run<ComputeSchedulePhase>(); |
| - Handle<Code> code = Handle<Code>::null(); |
| { |
| // Generate optimized code. |
| Linkage linkage(data.instruction_zone(), info()); |
| - code = GenerateCode(&linkage, &data); |
| - info()->SetCode(code); |
| + GenerateCode(&linkage); |
| } |
| + Handle<Code> code = data.code(); |
| + info()->SetCode(code); |
| // Print optimized code. |
| v8::internal::CodeGenerator::PrintCode(code, info()); |
| @@ -497,32 +737,24 @@ Handle<Code> Pipeline::GenerateCode() { |
| } |
| -void Pipeline::ComputeSchedule(PipelineData* data) { |
| - PhaseScope phase_scope(data->pipeline_statistics(), "scheduling"); |
| - ZonePool::Scope zone_scope(data->zone_pool()); |
| - Schedule* schedule = |
| - Scheduler::ComputeSchedule(zone_scope.zone(), data->graph()); |
| - TraceSchedule(schedule); |
| - if (VerifyGraphs()) ScheduleVerifier::Run(schedule); |
| - data->set_schedule(schedule); |
| -} |
| - |
| - |
| Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage, |
| Graph* graph, |
| Schedule* schedule) { |
| ZonePool zone_pool(isolate()); |
| CHECK(SupportedBackend()); |
| PipelineData data(graph, schedule, &zone_pool); |
| + this->data_ = &data; |
| if (schedule == NULL) { |
| // TODO(rossberg): Should this really be untyped? |
| - VerifyAndPrintGraph(graph, "Machine", true); |
| - ComputeSchedule(&data); |
| + RunPrintAndVerify("Machine", true); |
| + Run<ComputeSchedulePhase>(); |
| } else { |
| TraceSchedule(schedule); |
| } |
| - Handle<Code> code = GenerateCode(linkage, &data); |
| + GenerateCode(linkage); |
| + Handle<Code> code = data.code(); |
| + |
| #if ENABLE_DISASSEMBLER |
| if (!code.is_null() && FLAG_print_opt_code) { |
| CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); |
| @@ -534,7 +766,9 @@ Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage, |
| } |
| -Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) { |
| +void Pipeline::GenerateCode(Linkage* linkage) { |
| + PipelineData* data = this->data_; |
| + |
| DCHECK_NOT_NULL(linkage); |
| DCHECK_NOT_NULL(data->graph()); |
| DCHECK_NOT_NULL(data->schedule()); |
| @@ -549,22 +783,16 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) { |
| InstructionBlocks* instruction_blocks = |
| InstructionSequence::InstructionBlocksFor(data->instruction_zone(), |
| data->schedule()); |
| - InstructionSequence sequence(data->instruction_zone(), instruction_blocks); |
| + data->set_sequence(new (data->instruction_zone()) InstructionSequence( |
| + data->instruction_zone(), instruction_blocks)); |
| // Select and schedule instructions covering the scheduled graph. |
| - { |
| - PhaseScope phase_scope(data->pipeline_statistics(), "select instructions"); |
| - ZonePool::Scope zone_scope(data->zone_pool()); |
| - InstructionSelector selector(zone_scope.zone(), data->graph(), linkage, |
| - &sequence, data->schedule(), |
| - data->source_positions()); |
| - selector.SelectInstructions(); |
| - } |
| + Run<InstructionSelectionPhase>(linkage); |
| if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { |
| TurboCfgFile tcf(isolate()); |
| tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(), |
| - &sequence); |
| + data->sequence()); |
| } |
| data->DeleteGraphZone(); |
| @@ -577,43 +805,15 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) { |
| // Don't track usage for this zone in compiler stats. |
| Zone verifier_zone(info()->isolate()); |
| RegisterAllocatorVerifier verifier( |
| - &verifier_zone, RegisterConfiguration::ArchDefault(), &sequence); |
| + &verifier_zone, RegisterConfiguration::ArchDefault(), data->sequence()); |
| #endif |
| // Allocate registers. |
| - Frame frame; |
| - { |
| - int node_count = sequence.VirtualRegisterCount(); |
| - if (node_count > UnallocatedOperand::kMaxVirtualRegisters) { |
| - info()->AbortOptimization(kNotEnoughVirtualRegistersForValues); |
| - return Handle<Code>::null(); |
| - } |
| - ZonePool::Scope zone_scope(data->zone_pool()); |
| - |
| - SmartArrayPointer<char> debug_name; |
| -#ifdef DEBUG |
| - debug_name = GetDebugName(info()); |
| -#endif |
| - |
| - RegisterAllocator allocator(RegisterConfiguration::ArchDefault(), |
| - zone_scope.zone(), &frame, &sequence, |
| - debug_name.get()); |
| - if (!allocator.Allocate(data->pipeline_statistics())) { |
| - info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); |
| - return Handle<Code>::null(); |
| - } |
| - if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { |
| - TurboCfgFile tcf(isolate()); |
| - tcf << AsC1VAllocator("CodeGen", &allocator); |
| - } |
| - } |
| - |
| - if (FLAG_trace_turbo) { |
| - OFStream os(stdout); |
| - PrintableInstructionSequence printable = { |
| - RegisterConfiguration::ArchDefault(), &sequence}; |
| - os << "----- Instruction sequence after register allocation -----\n" |
| - << printable; |
| + data->set_frame(new (data->instruction_zone()) Frame); |
| + Run<RegisterAllocationPhase>(); |
| + if (data->compilation_failed()) { |
| + info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); |
| + return; |
| } |
| #ifdef DEBUG |
| @@ -626,20 +826,15 @@ Handle<Code> Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) { |
| } |
| // Generate native sequence. |
| - Handle<Code> code; |
| - { |
| - PhaseScope phase_scope(data->pipeline_statistics(), "generate code"); |
| - CodeGenerator generator(&frame, linkage, &sequence, info()); |
| - code = generator.GenerateCode(); |
| - } |
| + Run<GenerateCodePhase>(linkage, info()); |
| + |
| if (profiler_data != NULL) { |
| #if ENABLE_DISASSEMBLER |
| std::ostringstream os; |
| - code->Disassemble(NULL, os); |
| + data->code()->Disassemble(NULL, os); |
| profiler_data->SetCode(&os); |
| #endif |
| } |
| - return code; |
| } |