[turbofan] refactor pipeline to use hydrogen like Run calls
authordcarney <dcarney@chromium.org>
Fri, 14 Nov 2014 16:44:38 +0000 (08:44 -0800)
committerCommit bot <commit-bot@chromium.org>
Fri, 14 Nov 2014 16:44:45 +0000 (16:44 +0000)
BUG=

Review URL: https://codereview.chromium.org/727733002

Cr-Commit-Position: refs/heads/master@{#25361}

src/compiler/ast-graph-builder.h
src/compiler/frame.h
src/compiler/instruction.h
src/compiler/pipeline.cc
src/compiler/pipeline.h
test/cctest/compiler/test-codegen-deopt.cc
test/cctest/compiler/test-instruction.cc
test/unittests/compiler/register-allocator-unittest.cc

index d076b5a..dfa4b93 100644 (file)
@@ -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();
index df9a01f..f99d7bd 100644 (file)
@@ -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);
 };
 
 
index 0a5b5eb..d6245d5 100644 (file)
@@ -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);
 };
 
 
index a05e2b3..e940198 100644 (file)
@@ -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;
 }
 
 
index 7811300..629426f 100644 (file)
@@ -42,17 +42,25 @@ class Pipeline {
 
  private:
   CompilationInfo* info_;
+  PipelineData* data_;
+
+  // Helpers for executing pipeline phases.
+  template <typename Phase>
+  void Run();
+  template <typename Phase, typename Arg0>
+  void Run(Arg0 arg_0);
+  template <typename Phase, typename Arg0, typename Arg1>
+  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<Code> 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_
index 974b423..65acfcc 100644 (file)
@@ -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);
index 041e6d8..294812f 100644 (file)
@@ -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) {
index 074789b..6866389 100644 (file)
@@ -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<BlockCompletion> Completions;
 
   SmartPointer<RegisterConfiguration> config_;
-  SmartPointer<Frame> frame_;
+  Frame* frame_;
   SmartPointer<RegisterAllocator> allocator_;
-  SmartPointer<InstructionSequence> sequence_;
+  InstructionSequence* sequence_;
   int num_general_registers_;
   int num_double_registers_;