From 1f9215ba8d57f7ea18b9c561c1f4dcea2093f466 Mon Sep 17 00:00:00 2001 From: "sigurds@chromium.org" Date: Tue, 9 Sep 2014 13:20:09 +0000 Subject: [PATCH] Add copy support in inliner. 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 --- src/compiler/change-lowering-unittest.cc | 6 +- src/compiler/generic-graph.h | 1 - src/compiler/js-graph.h | 14 ++- src/compiler/js-inlining.cc | 135 +++++++++++++++------ src/compiler/machine-operator-reducer-unittest.cc | 3 +- src/compiler/pipeline.cc | 6 +- .../simplified-operator-reducer-unittest.cc | 3 +- test/cctest/compiler/test-changes-lowering.cc | 5 +- test/cctest/compiler/test-js-constant-cache.cc | 11 +- .../compiler/test-js-context-specialization.cc | 4 +- test/cctest/compiler/test-js-typed-lowering.cc | 2 +- .../compiler/test-machine-operator-reducer.cc | 4 +- test/cctest/compiler/test-representation-change.cc | 5 +- test/cctest/compiler/test-simplified-lowering.cc | 9 +- 14 files changed, 151 insertions(+), 57 deletions(-) diff --git a/src/compiler/change-lowering-unittest.cc b/src/compiler/change-lowering-unittest.cc index 1978476..9d56331 100644 --- a/src/compiler/change-lowering-unittest.cc +++ b/src/compiler/change-lowering-unittest.cc @@ -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); } diff --git a/src/compiler/generic-graph.h b/src/compiler/generic-graph.h index e8de9eb..a555456 100644 --- a/src/compiler/generic-graph.h +++ b/src/compiler/generic-graph.h @@ -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_; diff --git a/src/compiler/js-graph.h b/src/compiler/js-graph.h index 71d6434..99a6a06 100644 --- a/src/compiler/js-graph.h +++ b/src/compiler/js-graph.h @@ -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 c_entry_stub_constant_; SetOncePointer undefined_constant_; diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc index 7a18c71..2936be4 100644 --- a/src/compiler/js-inlining.cc +++ b/src/compiler/js-inlining.cc @@ -67,14 +67,9 @@ static void Parse(Handle 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(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 match(node->InputAt(0)); + HeapObjectMatcher 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); } } } diff --git a/src/compiler/machine-operator-reducer-unittest.cc b/src/compiler/machine-operator-reducer-unittest.cc index 4267161..d3448fb 100644 --- a/src/compiler/machine-operator-reducer-unittest.cc +++ b/src/compiler/machine-operator-reducer-unittest.cc @@ -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); } diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc index 6b5fdcf..ce9ce3a 100644 --- a/src/compiler/pipeline.cc +++ b/src/compiler/pipeline.cc @@ -170,7 +170,9 @@ Handle 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 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 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); diff --git a/src/compiler/simplified-operator-reducer-unittest.cc b/src/compiler/simplified-operator-reducer-unittest.cc index 1736cfc..6214f3b 100644 --- a/src/compiler/simplified-operator-reducer-unittest.cc +++ b/src/compiler/simplified-operator-reducer-unittest.cc @@ -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); } diff --git a/test/cctest/compiler/test-changes-lowering.cc b/test/cctest/compiler/test-changes-lowering.cc index 071acf3..d4076e9 100644 --- a/test/cctest/compiler/test-changes-lowering.cc +++ b/test/cctest/compiler/test-changes-lowering.cc @@ -31,10 +31,13 @@ class ChangesLoweringTester : public GraphBuilderTester { explicit ChangesLoweringTester(MachineType p0 = kMachNone) : GraphBuilderTester(p0), typer(this->zone()), - jsgraph(this->graph(), this->common(), &typer), + javascript(this->zone()), + jsgraph(this->graph(), this->common(), &javascript, &typer, + this->machine()), function(Handle::null()) {} Typer typer; + JSOperatorBuilder javascript; JSGraph jsgraph; Handle function; diff --git a/test/cctest/compiler/test-js-constant-cache.cc b/test/cctest/compiler/test-js-constant-cache.cc index fc67df2..8bfadbf 100644 --- a/test/cctest/compiler/test-js-constant-cache.cc +++ b/test/cctest/compiler/test-js-constant-cache.cc @@ -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; } diff --git a/test/cctest/compiler/test-js-context-specialization.cc b/test/cctest/compiler/test-js-context-specialization.cc index e5e6ce7..1253dd8 100644 --- a/test/cctest/compiler/test-js-context-specialization.cc +++ b/test/cctest/compiler/test-js-context-specialization.cc @@ -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_; diff --git a/test/cctest/compiler/test-js-typed-lowering.cc b/test/cctest/compiler/test-js-typed-lowering.cc index c53cd75..41879cf 100644 --- a/test/cctest/compiler/test-js-typed-lowering.cc +++ b/test/cctest/compiler/test-js-typed-lowering.cc @@ -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(); diff --git a/test/cctest/compiler/test-machine-operator-reducer.cc b/test/cctest/compiler/test-machine-operator-reducer.cc index bcd6835..d6928c7 100644 --- a/test/cctest/compiler/test-machine-operator-reducer.cc +++ b/test/cctest/compiler/test-machine-operator-reducer.cc @@ -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(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; diff --git a/test/cctest/compiler/test-representation-change.cc b/test/cctest/compiler/test-representation-change.cc index 2493632..36da572 100644 --- a/test/cctest/compiler/test-representation-change.cc +++ b/test/cctest/compiler/test-representation-change.cc @@ -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_; diff --git a/test/cctest/compiler/test-simplified-lowering.cc b/test/cctest/compiler/test-simplified-lowering.cc index ab0e76f..fa50f89 100644 --- a/test/cctest/compiler/test-simplified-lowering.cc +++ b/test/cctest/compiler/test-simplified-lowering.cc @@ -36,10 +36,13 @@ class SimplifiedLoweringTester : public GraphBuilderTester { MachineType p4 = kMachNone) : GraphBuilderTester(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 = -- 2.7.4