1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/js-inlining.h"
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/ast/ast.h"
8f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compilation-info.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler.h"
10f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compiler/all-nodes.h"
11f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/compiler/bytecode-graph-builder.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/common-operator.h"
1362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/compiler/compiler-source-position-table.h"
14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/graph-reducer.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/js-operator.h"
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/node-matchers.h"
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/node-properties.h"
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler/operator-properties.h"
19f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/compiler/simplified-operator.h"
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate-inl.h"
21f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/parsing/parse-info.h"
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace compiler {
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define TRACE(...)                                      \
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  do {                                                  \
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (FLAG_trace_turbo_inlining) PrintF(__VA_ARGS__); \
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } while (false)
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Provides convenience accessors for the common layout of nodes having either
3462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// the {JSCall} or the {JSConstruct} operator.
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass JSCallAccessor {
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit JSCallAccessor(Node* call) : call_(call) {
3862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(call->opcode() == IrOpcode::kJSCall ||
3962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch           call->opcode() == IrOpcode::kJSConstruct);
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* target() {
4362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Both, {JSCall} and {JSConstruct}, have same layout here.
44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return call_->InputAt(0);
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* receiver() {
4862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_EQ(IrOpcode::kJSCall, call_->opcode());
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return call_->InputAt(1);
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* new_target() {
5362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_EQ(IrOpcode::kJSConstruct, call_->opcode());
54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return call_->InputAt(formal_arguments() + 1);
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* frame_state() {
5862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Both, {JSCall} and {JSConstruct}, have frame state.
59f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return NodeProperties::GetFrameStateInput(call_);
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int formal_arguments() {
6362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Both, {JSCall} and {JSConstruct}, have two extra inputs:
6462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //  - JSConstruct: Includes target function and new target.
6562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    //  - JSCall: Includes target function and receiver.
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return call_->op()->ValueInputCount() - 2;
67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
69f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  float frequency() const {
7062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return (call_->opcode() == IrOpcode::kJSCall)
7162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               ? CallParametersOf(call_->op()).frequency()
7262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               : ConstructParametersOf(call_->op()).frequency();
73f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
74f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* call_;
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochReduction JSInliner::InlineCall(Node* call, Node* new_target, Node* context,
80f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                Node* frame_state, Node* start, Node* end,
81f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                Node* exception_target,
82f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                const NodeVector& uncaught_subcalls) {
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The scheduler is smart enough to place our code; we just ensure {control}
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // becomes the control input of the start of the inlinee, and {effect} becomes
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // the effect input of the start of the inlinee.
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* control = NodeProperties::GetControlInput(call);
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Node* effect = NodeProperties::GetEffectInput(call);
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int const inlinee_new_target_index =
90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      static_cast<int>(start->op()->ValueOutputCount()) - 3;
91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int const inlinee_arity_index =
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      static_cast<int>(start->op()->ValueOutputCount()) - 2;
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int const inlinee_context_index =
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      static_cast<int>(start->op()->ValueOutputCount()) - 1;
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // {inliner_inputs} counts JSFunction, receiver, arguments, but not
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // new target value, argument count, context, effect or control.
98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int inliner_inputs = call->op()->ValueInputCount();
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Iterate over all uses of the start node.
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (Edge edge : start->use_edges()) {
101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Node* use = edge.from();
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (use->opcode()) {
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kParameter: {
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        int index = 1 + ParameterIndexOf(use->op());
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK_LE(index, inlinee_context_index);
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        if (index < inliner_inputs && index < inlinee_new_target_index) {
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // There is an input from the call, and the index is a value
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // projection but not the context, so rewire the input.
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Replace(use, call->InputAt(index));
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (index == inlinee_new_target_index) {
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // The projection is requesting the new target value.
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Replace(use, new_target);
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (index == inlinee_arity_index) {
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // The projection is requesting the number of arguments.
115c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          Replace(use, jsgraph()->Constant(inliner_inputs - 2));
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (index == inlinee_context_index) {
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // The projection is requesting the inlinee function context.
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Replace(use, context);
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          // Call has fewer arguments than required, fill with undefined.
121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          Replace(use, jsgraph()->UndefinedConstant());
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      default:
126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (NodeProperties::IsEffectEdge(edge)) {
127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          edge.UpdateTo(effect);
128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        } else if (NodeProperties::IsControlEdge(edge)) {
129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          edge.UpdateTo(control);
130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        } else if (NodeProperties::IsFrameStateEdge(edge)) {
131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          edge.UpdateTo(frame_state);
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          UNREACHABLE();
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
139f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (exception_target != nullptr) {
140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Link uncaught calls in the inlinee to {exception_target}
141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    int subcall_count = static_cast<int>(uncaught_subcalls.size());
142f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (subcall_count > 0) {
143f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      TRACE(
144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          "Inlinee contains %d calls without IfException; "
145f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          "linking to existing IfException\n",
146f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          subcall_count);
147f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
148f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    NodeVector on_exception_nodes(local_zone_);
149f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    for (Node* subcall : uncaught_subcalls) {
150f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Node* on_exception =
151f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          graph()->NewNode(common()->IfException(), subcall, subcall);
152f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      on_exception_nodes.push_back(on_exception);
153f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
154f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
155f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK_EQ(subcall_count, static_cast<int>(on_exception_nodes.size()));
156f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (subcall_count > 0) {
157f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Node* control_output =
158f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          graph()->NewNode(common()->Merge(subcall_count), subcall_count,
159f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                           &on_exception_nodes.front());
160f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      NodeVector values_effects(local_zone_);
161f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      values_effects = on_exception_nodes;
162f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      values_effects.push_back(control_output);
163f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Node* value_output = graph()->NewNode(
164f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          common()->Phi(MachineRepresentation::kTagged, subcall_count),
165f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          subcall_count + 1, &values_effects.front());
166f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      Node* effect_output =
167f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          graph()->NewNode(common()->EffectPhi(subcall_count),
168f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                           subcall_count + 1, &values_effects.front());
169f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      ReplaceWithValue(exception_target, value_output, effect_output,
170f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                       control_output);
171f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    } else {
172f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      ReplaceWithValue(exception_target, exception_target, exception_target,
173f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                       jsgraph()->Dead());
174f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
175f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
176f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeVector values(local_zone_);
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeVector effects(local_zone_);
179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeVector controls(local_zone_);
180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (Node* const input : end->inputs()) {
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (input->opcode()) {
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case IrOpcode::kReturn:
183c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        values.push_back(NodeProperties::GetValueInput(input, 1));
184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        effects.push_back(NodeProperties::GetEffectInput(input));
185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        controls.push_back(NodeProperties::GetControlInput(input));
186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case IrOpcode::kDeoptimize:
188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case IrOpcode::kTerminate:
189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case IrOpcode::kThrow:
190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        NodeProperties::MergeControlToEnd(graph(), common(), input);
191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        Revisit(graph()->end());
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UNREACHABLE();
195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        break;
196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(values.size(), effects.size());
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(values.size(), controls.size());
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Depending on whether the inlinee produces a value, we either replace value
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // uses with said value or kill value uses if no value can be returned.
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (values.size() > 0) {
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int const input_count = static_cast<int>(controls.size());
205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* control_output = graph()->NewNode(common()->Merge(input_count),
206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                            input_count, &controls.front());
207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    values.push_back(control_output);
208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    effects.push_back(control_output);
209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* value_output = graph()->NewNode(
210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        common()->Phi(MachineRepresentation::kTagged, input_count),
211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        static_cast<int>(values.size()), &values.front());
212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* effect_output =
213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        graph()->NewNode(common()->EffectPhi(input_count),
214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                         static_cast<int>(effects.size()), &effects.front());
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ReplaceWithValue(call, value_output, effect_output, control_output);
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Changed(value_output);
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    ReplaceWithValue(call, call, call, jsgraph()->Dead());
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return Changed(call);
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochNode* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state,
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                            int parameter_count,
22562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                            BailoutId bailout_id,
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                            FrameStateType frame_state_type,
227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                            Handle<SharedFunctionInfo> shared) {
228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const FrameStateFunctionInfo* state_info =
229f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      common()->CreateFrameStateFunctionInfo(frame_state_type,
230f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                             parameter_count + 1, 0, shared);
231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const Operator* op = common()->FrameState(
23362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      bailout_id, OutputFrameStateCombine::Ignore(), state_info);
23462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const Operator* op0 = common()->StateValues(0, SparseInputMask::Dense());
235f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* node0 = graph()->NewNode(op0);
236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  NodeVector params(local_zone_);
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (int parameter = 0; parameter < parameter_count + 1; ++parameter) {
238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    params.push_back(node->InputAt(1 + parameter));
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
24062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const Operator* op_param = common()->StateValues(
24162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      static_cast<int>(params.size()), SparseInputMask::Dense());
242f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* params_node = graph()->NewNode(
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      op_param, static_cast<int>(params.size()), &params.front());
244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return graph()->NewNode(op, params_node, node0, node0,
245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                          jsgraph()->UndefinedConstant(), node->InputAt(0),
246f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                          outer_frame_state);
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* JSInliner::CreateTailCallerFrameState(Node* node, Node* frame_state) {
2503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
2513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Handle<SharedFunctionInfo> shared;
2523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  frame_info.shared_info().ToHandle(&shared);
2533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* function = frame_state->InputAt(kFrameStateFunctionInput);
2553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If we are inlining a tail call drop caller's frame state and an
2573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // arguments adaptor if it exists.
258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  frame_state = NodeProperties::GetFrameStateInput(frame_state);
2593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (frame_state->opcode() == IrOpcode::kFrameState) {
2603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
2613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (frame_info.type() == FrameStateType::kArgumentsAdaptor) {
262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      frame_state = NodeProperties::GetFrameStateInput(frame_state);
2633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
2643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
2653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const FrameStateFunctionInfo* state_info =
267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      common()->CreateFrameStateFunctionInfo(
2683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch          FrameStateType::kTailCallerFunction, 0, 0, shared);
2693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const Operator* op = common()->FrameState(
2713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      BailoutId(-1), OutputFrameStateCombine::Ignore(), state_info);
27262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const Operator* op0 = common()->StateValues(0, SparseInputMask::Dense());
273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* node0 = graph()->NewNode(op0);
274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return graph()->NewNode(op, node0, node0, node0,
275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                          jsgraph()->UndefinedConstant(), function,
276f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                          frame_state);
2773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace {
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
281f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// TODO(bmeurer): Unify this with the witness helper functions in the
282f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// js-builtin-reducer.cc once we have a better understanding of the
283f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// map tracking we want to do, and eventually changed the CheckMaps
284f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// operator to carry map constants on the operator instead of inputs.
285f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// I.e. if the CheckMaps has some kind of SmallMapSet as operator
286f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// parameter, then this could be changed to call a generic
287f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch//
288f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch//   SmallMapSet NodeProperties::CollectMapWitness(receiver, effect)
289f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch//
290f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// function, which either returns the map set from the CheckMaps or
291f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// a singleton set from a StoreField.
292f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochbool NeedsConvertReceiver(Node* receiver, Node* effect) {
29362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Check if the {receiver} is already a JSReceiver.
29462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  switch (receiver->opcode()) {
29562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSConstruct:
29662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSConstructWithSpread:
29762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSCreate:
29862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSCreateArguments:
29962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSCreateArray:
30062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSCreateClosure:
30162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSCreateIterResultObject:
30262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSCreateKeyValueArray:
30362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSCreateLiteralArray:
30462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSCreateLiteralObject:
30562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSCreateLiteralRegExp:
30662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSConvertReceiver:
30762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSGetSuperConstructor:
30862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kJSToObject: {
309f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return false;
310f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
31162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    default: {
31262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // We don't really care about the exact maps here, just the instance
31362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // types, which don't change across potential side-effecting operations.
31462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      ZoneHandleSet<Map> maps;
31562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      NodeProperties::InferReceiverMapsResult result =
31662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          NodeProperties::InferReceiverMaps(receiver, effect, &maps);
31762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (result != NodeProperties::kNoReceiverMaps) {
31862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // Check if all {maps} are actually JSReceiver maps.
31962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        for (size_t i = 0; i < maps.size(); ++i) {
32062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          if (!maps[i]->IsJSReceiverMap()) return true;
321f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        }
32262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        return false;
323f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
32462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return true;
325f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
326f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
327f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
328f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// TODO(mstarzinger,verwaest): Move this predicate onto SharedFunctionInfo?
330109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochbool NeedsImplicitReceiver(Handle<SharedFunctionInfo> shared_info) {
331109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DisallowHeapAllocation no_gc;
332109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Isolate* const isolate = shared_info->GetIsolate();
333109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Code* const construct_stub = shared_info->construct_stub();
3343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return construct_stub != *isolate->builtins()->JSBuiltinsConstructStub() &&
3353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         construct_stub !=
3363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch             *isolate->builtins()->JSBuiltinsConstructStubForDerived() &&
3373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch         construct_stub != *isolate->builtins()->JSConstructStubApi();
338109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch}
339109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
340109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochbool IsNonConstructible(Handle<SharedFunctionInfo> shared_info) {
341109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DisallowHeapAllocation no_gc;
342109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Isolate* const isolate = shared_info->GetIsolate();
343109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Code* const construct_stub = shared_info->construct_stub();
344109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  return construct_stub == *isolate->builtins()->ConstructedNonConstructable();
345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
34962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Determines whether the call target of the given call {node} is statically
35062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// known and can be used as an inlining candidate. The {SharedFunctionInfo} of
35162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// the call target is provided (the exact closure might be unknown).
35262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochbool JSInliner::DetermineCallTarget(
35362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* node, Handle<SharedFunctionInfo>& shared_info_out) {
35462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IrOpcode::IsInlineeOpcode(node->opcode()));
35562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HeapObjectMatcher match(node->InputAt(0));
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // This reducer can handle both normal function calls as well a constructor
358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // calls whenever the target is a constant function object, as follows:
35962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //  - JSCall(target:constant, receiver, args...)
36062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //  - JSConstruct(target:constant, args..., new.target)
36162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (match.HasValue() && match.Value()->IsJSFunction()) {
36262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<JSFunction> function = Handle<JSFunction>::cast(match.Value());
36362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
36462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Disallow cross native-context inlining for now. This means that all parts
36562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // of the resulting code will operate on the same global object. This also
36662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // prevents cross context leaks, where we could inline functions from a
36762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // different context and hold on to that context (and closure) from the code
36862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // object.
36962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // TODO(turbofan): We might want to revisit this restriction later when we
37062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // have a need for this, and we know how to model different native contexts
37162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // in the same graph in a compositional way.
37262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (function->context()->native_context() !=
37362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        info_->context()->native_context()) {
37462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return false;
37562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
37662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
37762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    shared_info_out = handle(function->shared());
37862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return true;
37962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
38062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
38162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // This reducer can also handle calls where the target is statically known to
38262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // be the result of a closure instantiation operation, as follows:
38362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //  - JSCall(JSCreateClosure[shared](context), receiver, args...)
38462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //  - JSConstruct(JSCreateClosure[shared](context), args..., new.target)
38562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (match.IsJSCreateClosure()) {
38662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CreateClosureParameters const& p = CreateClosureParametersOf(match.op());
38762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
38862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Disallow inlining in case the instantiation site was never run and hence
38962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // the vector cell does not contain a valid feedback vector for the call
39062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // target.
39162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // TODO(turbofan): We might consider to eagerly create the feedback vector
39262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // in such a case (in {DetermineCallContext} below) eventually.
39362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    FeedbackSlot slot = p.feedback().slot();
39462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<Cell> cell(Cell::cast(p.feedback().vector()->Get(slot)));
39562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!cell->value()->IsFeedbackVector()) return false;
39662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
39762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    shared_info_out = p.shared_info();
39862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return true;
39962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
40062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
40162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return false;
40262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
40362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
40462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Determines statically known information about the call target (assuming that
40562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// the call target is known according to {DetermineCallTarget} above). The
40662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// following static information is provided:
40762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch//  - context         : The context (as SSA value) bound by the call target.
40862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch//  - feedback_vector : The target is guaranteed to use this feedback vector.
40962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid JSInliner::DetermineCallContext(
41062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* node, Node*& context_out,
41162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<FeedbackVector>& feedback_vector_out) {
41262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(IrOpcode::IsInlineeOpcode(node->opcode()));
413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HeapObjectMatcher match(node->InputAt(0));
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
41562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (match.HasValue() && match.Value()->IsJSFunction()) {
41662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<JSFunction> function = Handle<JSFunction>::cast(match.Value());
41762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
41862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // If the target function was never invoked, its literals array might not
41962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // contain a feedback vector. We ensure at this point that it is created.
42062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    JSFunction::EnsureLiterals(function);
42162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
42262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // The inlinee specializes to the context from the JSFunction object.
42362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    context_out = jsgraph()->Constant(handle(function->context()));
42462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    feedback_vector_out = handle(function->feedback_vector());
42562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return;
42662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
42762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
42862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (match.IsJSCreateClosure()) {
42962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CreateClosureParameters const& p = CreateClosureParametersOf(match.op());
43062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
43162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Load the feedback vector of the target by looking up its vector cell at
43262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // the instantiation site (we only decide to inline if it's populated).
43362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    FeedbackSlot slot = p.feedback().slot();
43462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<Cell> cell(Cell::cast(p.feedback().vector()->Get(slot)));
43562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK(cell->value()->IsFeedbackVector());
43662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
43762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // The inlinee uses the locally provided context at instantiation.
43862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    context_out = NodeProperties::GetContextInput(match.node());
43962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    feedback_vector_out = handle(FeedbackVector::cast(cell->value()));
44062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return;
44162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
44262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
44362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Must succeed.
44462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  UNREACHABLE();
445014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
44762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochReduction JSInliner::Reduce(Node* node) {
44862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!IrOpcode::IsInlineeOpcode(node->opcode())) return NoChange();
44962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return ReduceJSCall(node);
45062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
45162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
45262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochReduction JSInliner::ReduceJSCall(Node* node) {
453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(IrOpcode::IsInlineeOpcode(node->opcode()));
45462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<SharedFunctionInfo> shared_info;
455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  JSCallAccessor call(node);
45662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
45762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Determine the call target.
45862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!DetermineCallTarget(node, shared_info)) return NoChange();
45962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
46062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Inlining is only supported in the bytecode pipeline.
46162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!info_->is_optimizing_from_bytecode()) {
46262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    TRACE("Not inlining %s into %s due to use of the deprecated pipeline\n",
46362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          shared_info->DebugName()->ToCString().get(),
46462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          info_->shared_info()->DebugName()->ToCString().get());
46562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return NoChange();
46662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Function must be inlineable.
469109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (!shared_info->IsInlineable()) {
470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    TRACE("Not inlining %s into %s because callee is not inlineable\n",
471109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          shared_info->DebugName()->ToCString().get(),
472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          info_->shared_info()->DebugName()->ToCString().get());
473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return NoChange();
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
476014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Constructor must be constructable.
47762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (node->opcode() == IrOpcode::kJSConstruct &&
478109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      IsNonConstructible(shared_info)) {
479014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    TRACE("Not inlining %s into %s because constructor is not constructable.\n",
480109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          shared_info->DebugName()->ToCString().get(),
481014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          info_->shared_info()->DebugName()->ToCString().get());
482014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return NoChange();
483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
48562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // TODO(706642): Don't inline derived class constructors for now, as the
48662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // inlining logic doesn't deal properly with derived class constructors
48762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // that return a primitive, i.e. it's not in sync with what the Parser
48862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // and the JSConstructSub does.
48962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (node->opcode() == IrOpcode::kJSConstruct &&
49062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      IsDerivedConstructor(shared_info->kind())) {
49162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    TRACE("Not inlining %s into %s because constructor is derived.\n",
49262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          shared_info->DebugName()->ToCString().get(),
49362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          info_->shared_info()->DebugName()->ToCString().get());
49462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return NoChange();
49562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
49662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Class constructors are callable, but [[Call]] will raise an exception.
498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
49962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (node->opcode() == IrOpcode::kJSCall &&
500109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      IsClassConstructor(shared_info->kind())) {
501014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    TRACE("Not inlining %s into %s because callee is a class constructor.\n",
502109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          shared_info->DebugName()->ToCString().get(),
503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          info_->shared_info()->DebugName()->ToCString().get());
504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return NoChange();
505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Function contains break points.
508109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (shared_info->HasDebugInfo()) {
509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    TRACE("Not inlining %s into %s because callee may contain break points\n",
510109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          shared_info->DebugName()->ToCString().get(),
511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          info_->shared_info()->DebugName()->ToCString().get());
512014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return NoChange();
513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // TODO(turbofan): TranslatedState::GetAdaptedArguments() currently relies on
516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // not inlining recursive functions. We might want to relax that at some
517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // point.
51813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  for (Node* frame_state = call.frame_state();
519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       frame_state->opcode() == IrOpcode::kFrameState;
520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch       frame_state = frame_state->InputAt(kFrameStateOuterStateInput)) {
521109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state);
522109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    Handle<SharedFunctionInfo> frame_shared_info;
523109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (frame_info.shared_info().ToHandle(&frame_shared_info) &&
524109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        *frame_shared_info == *shared_info) {
525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      TRACE("Not inlining %s into %s because call is recursive\n",
526109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch            shared_info->DebugName()->ToCString().get(),
527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            info_->shared_info()->DebugName()->ToCString().get());
528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return NoChange();
529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
532f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Find the IfException node, if any.
533f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* exception_target = nullptr;
534f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  for (Edge edge : node->use_edges()) {
535f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (NodeProperties::IsControlEdge(edge) &&
536f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        edge.from()->opcode() == IrOpcode::kIfException) {
537f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      DCHECK_NULL(exception_target);
538f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      exception_target = edge.from();
539f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
540f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
541f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
542f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  NodeVector uncaught_subcalls(local_zone_);
543f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
544f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (exception_target != nullptr) {
545f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (!FLAG_inline_into_try) {
546f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      TRACE(
547f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          "Try block surrounds #%d:%s and --no-inline-into-try active, so not "
548f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          "inlining %s into %s.\n",
549f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          exception_target->id(), exception_target->op()->mnemonic(),
550109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch          shared_info->DebugName()->ToCString().get(),
551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          info_->shared_info()->DebugName()->ToCString().get());
552f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      return NoChange();
553f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    } else {
554f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      TRACE(
555f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          "Inlining %s into %s regardless of surrounding try-block to catcher "
556f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          "#%d:%s\n",
557f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          shared_info->DebugName()->ToCString().get(),
558f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          info_->shared_info()->DebugName()->ToCString().get(),
559f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          exception_target->id(), exception_target->op()->mnemonic());
560f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
56362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ParseInfo parse_info(shared_info);
56462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CompilationInfo info(parse_info.zone(), &parse_info,
56562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                       Handle<JSFunction>::null());
566109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  if (info_->is_deoptimization_enabled()) info.MarkAsDeoptimizationEnabled();
56762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  info.MarkAsOptimizeFromBytecode();
568f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
56962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!Compiler::EnsureBytecode(&info)) {
570f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    TRACE("Not inlining %s into %s because bytecode generation failed\n",
571f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          shared_info->DebugName()->ToCString().get(),
572f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          info_->shared_info()->DebugName()->ToCString().get());
573f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (info_->isolate()->has_pending_exception()) {
574f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      info_->isolate()->clear_pending_exception();
575f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
576f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return NoChange();
577f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Remember that we inlined this function. This needs to be called right
580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // after we ensure deoptimization support so that the code flusher
581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // does not remove the code with the deoptimization support.
582c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int inlining_id = info_->AddInlinedFunction(
583c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      shared_info, source_positions_->GetSourcePosition(node));
584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // ----------------------------------------------------------------
586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // After this point, we've made a decision to inline this function.
587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // We shall not bailout from inlining if we got here.
588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  TRACE("Inlining %s into %s\n",
590109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        shared_info->DebugName()->ToCString().get(),
591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        info_->shared_info()->DebugName()->ToCString().get());
592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
59362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Determine the targets feedback vector and its context.
59462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context;
59562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<FeedbackVector> feedback_vector;
59662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DetermineCallContext(node, context, feedback_vector);
59713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
59813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Create the subgraph for the inlinee.
59913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* start;
60013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* end;
60162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  {
602f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Run the BytecodeGraphBuilder to create the subgraph.
603f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    Graph::SubgraphScope scope(graph());
60462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    BytecodeGraphBuilder graph_builder(
60562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        parse_info.zone(), shared_info, feedback_vector, BailoutId::None(),
60662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        jsgraph(), call.frequency(), source_positions_, inlining_id);
60713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    graph_builder.CreateGraph(false);
60813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
60913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Extract the inlinee start/end nodes.
61013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    start = graph()->start();
61113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    end = graph()->end();
612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
614f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (exception_target != nullptr) {
615f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Find all uncaught 'calls' in the inlinee.
616f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    AllNodes inlined_nodes(local_zone_, end, graph());
617f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    for (Node* subnode : inlined_nodes.reachable) {
618f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // Every possibly throwing node with an IfSuccess should get an
619f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // IfException.
620f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      if (subnode->op()->HasProperty(Operator::kNoThrow)) {
621f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        continue;
622f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
623f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      bool hasIfException = false;
624f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      for (Node* use : subnode->uses()) {
625f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        if (use->opcode() == IrOpcode::kIfException) {
626f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          hasIfException = true;
627f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch          break;
628f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        }
629f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
630f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      if (!hasIfException) {
631f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        DCHECK_EQ(2, subnode->op()->ControlOutputCount());
632f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        uncaught_subcalls.push_back(subnode);
633f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
634f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
635f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
636f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
63713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* frame_state = call.frame_state();
638f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* new_target = jsgraph()->UndefinedConstant();
63913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
64062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Inline {JSConstruct} requires some additional magic.
64162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (node->opcode() == IrOpcode::kJSConstruct) {
64262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Swizzle the inputs of the {JSConstruct} node to look like inputs to a
64362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // normal {JSCall} node so that the rest of the inlining machinery
64462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // behaves as if we were dealing with a regular function invocation.
64562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    new_target = call.new_target();  // Retrieve new target value input.
64662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    node->RemoveInput(call.formal_arguments() + 1);  // Drop new target.
64762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    node->InsertInput(graph()->zone(), 1, new_target);
64862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
64913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Insert nodes around the call that model the behavior required for a
65013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // constructor dispatch (allocate implicit receiver and check return value).
65113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // This models the behavior usually accomplished by our {JSConstructStub}.
65213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Note that the context has to be the callers context (input to call node).
65362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Also note that by splitting off the {JSCreate} piece of the constructor
65462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // call, we create an observable deoptimization point after the receiver
65562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // instantiation but before the invocation (i.e. inside {JSConstructStub}
65662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // where execution continues at {construct_stub_create_deopt_pc_offset}).
657c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* receiver = jsgraph()->TheHoleConstant();  // Implicit receiver.
65813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (NeedsImplicitReceiver(shared_info)) {
65913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Node* effect = NodeProperties::GetEffectInput(node);
66062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* control = NodeProperties::GetControlInput(node);
66113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      Node* context = NodeProperties::GetContextInput(node);
66262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* frame_state_inside = CreateArtificialFrameState(
66362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          node, frame_state, call.formal_arguments(),
66462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          BailoutId::ConstructStubCreate(), FrameStateType::kConstructStub,
66562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          info.shared_info());
66662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* create =
66762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          graph()->NewNode(javascript()->Create(), call.target(), new_target,
66862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                           context, frame_state_inside, effect, control);
66962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* success = graph()->NewNode(common()->IfSuccess(), create);
67062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      uncaught_subcalls.push_back(create);  // Adds {IfException}.
67162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      NodeProperties::ReplaceControlInput(node, success);
67213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      NodeProperties::ReplaceEffectInput(node, create);
67313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      // Insert a check of the return value to determine whether the return
674f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // value or the implicit receiver should be selected as a result of the
675f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // call.
676f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* check = graph()->NewNode(simplified()->ObjectIsReceiver(), node);
677f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* select =
678f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
679f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                           check, node, create);
680f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      NodeProperties::ReplaceUses(node, select, node, node, node);
681f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Fix-up inputs that have been mangled by the {ReplaceUses} call above.
682f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      NodeProperties::ReplaceValueInput(select, node, 1);  // Fix-up input.
683f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      NodeProperties::ReplaceValueInput(check, node, 0);   // Fix-up input.
68413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      receiver = create;  // The implicit receiver.
68513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
68662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    node->ReplaceInput(1, receiver);
68713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Insert a construct stub frame into the chain of frame states. This will
689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // reconstruct the proper frame when deoptimizing within the constructor.
690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    frame_state = CreateArtificialFrameState(
691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        node, frame_state, call.formal_arguments(),
69262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        BailoutId::ConstructStubInvoke(), FrameStateType::kConstructStub,
69362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        info.shared_info());
694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
695958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Insert a JSConvertReceiver node for sloppy callees. Note that the context
69762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // passed into this node has to be the callees context (loaded above).
69862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (node->opcode() == IrOpcode::kJSCall &&
699f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      is_sloppy(shared_info->language_mode()) && !shared_info->native()) {
700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Node* effect = NodeProperties::GetEffectInput(node);
701f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (NeedsConvertReceiver(call.receiver(), effect)) {
70262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      const CallParameters& p = CallParametersOf(node->op());
70362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* convert = effect =
70462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          graph()->NewNode(javascript()->ConvertReceiver(p.convert_mode()),
70562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                           call.receiver(), context, effect, start);
706f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      NodeProperties::ReplaceValueInput(node, convert, 1);
707f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      NodeProperties::ReplaceEffectInput(node, effect);
708f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
7113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // If we are inlining a JS call at tail position then we have to pop current
7123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // frame state and its potential arguments adaptor frame state in order to
7133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // make the call stack be consistent with non-inlining case.
7143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // After that we add a tail caller frame state which lets deoptimizer handle
7153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // the case when the outermost function inlines a tail call (it should remove
7163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // potential arguments adaptor frame that belongs to outermost function when
7173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // deopt happens).
71862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (node->opcode() == IrOpcode::kJSCall) {
71962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    const CallParameters& p = CallParametersOf(node->op());
7203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (p.tail_call_mode() == TailCallMode::kAllow) {
7213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      frame_state = CreateTailCallerFrameState(node, frame_state);
7223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
7233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Insert argument adaptor frame if required. The callees formal parameter
726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // count (i.e. value outputs of start node minus target, receiver, new target,
727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // arguments count and context) have to match the number of arguments passed
728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to the call.
729f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  int parameter_count = shared_info->internal_formal_parameter_count();
730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK_EQ(parameter_count, start->op()->ValueOutputCount() - 5);
731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (call.formal_arguments() != parameter_count) {
732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    frame_state = CreateArtificialFrameState(
73362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        node, frame_state, call.formal_arguments(), BailoutId::None(),
734109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        FrameStateType::kArgumentsAdaptor, shared_info);
735958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
737f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return InlineCall(node, new_target, context, frame_state, start, end,
738f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                    exception_target, uncaught_subcalls);
739958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
74113e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochGraph* JSInliner::graph() const { return jsgraph()->graph(); }
74213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
743f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochJSOperatorBuilder* JSInliner::javascript() const {
744f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return jsgraph()->javascript();
745f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
746f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
747f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochCommonOperatorBuilder* JSInliner::common() const { return jsgraph()->common(); }
748f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
749f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochSimplifiedOperatorBuilder* JSInliner::simplified() const {
750f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return jsgraph()->simplified();
751f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
752f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace compiler
754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
756