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()), ¶ms.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