| 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"; }
|
| +
|
| + 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;
|
| }
|
|
|
|
|
|
|