| Index: src/compiler/js-inlining.cc
|
| diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc
|
| index 147cfc9134a896d7b34b9e7e5f00c1c5707cc0f3..7a18c714c9d40e35eaf9b7432b5ba317839627a9 100644
|
| --- a/src/compiler/js-inlining.cc
|
| +++ b/src/compiler/js-inlining.cc
|
| @@ -2,7 +2,6 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "src/compiler/access-builder.h"
|
| #include "src/compiler/ast-graph-builder.h"
|
| #include "src/compiler/common-operator.h"
|
| #include "src/compiler/generic-node-inl.h"
|
| @@ -68,9 +67,14 @@ 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:
|
| - Inlinee(Node* start, Node* end) : start_(start), end_(end) {}
|
| + explicit Inlinee(JSGraph* graph) : jsgraph_(graph) {}
|
| +
|
| + Graph* graph() { return jsgraph_->graph(); }
|
| + JSGraph* jsgraph() { return jsgraph_; }
|
|
|
| // Returns the last regular control node, that is
|
| // the last control node before the end node.
|
| @@ -88,25 +92,24 @@ class Inlinee {
|
| }
|
| // Return the unique return statement of the graph.
|
| Node* unique_return() {
|
| - Node* unique_return = NodeProperties::GetControlInput(end_);
|
| + Node* unique_return =
|
| + NodeProperties::GetControlInput(jsgraph_->graph()->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.
|
| - static void UnifyReturn(JSGraph* jsgraph);
|
| + void UnifyReturn();
|
|
|
| private:
|
| - Node* start_;
|
| - Node* end_;
|
| + JSGraph* jsgraph_;
|
| };
|
|
|
|
|
| -void Inlinee::UnifyReturn(JSGraph* jsgraph) {
|
| - Graph* graph = jsgraph->graph();
|
| +void Inlinee::UnifyReturn() {
|
| + Graph* graph = jsgraph_->graph();
|
|
|
| Node* final_merge = NodeProperties::GetControlInput(graph->end(), 0);
|
| if (final_merge->opcode() == IrOpcode::kReturn) {
|
| @@ -117,11 +120,11 @@ void Inlinee::UnifyReturn(JSGraph* jsgraph) {
|
|
|
| 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();
|
| @@ -147,104 +150,37 @@ void Inlinee::UnifyReturn(JSGraph* jsgraph) {
|
| 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);
|
| }
|
|
|
|
|
| -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(), static_cast<int>(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) {
|
| + MachineOperatorBuilder machine(jsgraph->zone());
|
| +
|
| // 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);
|
|
|
| // The inlinee uses the context from the JSFunction object. This will
|
| // also be the effect dependency for the inlinee as it produces an effect.
|
| - SimplifiedOperatorBuilder simplified(jsgraph->zone());
|
| + // TODO(sigurds) Use simplified load once it is ready.
|
| Node* context = jsgraph->graph()->NewNode(
|
| - simplified.LoadField(AccessBuilder::ForJSFunctionContext()),
|
| - NodeProperties::GetValueInput(call, 0),
|
| + 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 = start_->op()->OutputCount();
|
| + int inlinee_inputs = graph()->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 = start_->uses().begin();
|
| - while (iter != start_->uses().end()) {
|
| + UseIter iter = graph()->start()->uses().begin();
|
| + while (iter != graph()->start()->uses().end()) {
|
| Node* use = *iter;
|
| switch (use->opcode()) {
|
| case IrOpcode::kParameter: {
|
| @@ -298,10 +234,10 @@ void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
|
| }
|
|
|
|
|
| -void JSInliner::TryInlineCall(Node* call) {
|
| - DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode());
|
| +void JSInliner::TryInlineCall(Node* node) {
|
| + DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
|
|
|
| - HeapObjectMatcher<JSFunction> match(call->InputAt(0));
|
| + HeapObjectMatcher<JSFunction> match(node->InputAt(0));
|
| if (!match.HasValue()) {
|
| return;
|
| }
|
| @@ -339,20 +275,21 @@ void JSInliner::TryInlineCall(Node* call) {
|
| info_->shared_info()->DebugName()->ToCString().get());
|
| }
|
|
|
| - Graph graph(info.zone());
|
| - Typer typer(info.zone());
|
| - JSGraph jsgraph(&graph, jsgraph_->common(), jsgraph_->javascript(), &typer,
|
| - jsgraph_->machine());
|
| + Graph graph(info_->zone());
|
| + graph.SetNextNodeId(jsgraph_->graph()->NextNodeID());
|
| +
|
| + Typer typer(info_->zone());
|
| + CommonOperatorBuilder common(info_->zone());
|
| + JSGraph jsgraph(&graph, &common, &typer);
|
|
|
| AstGraphBuilder graph_builder(&info, &jsgraph);
|
| graph_builder.CreateGraph();
|
| - Inlinee::UnifyReturn(&jsgraph);
|
|
|
| - CopyVisitor visitor(&graph, jsgraph_->graph(), info.zone());
|
| - visitor.CopyGraph();
|
| + Inlinee inlinee(&jsgraph);
|
| + inlinee.UnifyReturn();
|
| + inlinee.InlineAtCall(jsgraph_, node);
|
|
|
| - Inlinee inlinee(visitor.GetCopy(graph.start()), visitor.GetCopy(graph.end()));
|
| - inlinee.InlineAtCall(jsgraph_, call);
|
| + jsgraph_->graph()->SetNextNodeId(inlinee.graph()->NextNodeID());
|
| }
|
| }
|
| }
|
|
|