Add copy support in inliner.
authorsigurds@chromium.org <sigurds@chromium.org>
Tue, 9 Sep 2014 13:20:09 +0000 (13:20 +0000)
committersigurds@chromium.org <sigurds@chromium.org>
Tue, 9 Sep 2014 13:20:09 +0000 (13:20 +0000)
Refactors JSGraph to ensure that the zone operators are created in
can be different from the Graph's zone.

R=mstarzinger@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23804 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

14 files changed:
src/compiler/change-lowering-unittest.cc
src/compiler/generic-graph.h
src/compiler/js-graph.h
src/compiler/js-inlining.cc
src/compiler/machine-operator-reducer-unittest.cc
src/compiler/pipeline.cc
src/compiler/simplified-operator-reducer-unittest.cc
test/cctest/compiler/test-changes-lowering.cc
test/cctest/compiler/test-js-constant-cache.cc
test/cctest/compiler/test-js-context-specialization.cc
test/cctest/compiler/test-js-typed-lowering.cc
test/cctest/compiler/test-machine-operator-reducer.cc
test/cctest/compiler/test-representation-change.cc
test/cctest/compiler/test-simplified-lowering.cc

index 1978476..9d56331 100644 (file)
@@ -74,10 +74,12 @@ class ChangeLoweringTest : public GraphTest {
 
   Reduction Reduce(Node* node) {
     Typer typer(zone());
-    JSGraph jsgraph(graph(), common(), &typer);
+    MachineOperatorBuilder machine(zone(), WordRepresentation());
+    JSOperatorBuilder javascript(zone());
+    JSGraph jsgraph(graph(), common(), &javascript, &typer, &machine);
     CompilationInfo info(isolate(), zone());
     Linkage linkage(&info);
-    MachineOperatorBuilder machine(zone(), WordRepresentation());
+
     ChangeLowering reducer(&jsgraph, &linkage, &machine);
     return reducer.Reduce(node);
   }
index e8de9eb..a555456 100644 (file)
@@ -22,7 +22,6 @@ class GenericGraphBase : public ZoneObject {
 
   NodeId NextNodeID() { return next_node_id_++; }
   NodeId NodeCount() const { return next_node_id_; }
-  void SetNextNodeId(NodeId next) { next_node_id_ = next; }
 
  private:
   Zone* zone_;
index 71d6434..99a6a06 100644 (file)
@@ -9,6 +9,7 @@
 #include "src/compiler/common-operator.h"
 #include "src/compiler/graph.h"
 #include "src/compiler/js-operator.h"
+#include "src/compiler/machine-operator.h"
 #include "src/compiler/node-properties.h"
 
 namespace v8 {
@@ -22,11 +23,14 @@ class Typer;
 // constants, and various helper methods.
 class JSGraph : public ZoneObject {
  public:
-  JSGraph(Graph* graph, CommonOperatorBuilder* common, Typer* typer)
+  JSGraph(Graph* graph, CommonOperatorBuilder* common,
+          JSOperatorBuilder* javascript, Typer* typer,
+          MachineOperatorBuilder* machine)
       : graph_(graph),
         common_(common),
-        javascript_(zone()),
+        javascript_(javascript),
         typer_(typer),
+        machine_(machine),
         cache_(zone()) {}
 
   // Canonicalized global constants.
@@ -73,8 +77,9 @@ class JSGraph : public ZoneObject {
     return Constant(immediate);
   }
 
-  JSOperatorBuilder* javascript() { return &javascript_; }
+  JSOperatorBuilder* javascript() { return javascript_; }
   CommonOperatorBuilder* common() { return common_; }
+  MachineOperatorBuilder* machine() { return machine_; }
   Graph* graph() { return graph_; }
   Zone* zone() { return graph()->zone(); }
   Isolate* isolate() { return zone()->isolate(); }
@@ -82,8 +87,9 @@ class JSGraph : public ZoneObject {
  private:
   Graph* graph_;
   CommonOperatorBuilder* common_;
-  JSOperatorBuilder javascript_;
+  JSOperatorBuilder* javascript_;
   Typer* typer_;
+  MachineOperatorBuilder* machine_;
 
   SetOncePointer<Node> c_entry_stub_constant_;
   SetOncePointer<Node> undefined_constant_;
index 7a18c71..2936be4 100644 (file)
@@ -67,14 +67,9 @@ static void Parse(Handle<JSFunction> function, CompilationInfoWithZone* info) {
 // A facade on a JSFunction's graph to facilitate inlining. It assumes the
 // that the function graph has only one return statement, and provides
 // {UnifyReturn} to convert a function graph to that end.
-// InlineAtCall will create some new nodes using {graph}'s builders (and hence
-// those nodes will live in {graph}'s zone.
 class Inlinee {
  public:
-  explicit Inlinee(JSGraph* graph) : jsgraph_(graph) {}
-
-  Graph* graph() { return jsgraph_->graph(); }
-  JSGraph* jsgraph() { return jsgraph_; }
+  Inlinee(Node* start, Node* end) : start_(start), end_(end) {}
 
   // Returns the last regular control node, that is
   // the last control node before the end node.
@@ -92,24 +87,25 @@ class Inlinee {
   }
   // Return the unique return statement of the graph.
   Node* unique_return() {
-    Node* unique_return =
-        NodeProperties::GetControlInput(jsgraph_->graph()->end());
+    Node* unique_return = NodeProperties::GetControlInput(end_);
     DCHECK_EQ(IrOpcode::kReturn, unique_return->opcode());
     return unique_return;
   }
   // Inline this graph at {call}, use {jsgraph} and its zone to create
   // any new nodes.
   void InlineAtCall(JSGraph* jsgraph, Node* call);
+
   // Ensure that only a single return reaches the end node.
-  void UnifyReturn();
+  static void UnifyReturn(JSGraph* jsgraph);
 
  private:
-  JSGraph* jsgraph_;
+  Node* start_;
+  Node* end_;
 };
 
 
-void Inlinee::UnifyReturn() {
-  Graph* graph = jsgraph_->graph();
+void Inlinee::UnifyReturn(JSGraph* jsgraph) {
+  Graph* graph = jsgraph->graph();
 
   Node* final_merge = NodeProperties::GetControlInput(graph->end(), 0);
   if (final_merge->opcode() == IrOpcode::kReturn) {
@@ -120,11 +116,11 @@ void Inlinee::UnifyReturn() {
 
   int predecessors =
       OperatorProperties::GetControlInputCount(final_merge->op());
-  Operator* op_phi = jsgraph_->common()->Phi(kMachAnyTagged, predecessors);
-  Operator* op_ephi = jsgraph_->common()->EffectPhi(predecessors);
+  Operator* op_phi = jsgraph->common()->Phi(kMachAnyTagged, predecessors);
+  Operator* op_ephi = jsgraph->common()->EffectPhi(predecessors);
 
-  NodeVector values(jsgraph_->zone());
-  NodeVector effects(jsgraph_->zone());
+  NodeVector values(jsgraph->zone());
+  NodeVector effects(jsgraph->zone());
   // Iterate over all control flow predecessors,
   // which must be return statements.
   InputIter iter = final_merge->inputs().begin();
@@ -150,14 +146,81 @@ void Inlinee::UnifyReturn() {
   Node* ephi = graph->NewNode(op_ephi, static_cast<int>(effects.size()),
                               &effects.front());
   Node* new_return =
-      graph->NewNode(jsgraph_->common()->Return(), phi, ephi, final_merge);
+      graph->NewNode(jsgraph->common()->Return(), phi, ephi, final_merge);
   graph->end()->ReplaceInput(0, new_return);
 }
 
 
-void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
-  MachineOperatorBuilder machine(jsgraph->zone());
+class CopyVisitor : public NullNodeVisitor {
+ public:
+  CopyVisitor(Graph* source_graph, Graph* target_graph, Zone* temp_zone)
+      : copies_(source_graph->NodeCount(), NULL, temp_zone),
+        sentinels_(source_graph->NodeCount(), NULL, temp_zone),
+        source_graph_(source_graph),
+        target_graph_(target_graph),
+        temp_zone_(temp_zone),
+        sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, 0, 0,
+                     "sentinel") {}
+
+  GenericGraphVisit::Control Post(Node* original) {
+    NodeVector inputs(temp_zone_);
+    for (InputIter it = original->inputs().begin();
+         it != original->inputs().end(); ++it) {
+      inputs.push_back(GetCopy(*it));
+    }
+
+    // Reuse the operator in the copy. This assumes that op lives in a zone
+    // that lives longer than graph()'s zone.
+    Node* copy =
+        target_graph_->NewNode(original->op(), inputs.size(), &inputs.front());
+    copies_[original->id()] = copy;
+    return GenericGraphVisit::CONTINUE;
+  }
+
+  Node* GetCopy(Node* original) {
+    Node* copy = copies_[original->id()];
+    if (copy == NULL) {
+      copy = GetSentinel(original);
+    }
+    return copy;
+  }
+
+  void CopyGraph() {
+    source_graph_->VisitNodeInputsFromEnd(this);
+    ReplaceSentinels();
+  }
 
+  const NodeVector& copies() { return copies_; }
+
+ private:
+  void ReplaceSentinels() {
+    for (int id = 0; id < source_graph_->NodeCount(); ++id) {
+      Node* sentinel = sentinels_[id];
+      if (sentinel == NULL) continue;
+      Node* copy = copies_[id];
+      DCHECK_NE(NULL, copy);
+      sentinel->ReplaceUses(copy);
+    }
+  }
+
+  Node* GetSentinel(Node* original) {
+    Node* sentinel = sentinels_[original->id()];
+    if (sentinel == NULL) {
+      sentinel = target_graph_->NewNode(&sentinel_op_);
+    }
+    return sentinel;
+  }
+
+  NodeVector copies_;
+  NodeVector sentinels_;
+  Graph* source_graph_;
+  Graph* target_graph_;
+  Zone* temp_zone_;
+  SimpleOperator sentinel_op_;
+};
+
+
+void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
   // The scheduler is smart enough to place our code; we just ensure {control}
   // becomes the control input of the start of the inlinee.
   Node* control = NodeProperties::GetControlInput(call);
@@ -166,21 +229,22 @@ void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
   // also be the effect dependency for the inlinee as it produces an effect.
   // TODO(sigurds) Use simplified load once it is ready.
   Node* context = jsgraph->graph()->NewNode(
-      machine.Load(kMachAnyTagged), NodeProperties::GetValueInput(call, 0),
+      jsgraph->machine()->Load(kMachAnyTagged),
+      NodeProperties::GetValueInput(call, 0),
       jsgraph->Int32Constant(JSFunction::kContextOffset - kHeapObjectTag),
       NodeProperties::GetEffectInput(call));
 
   // {inlinee_inputs} counts JSFunction, Receiver, arguments, context,
   // but not effect, control.
-  int inlinee_inputs = graph()->start()->op()->OutputCount();
+  int inlinee_inputs = start_->op()->OutputCount();
   // Context is last argument.
   int inlinee_context_index = inlinee_inputs - 1;
   // {inliner_inputs} counts JSFunction, Receiver, arguments, but not
   // context, effect, control.
   int inliner_inputs = OperatorProperties::GetValueInputCount(call->op());
   // Iterate over all uses of the start node.
-  UseIter iter = graph()->start()->uses().begin();
-  while (iter != graph()->start()->uses().end()) {
+  UseIter iter = start_->uses().begin();
+  while (iter != start_->uses().end()) {
     Node* use = *iter;
     switch (use->opcode()) {
       case IrOpcode::kParameter: {
@@ -234,10 +298,10 @@ void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
 }
 
 
-void JSInliner::TryInlineCall(Node* node) {
-  DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
+void JSInliner::TryInlineCall(Node* call) {
+  DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode());
 
-  HeapObjectMatcher<JSFunction> match(node->InputAt(0));
+  HeapObjectMatcher<JSFunction> match(call->InputAt(0));
   if (!match.HasValue()) {
     return;
   }
@@ -275,21 +339,20 @@ void JSInliner::TryInlineCall(Node* node) {
            info_->shared_info()->DebugName()->ToCString().get());
   }
 
-  Graph graph(info_->zone());
-  graph.SetNextNodeId(jsgraph_->graph()->NextNodeID());
-
-  Typer typer(info_->zone());
-  CommonOperatorBuilder common(info_->zone());
-  JSGraph jsgraph(&graph, &common, &typer);
+  Graph graph(info.zone());
+  Typer typer(info.zone());
+  JSGraph jsgraph(&graph, jsgraph_->common(), jsgraph_->javascript(), &typer,
+                  jsgraph_->machine());
 
   AstGraphBuilder graph_builder(&info, &jsgraph);
   graph_builder.CreateGraph();
+  Inlinee::UnifyReturn(&jsgraph);
 
-  Inlinee inlinee(&jsgraph);
-  inlinee.UnifyReturn();
-  inlinee.InlineAtCall(jsgraph_, node);
+  CopyVisitor visitor(&graph, jsgraph_->graph(), info.zone());
+  visitor.CopyGraph();
 
-  jsgraph_->graph()->SetNextNodeId(inlinee.graph()->NextNodeID());
+  Inlinee inlinee(visitor.GetCopy(graph.start()), visitor.GetCopy(graph.end()));
+  inlinee.InlineAtCall(jsgraph_, call);
 }
 }
 }
index 4267161..d3448fb 100644 (file)
@@ -20,7 +20,8 @@ class MachineOperatorReducerTest : public GraphTest {
  protected:
   Reduction Reduce(Node* node) {
     Typer typer(zone());
-    JSGraph jsgraph(graph(), common(), &typer);
+    JSOperatorBuilder javascript(zone());
+    JSGraph jsgraph(graph(), common(), &javascript, &typer, &machine_);
     MachineOperatorReducer reducer(&jsgraph);
     return reducer.Reduce(node);
   }
index 6b5fdcf..ce9ce3a 100644 (file)
@@ -170,7 +170,9 @@ Handle<Code> Pipeline::GenerateCode() {
   // typer could sweep over later.
   Typer typer(zone());
   CommonOperatorBuilder common(zone());
-  JSGraph jsgraph(&graph, &common, &typer);
+  JSOperatorBuilder javascript(zone());
+  MachineOperatorBuilder machine(zone());
+  JSGraph jsgraph(&graph, &common, &javascript, &typer, &machine);
   Node* context_node;
   {
     PhaseStats graph_builder_stats(info(), PhaseStats::CREATE_GRAPH,
@@ -256,7 +258,6 @@ Handle<Code> Pipeline::GenerateCode() {
       SourcePositionTable::Scope pos(&source_positions,
                                      SourcePosition::Unknown());
       Linkage linkage(info());
-      MachineOperatorBuilder machine(zone());
       ValueNumberingReducer vn_reducer(zone());
       SimplifiedOperatorReducer simple_reducer(&jsgraph, &machine);
       ChangeLowering lowering(&jsgraph, &linkage, &machine);
@@ -281,7 +282,6 @@ Handle<Code> Pipeline::GenerateCode() {
                                 "generic lowering");
       SourcePositionTable::Scope pos(&source_positions,
                                      SourcePosition::Unknown());
-      MachineOperatorBuilder machine(zone());
       JSGenericLowering lowering(info(), &jsgraph, &machine);
       GraphReducer graph_reducer(&graph);
       graph_reducer.AddReducer(&lowering);
index 1736cfc..6214f3b 100644 (file)
@@ -23,7 +23,8 @@ class SimplifiedOperatorReducerTest : public GraphTest {
   Reduction Reduce(Node* node) {
     Typer typer(zone());
     MachineOperatorBuilder machine(zone());
-    JSGraph jsgraph(graph(), common(), &typer);
+    JSOperatorBuilder javascript(zone());
+    JSGraph jsgraph(graph(), common(), &javascript, &typer, &machine);
     SimplifiedOperatorReducer reducer(&jsgraph, &machine);
     return reducer.Reduce(node);
   }
index 071acf3..d4076e9 100644 (file)
@@ -31,10 +31,13 @@ class ChangesLoweringTester : public GraphBuilderTester<ReturnType> {
   explicit ChangesLoweringTester(MachineType p0 = kMachNone)
       : GraphBuilderTester<ReturnType>(p0),
         typer(this->zone()),
-        jsgraph(this->graph(), this->common(), &typer),
+        javascript(this->zone()),
+        jsgraph(this->graph(), this->common(), &javascript, &typer,
+                this->machine()),
         function(Handle<JSFunction>::null()) {}
 
   Typer typer;
+  JSOperatorBuilder javascript;
   JSGraph jsgraph;
   Handle<JSFunction> function;
 
index fc67df2..8bfadbf 100644 (file)
@@ -17,10 +17,16 @@ using namespace v8::internal::compiler;
 class JSCacheTesterHelper {
  protected:
   explicit JSCacheTesterHelper(Zone* zone)
-      : main_graph_(zone), main_common_(zone), main_typer_(zone) {}
+      : main_graph_(zone),
+        main_common_(zone),
+        main_javascript_(zone),
+        main_typer_(zone),
+        main_machine_(zone) {}
   Graph main_graph_;
   CommonOperatorBuilder main_common_;
+  JSOperatorBuilder main_javascript_;
   Typer main_typer_;
+  MachineOperatorBuilder main_machine_;
 };
 
 
@@ -30,7 +36,8 @@ class JSConstantCacheTester : public HandleAndZoneScope,
  public:
   JSConstantCacheTester()
       : JSCacheTesterHelper(main_zone()),
-        JSGraph(&main_graph_, &main_common_, &main_typer_) {}
+        JSGraph(&main_graph_, &main_common_, &main_javascript_, &main_typer_,
+                &main_machine_) {}
 
   Type* upper(Node* node) { return NodeProperties::GetBounds(node).upper; }
 
index e5e6ce7..1253dd8 100644 (file)
@@ -22,9 +22,10 @@ class ContextSpecializationTester : public HandleAndZoneScope,
       : DirectGraphBuilder(new (main_zone()) Graph(main_zone())),
         common_(main_zone()),
         javascript_(main_zone()),
+        machine_(main_zone()),
         simplified_(main_zone()),
         typer_(main_zone()),
-        jsgraph_(graph(), common(), &typer_),
+        jsgraph_(graph(), common(), &javascript_, &typer_, &machine_),
         info_(main_isolate(), main_zone()) {}
 
   Factory* factory() { return main_isolate()->factory(); }
@@ -37,6 +38,7 @@ class ContextSpecializationTester : public HandleAndZoneScope,
  private:
   CommonOperatorBuilder common_;
   JSOperatorBuilder javascript_;
+  MachineOperatorBuilder machine_;
   SimplifiedOperatorBuilder simplified_;
   Typer typer_;
   JSGraph jsgraph_;
index c53cd75..41879cf 100644 (file)
@@ -50,7 +50,7 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
   }
 
   Node* reduce(Node* node) {
-    JSGraph jsgraph(&graph, &common, &typer);
+    JSGraph jsgraph(&graph, &common, &javascript, &typer, &machine);
     JSTypedLowering reducer(&jsgraph);
     Reduction reduction = reducer.Reduce(node);
     if (reduction.Changed()) return reduction.replacement();
index bcd6835..d6928c7 100644 (file)
@@ -55,8 +55,9 @@ class ReducerTester : public HandleAndZoneScope {
         machine(main_zone()),
         common(main_zone()),
         graph(main_zone()),
+        javascript(main_zone()),
         typer(main_zone()),
-        jsgraph(&graph, &common, &typer),
+        jsgraph(&graph, &common, &javascript, &typer, &machine),
         maxuint32(Constant<int32_t>(kMaxUInt32)) {
     Node* s = graph.NewNode(common.Start(num_parameters));
     graph.SetStart(s);
@@ -68,6 +69,7 @@ class ReducerTester : public HandleAndZoneScope {
   MachineOperatorBuilder machine;
   CommonOperatorBuilder common;
   Graph graph;
+  JSOperatorBuilder javascript;
   Typer typer;
   JSGraph jsgraph;
   Node* maxuint32;
index 2493632..36da572 100644 (file)
@@ -25,13 +25,16 @@ class RepresentationChangerTester : public HandleAndZoneScope,
   explicit RepresentationChangerTester(int num_parameters = 0)
       : GraphAndBuilders(main_zone()),
         typer_(main_zone()),
-        jsgraph_(main_graph_, &main_common_, &typer_),
+        javascript_(main_zone()),
+        jsgraph_(main_graph_, &main_common_, &javascript_, &typer_,
+                 &main_machine_),
         changer_(&jsgraph_, &main_simplified_, &main_machine_, main_isolate()) {
     Node* s = graph()->NewNode(common()->Start(num_parameters));
     graph()->SetStart(s);
   }
 
   Typer typer_;
+  JSOperatorBuilder javascript_;
   JSGraph jsgraph_;
   RepresentationChanger changer_;
 
index ab0e76f..fa50f89 100644 (file)
@@ -36,10 +36,13 @@ class SimplifiedLoweringTester : public GraphBuilderTester<ReturnType> {
                            MachineType p4 = kMachNone)
       : GraphBuilderTester<ReturnType>(p0, p1, p2, p3, p4),
         typer(this->zone()),
-        jsgraph(this->graph(), this->common(), &typer),
+        javascript(this->zone()),
+        jsgraph(this->graph(), this->common(), &javascript, &typer,
+                this->machine()),
         lowering(&jsgraph) {}
 
   Typer typer;
+  JSOperatorBuilder javascript;
   JSGraph jsgraph;
   SimplifiedLowering lowering;
 
@@ -626,6 +629,7 @@ TEST(RunAccessTests_Smi) {
 class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders {
  public:
   Typer typer;
+  JSOperatorBuilder javascript;
   JSGraph jsgraph;
   Node* p0;
   Node* p1;
@@ -636,7 +640,8 @@ class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders {
   explicit TestingGraph(Type* p0_type, Type* p1_type = Type::None())
       : GraphAndBuilders(main_zone()),
         typer(main_zone()),
-        jsgraph(graph(), common(), &typer) {
+        javascript(main_zone()),
+        jsgraph(graph(), common(), &javascript, &typer, machine()) {
     start = graph()->NewNode(common()->Start(2));
     graph()->SetStart(start);
     ret =