| Index: src/compiler/js-inlining.cc
 | 
| diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc
 | 
| index 53ff3c9c1da9d3730e77fd1fe7caff34fc93990c..982d7a6e51f7d12570eb1f09517bb049b9e1b29c 100644
 | 
| --- a/src/compiler/js-inlining.cc
 | 
| +++ b/src/compiler/js-inlining.cc
 | 
| @@ -8,7 +8,6 @@
 | 
|  #include "src/ast/ast.h"
 | 
|  #include "src/ast/scopes.h"
 | 
|  #include "src/compiler.h"
 | 
| -#include "src/compiler/all-nodes.h"
 | 
|  #include "src/compiler/ast-graph-builder.h"
 | 
|  #include "src/compiler/ast-loop-assignment-analyzer.h"
 | 
|  #include "src/compiler/common-operator.h"
 | 
| @@ -77,63 +76,6 @@ class JSCallAccessor {
 | 
|  };
 | 
|  
 | 
|  
 | 
| -class CopyVisitor {
 | 
| - public:
 | 
| -  CopyVisitor(Graph* source_graph, Graph* target_graph, Zone* temp_zone)
 | 
| -      : sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, "Sentinel", 0, 0,
 | 
| -                     0, 0, 0, 0),
 | 
| -        sentinel_(target_graph->NewNode(&sentinel_op_)),
 | 
| -        copies_(source_graph->NodeCount(), sentinel_, temp_zone),
 | 
| -        source_graph_(source_graph),
 | 
| -        target_graph_(target_graph),
 | 
| -        temp_zone_(temp_zone) {}
 | 
| -
 | 
| -  Node* GetCopy(Node* orig) { return copies_[orig->id()]; }
 | 
| -
 | 
| -  void CopyGraph() {
 | 
| -    NodeVector inputs(temp_zone_);
 | 
| -    // TODO(bmeurer): AllNodes should be turned into something like
 | 
| -    // Graph::CollectNodesReachableFromEnd() and the gray set stuff should be
 | 
| -    // removed since it's only needed by the visualizer.
 | 
| -    AllNodes all(temp_zone_, source_graph_);
 | 
| -    // Copy all nodes reachable from end.
 | 
| -    for (Node* orig : all.live) {
 | 
| -      Node* copy = GetCopy(orig);
 | 
| -      if (copy != sentinel_) {
 | 
| -        // Mapping already exists.
 | 
| -        continue;
 | 
| -      }
 | 
| -      // Copy the node.
 | 
| -      inputs.clear();
 | 
| -      for (Node* input : orig->inputs()) inputs.push_back(copies_[input->id()]);
 | 
| -      copy = target_graph_->NewNode(orig->op(), orig->InputCount(),
 | 
| -                                    inputs.empty() ? nullptr : &inputs[0]);
 | 
| -      copies_[orig->id()] = copy;
 | 
| -    }
 | 
| -    // For missing inputs.
 | 
| -    for (Node* orig : all.live) {
 | 
| -      Node* copy = copies_[orig->id()];
 | 
| -      for (int i = 0; i < copy->InputCount(); ++i) {
 | 
| -        Node* input = copy->InputAt(i);
 | 
| -        if (input == sentinel_) {
 | 
| -          copy->ReplaceInput(i, GetCopy(orig->InputAt(i)));
 | 
| -        }
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  const NodeVector& copies() const { return copies_; }
 | 
| -
 | 
| - private:
 | 
| -  Operator const sentinel_op_;
 | 
| -  Node* const sentinel_;
 | 
| -  NodeVector copies_;
 | 
| -  Graph* const source_graph_;
 | 
| -  Graph* const target_graph_;
 | 
| -  Zone* const temp_zone_;
 | 
| -};
 | 
| -
 | 
| -
 | 
|  Reduction JSInliner::InlineCall(Node* call, Node* new_target, Node* context,
 | 
|                                  Node* frame_state, Node* start, Node* end) {
 | 
|    // The scheduler is smart enough to place our code; we just ensure {control}
 | 
| @@ -448,69 +390,71 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
 | 
|          shared_info->DebugName()->ToCString().get(),
 | 
|          info_->shared_info()->DebugName()->ToCString().get());
 | 
|  
 | 
| -  // Run the loop assignment analyzer on the inlinee.
 | 
| -  AstLoopAssignmentAnalyzer loop_assignment_analyzer(&zone, &info);
 | 
| -  LoopAssignmentAnalysis* loop_assignment = loop_assignment_analyzer.Analyze();
 | 
| -
 | 
| -  // Run the type hint analyzer on the inlinee.
 | 
| -  TypeHintAnalyzer type_hint_analyzer(&zone);
 | 
| -  TypeHintAnalysis* type_hint_analysis =
 | 
| -      type_hint_analyzer.Analyze(handle(shared_info->code(), info.isolate()));
 | 
| -
 | 
| -  // TODO(mstarzinger): We could use the temporary zone for the graph because
 | 
| -  // nodes are copied. This however leads to Zone-Types being allocated in the
 | 
| -  // wrong zone and makes the engine explode at high speeds. Explosion bad!
 | 
| -  Graph graph(jsgraph_->zone());
 | 
| -  JSGraph jsgraph(info.isolate(), &graph, jsgraph_->common(),
 | 
| -                  jsgraph_->javascript(), jsgraph_->simplified(),
 | 
| -                  jsgraph_->machine());
 | 
| -  AstGraphBuilder graph_builder(local_zone_, &info, &jsgraph, loop_assignment,
 | 
| -                                type_hint_analysis);
 | 
| -  graph_builder.CreateGraph(false);
 | 
| -
 | 
| -  CopyVisitor visitor(&graph, jsgraph_->graph(), &zone);
 | 
| -  visitor.CopyGraph();
 | 
| -
 | 
| -  Node* start = visitor.GetCopy(graph.start());
 | 
| -  Node* end = visitor.GetCopy(graph.end());
 | 
| +  // Create the subgraph for the inlinee.
 | 
| +  Node* start;
 | 
| +  Node* end;
 | 
| +  {
 | 
| +    // Run the loop assignment analyzer on the inlinee.
 | 
| +    AstLoopAssignmentAnalyzer loop_assignment_analyzer(&zone, &info);
 | 
| +    LoopAssignmentAnalysis* loop_assignment =
 | 
| +        loop_assignment_analyzer.Analyze();
 | 
| +
 | 
| +    // Run the type hint analyzer on the inlinee.
 | 
| +    TypeHintAnalyzer type_hint_analyzer(&zone);
 | 
| +    TypeHintAnalysis* type_hint_analysis =
 | 
| +        type_hint_analyzer.Analyze(handle(shared_info->code(), info.isolate()));
 | 
| +
 | 
| +    // Run the AstGraphBuilder to create the subgraph.
 | 
| +    Graph::SubgraphScope scope(graph());
 | 
| +    AstGraphBuilder graph_builder(&zone, &info, jsgraph(), loop_assignment,
 | 
| +                                  type_hint_analysis);
 | 
| +    graph_builder.CreateGraph(false);
 | 
| +
 | 
| +    // Extract the inlinee start/end nodes.
 | 
| +    start = graph()->start();
 | 
| +    end = graph()->end();
 | 
| +  }
 | 
| +
 | 
|    Node* frame_state = call.frame_state_after();
 | 
|    Node* new_target = jsgraph_->UndefinedConstant();
 | 
|  
 | 
| -  // Insert nodes around the call that model the behavior required for a
 | 
| -  // constructor dispatch (allocate implicit receiver and check return value).
 | 
| -  // This models the behavior usually accomplished by our {JSConstructStub}.
 | 
| -  // Note that the context has to be the callers context (input to call node).
 | 
| -  Node* receiver = jsgraph_->UndefinedConstant();  // Implicit receiver.
 | 
| -  if (node->opcode() == IrOpcode::kJSCallConstruct &&
 | 
| -      NeedsImplicitReceiver(shared_info)) {
 | 
| -    Node* effect = NodeProperties::GetEffectInput(node);
 | 
| -    Node* context = NodeProperties::GetContextInput(node);
 | 
| -    Node* create = jsgraph_->graph()->NewNode(
 | 
| -        jsgraph_->javascript()->Create(), call.target(), call.new_target(),
 | 
| -        context, call.frame_state_before(), effect);
 | 
| -    NodeProperties::ReplaceEffectInput(node, create);
 | 
| -    // Insert a check of the return value to determine whether the return value
 | 
| -    // or the implicit receiver should be selected as a result of the call.
 | 
| -    Node* check = jsgraph_->graph()->NewNode(
 | 
| -        jsgraph_->javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1),
 | 
| -        node, context, node, start);
 | 
| -    Node* select = jsgraph_->graph()->NewNode(
 | 
| -        jsgraph_->common()->Select(MachineRepresentation::kTagged), check, node,
 | 
| -        create);
 | 
| -    NodeProperties::ReplaceUses(node, select, check, node, node);
 | 
| -    NodeProperties::ReplaceValueInput(select, node, 1);
 | 
| -    NodeProperties::ReplaceValueInput(check, node, 0);
 | 
| -    NodeProperties::ReplaceEffectInput(check, node);
 | 
| -    receiver = create;  // The implicit receiver.
 | 
| -  }
 | 
| -
 | 
| -  // Swizzle the inputs of the {JSCallConstruct} node to look like inputs to a
 | 
| -  // normal {JSCallFunction} node so that the rest of the inlining machinery
 | 
| -  // behaves as if we were dealing with a regular function invocation.
 | 
| +  // Inline {JSCallConstruct} requires some additional magic.
 | 
|    if (node->opcode() == IrOpcode::kJSCallConstruct) {
 | 
| +    // Insert nodes around the call that model the behavior required for a
 | 
| +    // constructor dispatch (allocate implicit receiver and check return value).
 | 
| +    // This models the behavior usually accomplished by our {JSConstructStub}.
 | 
| +    // Note that the context has to be the callers context (input to call node).
 | 
| +    Node* receiver = jsgraph_->UndefinedConstant();  // Implicit receiver.
 | 
| +    if (NeedsImplicitReceiver(shared_info)) {
 | 
| +      Node* effect = NodeProperties::GetEffectInput(node);
 | 
| +      Node* context = NodeProperties::GetContextInput(node);
 | 
| +      Node* create = jsgraph_->graph()->NewNode(
 | 
| +          jsgraph_->javascript()->Create(), call.target(), call.new_target(),
 | 
| +          context, call.frame_state_before(), effect);
 | 
| +      NodeProperties::ReplaceEffectInput(node, create);
 | 
| +      // Insert a check of the return value to determine whether the return
 | 
| +      // value
 | 
| +      // or the implicit receiver should be selected as a result of the call.
 | 
| +      Node* check = jsgraph_->graph()->NewNode(
 | 
| +          jsgraph_->javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1),
 | 
| +          node, context, node, start);
 | 
| +      Node* select = jsgraph_->graph()->NewNode(
 | 
| +          jsgraph_->common()->Select(MachineRepresentation::kTagged), check,
 | 
| +          node, create);
 | 
| +      NodeProperties::ReplaceUses(node, select, check, node, node);
 | 
| +      NodeProperties::ReplaceValueInput(select, node, 1);
 | 
| +      NodeProperties::ReplaceValueInput(check, node, 0);
 | 
| +      NodeProperties::ReplaceEffectInput(check, node);
 | 
| +      receiver = create;  // The implicit receiver.
 | 
| +    }
 | 
| +
 | 
| +    // Swizzle the inputs of the {JSCallConstruct} node to look like inputs to a
 | 
| +    // normal {JSCallFunction} node so that the rest of the inlining machinery
 | 
| +    // behaves as if we were dealing with a regular function invocation.
 | 
|      new_target = call.new_target();  // Retrieve new target value input.
 | 
|      node->RemoveInput(call.formal_arguments() + 1);  // Drop new target.
 | 
|      node->InsertInput(jsgraph_->graph()->zone(), 1, receiver);
 | 
| +
 | 
|      // Insert a construct stub frame into the chain of frame states. This will
 | 
|      // reconstruct the proper frame when deoptimizing within the constructor.
 | 
|      frame_state = CreateArtificialFrameState(
 | 
| @@ -570,6 +514,8 @@ Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) {
 | 
|    return InlineCall(node, new_target, context, frame_state, start, end);
 | 
|  }
 | 
|  
 | 
| +Graph* JSInliner::graph() const { return jsgraph()->graph(); }
 | 
| +
 | 
|  }  // namespace compiler
 | 
|  }  // namespace internal
 | 
|  }  // namespace v8
 | 
| 
 |