| Index: src/compiler/js-inlining.cc
|
| diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc
|
| index 7a18c714c9d40e35eaf9b7432b5ba317839627a9..2936be49b3d0bd8b7ced8434f43eb2ad5db7d404 100644
|
| --- a/src/compiler/js-inlining.cc
|
| +++ b/src/compiler/js-inlining.cc
|
| @@ -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);
|
| }
|
| }
|
| }
|
|
|