From: dcarney Date: Fri, 14 Nov 2014 16:44:38 +0000 (-0800) Subject: [turbofan] refactor pipeline to use hydrogen like Run calls X-Git-Tag: upstream/4.7.83~5679 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c97a7acf6548b84cad53ad0684a1381c3cebea34;p=platform%2Fupstream%2Fv8.git [turbofan] refactor pipeline to use hydrogen like Run calls BUG= Review URL: https://codereview.chromium.org/727733002 Cr-Commit-Position: refs/heads/master@{#25361} --- diff --git a/src/compiler/ast-graph-builder.h b/src/compiler/ast-graph-builder.h index d076b5a..dfa4b93 100644 --- a/src/compiler/ast-graph-builder.h +++ b/src/compiler/ast-graph-builder.h @@ -58,10 +58,6 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor { typedef StructuredGraphBuilder::Environment BaseEnvironment; virtual BaseEnvironment* CopyEnvironment(BaseEnvironment* env) OVERRIDE; - // TODO(mstarzinger): The pipeline only needs to be a friend to access the - // function context. Remove as soon as the context is a parameter. - friend class Pipeline; - // Getters for values in the activation record. Node* GetFunctionClosure(); Node* GetFunctionContext(); diff --git a/src/compiler/frame.h b/src/compiler/frame.h index df9a01f..f99d7bd 100644 --- a/src/compiler/frame.h +++ b/src/compiler/frame.h @@ -17,7 +17,7 @@ namespace compiler { // registers for a compiled function. Frames are usually populated by the // register allocator and are used by Linkage to generate code for the prologue // and epilogue to compiled code. -class Frame { +class Frame : public ZoneObject { public: Frame() : register_save_area_size_(0), @@ -69,6 +69,8 @@ class Frame { int double_spill_slot_count_; BitVector* allocated_registers_; BitVector* allocated_double_registers_; + + DISALLOW_COPY_AND_ASSIGN(Frame); }; diff --git a/src/compiler/instruction.h b/src/compiler/instruction.h index 0a5b5eb..d6245d5 100644 --- a/src/compiler/instruction.h +++ b/src/compiler/instruction.h @@ -889,7 +889,7 @@ struct PrintableInstructionSequence; // Represents architecture-specific generated code before, during, and after // register allocation. // TODO(titzer): s/IsDouble/IsFloat64/ -class InstructionSequence FINAL { +class InstructionSequence FINAL : public ZoneObject { public: static InstructionBlocks* InstructionBlocksFor(Zone* zone, const Schedule* schedule); @@ -1015,6 +1015,8 @@ class InstructionSequence FINAL { VirtualRegisterSet doubles_; VirtualRegisterSet references_; DeoptimizationVector deoptimization_entries_; + + DISALLOW_COPY_AND_ASSIGN(InstructionSequence); }; diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc index a05e2b3..e940198 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::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::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() { return code_; } + void set_code(Handle 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_; 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_; + 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 GetDebugName(CompilationInfo* info) { + SmartArrayPointer 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 +void Pipeline::Run() { + PipelineRunScope scope(this->data_, Phase::phase_name()); + Phase phase; + phase.Run(this->data_, scope.zone()); +} + + +template +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 +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"; } + + 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 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 filename(buffer, sizeof(buffer)); SmartArrayPointer 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(info_), phase); + SNPrintF(filename, "turbo-%p-%s", static_cast(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 GetDebugName(CompilationInfo* info) { - SmartArrayPointer 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(phase); + } + if (VerifyGraphs()) { + Run(untyped); } - return name; } @@ -297,13 +626,16 @@ Handle Pipeline::GenerateCode() { } ZonePool zone_pool(isolate()); - SmartPointer 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 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::null(); - context_node = graph_builder.GetFunctionContext(); - } - - VerifyAndPrintGraph(data.graph(), "Initial untyped", true); + Run(); + if (data.compilation_failed()) return Handle::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(); + 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(); + 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(); + 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 Pipeline::GenerateCode() { if (!SupportedTarget()) return Handle::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(); + 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(); + 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(); + 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(); + // // 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(); + RunPrintAndVerify("Late Control reduced"); } + // Lower any remaining generic JSOperators. + Run(); + // 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(); - Handle code = Handle::null(); { // Generate optimized code. Linkage linkage(data.instruction_zone(), info()); - code = GenerateCode(&linkage, &data); - info()->SetCode(code); + GenerateCode(&linkage); } + Handle code = data.code(); + info()->SetCode(code); // Print optimized code. v8::internal::CodeGenerator::PrintCode(code, info()); @@ -497,32 +737,24 @@ Handle 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 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(); } else { TraceSchedule(schedule); } - Handle code = GenerateCode(linkage, &data); + GenerateCode(linkage); + Handle 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 Pipeline::GenerateCodeForMachineGraph(Linkage* linkage, } -Handle 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 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(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 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::null(); - } - ZonePool::Scope zone_scope(data->zone_pool()); - - SmartArrayPointer 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::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(); + if (data->compilation_failed()) { + info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); + return; } #ifdef DEBUG @@ -626,20 +826,15 @@ Handle Pipeline::GenerateCode(Linkage* linkage, PipelineData* data) { } // Generate native sequence. - Handle code; - { - PhaseScope phase_scope(data->pipeline_statistics(), "generate code"); - CodeGenerator generator(&frame, linkage, &sequence, info()); - code = generator.GenerateCode(); - } + Run(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; } diff --git a/src/compiler/pipeline.h b/src/compiler/pipeline.h index 7811300..629426f 100644 --- a/src/compiler/pipeline.h +++ b/src/compiler/pipeline.h @@ -42,17 +42,25 @@ class Pipeline { private: CompilationInfo* info_; + PipelineData* data_; + + // Helpers for executing pipeline phases. + template + void Run(); + template + void Run(Arg0 arg_0); + template + void Run(Arg0 arg_0, Arg1 arg_1); CompilationInfo* info() const { return info_; } Isolate* isolate() { return info_->isolate(); } - void ComputeSchedule(PipelineData* data); - void VerifyAndPrintGraph(Graph* graph, const char* phase, - bool untyped = false); - Handle GenerateCode(Linkage* linkage, PipelineData* data); + void RunPrintAndVerify(const char* phase, bool untyped = false); + void GenerateCode(Linkage* linkage); }; -} -} -} // namespace v8::internal::compiler + +} // namespace compiler +} // namespace internal +} // namespace v8 #endif // V8_COMPILER_PIPELINE_H_ diff --git a/test/cctest/compiler/test-codegen-deopt.cc b/test/cctest/compiler/test-codegen-deopt.cc index 974b423..65acfcc 100644 --- a/test/cctest/compiler/test-codegen-deopt.cc +++ b/test/cctest/compiler/test-codegen-deopt.cc @@ -56,7 +56,7 @@ class DeoptCodegenTester { graph = new (scope_->main_zone()) Graph(scope_->main_zone()); } - virtual ~DeoptCodegenTester() { delete code; } + virtual ~DeoptCodegenTester() {} void GenerateCodeFromSchedule(Schedule* schedule) { OFStream os(stdout); @@ -68,7 +68,8 @@ class DeoptCodegenTester { Linkage* linkage = new (scope_->main_zone()) Linkage(info.zone(), &info); InstructionBlocks* instruction_blocks = TestInstrSeq::InstructionBlocksFor(scope_->main_zone(), schedule); - code = new TestInstrSeq(scope_->main_zone(), instruction_blocks); + code = new (scope_->main_zone()) + TestInstrSeq(scope_->main_zone(), instruction_blocks); SourcePositionTable source_positions(graph); InstructionSelector selector(scope_->main_zone(), graph, linkage, code, schedule, &source_positions); diff --git a/test/cctest/compiler/test-instruction.cc b/test/cctest/compiler/test-instruction.cc index 041e6d8..294812f 100644 --- a/test/cctest/compiler/test-instruction.cc +++ b/test/cctest/compiler/test-instruction.cc @@ -36,8 +36,6 @@ class InstructionTester : public HandleAndZoneScope { machine(zone()), code(NULL) {} - ~InstructionTester() { delete code; } - Isolate* isolate; Graph graph; Schedule schedule; @@ -57,7 +55,7 @@ class InstructionTester : public HandleAndZoneScope { } InstructionBlocks* instruction_blocks = TestInstrSeq::InstructionBlocksFor(main_zone(), &schedule); - code = new TestInstrSeq(main_zone(), instruction_blocks); + code = new (main_zone()) TestInstrSeq(main_zone(), instruction_blocks); } Node* Int32Constant(int32_t val) { diff --git a/test/unittests/compiler/register-allocator-unittest.cc b/test/unittests/compiler/register-allocator-unittest.cc index 074789b..6866389 100644 --- a/test/unittests/compiler/register-allocator-unittest.cc +++ b/test/unittests/compiler/register-allocator-unittest.cc @@ -124,7 +124,9 @@ class RegisterAllocatorTest : public TestWithZone { } RegisterAllocatorTest() - : num_general_registers_(kDefaultNRegs), + : frame_(nullptr), + sequence_(nullptr), + num_general_registers_(kDefaultNRegs), num_double_registers_(kDefaultNRegs), instruction_blocks_(zone()), current_instruction_index_(-1), @@ -151,17 +153,18 @@ class RegisterAllocatorTest : public TestWithZone { } Frame* frame() { - if (frame_.is_empty()) { - frame_.Reset(new Frame()); + if (frame_ == nullptr) { + frame_ = new (zone()) Frame(); } - return frame_.get(); + return frame_; } InstructionSequence* sequence() { - if (sequence_.is_empty()) { - sequence_.Reset(new InstructionSequence(zone(), &instruction_blocks_)); + if (sequence_ == nullptr) { + sequence_ = + new (zone()) InstructionSequence(zone(), &instruction_blocks_); } - return sequence_.get(); + return sequence_; } RegisterAllocator* allocator() { @@ -516,9 +519,9 @@ class RegisterAllocatorTest : public TestWithZone { typedef std::vector Completions; SmartPointer config_; - SmartPointer frame_; + Frame* frame_; SmartPointer allocator_; - SmartPointer sequence_; + InstructionSequence* sequence_; int num_general_registers_; int num_double_registers_;