25#if V8_ENABLE_WEBASSEMBLY 
   38static const int kMaxDepthForInlining = 50;
 
   43    if (v8_flags.trace_turbo_inlining) { \ 
   44      StdoutStream() << x << "\n";       \ 
 
   53    DCHECK(call->opcode() == IrOpcode::kJSCall ||
 
   54           call->opcode() == IrOpcode::kJSConstruct);
 
 
   58    return call_->
InputAt(JSCallOrConstructNode::TargetIndex());
 
 
 
   85#if V8_ENABLE_WEBASSEMBLY 
   89                                      Node* exception_target,
 
   91  JSWasmCallNode 
n(call);
 
   95      static_cast<int>(n.Parameters().signature()->parameter_count()));
 
  101                                Node* exception_target,
 
  103                                int argument_count) {
 
  113  int const inlinee_new_target_index = 
start.NewTargetOutputIndex();
 
  114  int const inlinee_arity_index = 
start.ArgCountOutputIndex();
 
  115  int const inlinee_context_index = 
start.ContextOutputIndex();
 
  119  const int inliner_inputs = argument_count +
 
  124    Node* use = edge.from();
 
  125    switch (use->opcode()) {
 
  126      case IrOpcode::kParameter: {
 
  129        if (index < inliner_inputs && index < inlinee_new_target_index) {
 
  132          Replace(use, call->InputAt(index));
 
  133        } 
else if (index == inlinee_new_target_index) {
 
  136        } 
else if (index == inlinee_arity_index) {
 
  139        } 
else if (index == inlinee_context_index) {
 
  143#ifdef V8_JS_LINKAGE_INCLUDES_DISPATCH_HANDLE 
  154          edge.UpdateTo(effect);
 
  156          edge.UpdateTo(control);
 
  158          edge.UpdateTo(frame_state);
 
  166  if (exception_target != 
nullptr) {
 
  168    int subcall_count = 
static_cast<int>(uncaught_subcalls.
size());
 
  169    if (subcall_count > 0) {
 
  170      TRACE(
"Inlinee contains " << subcall_count
 
  171                                << 
" calls without local exception handler; " 
  172                                << 
"linking to surrounding exception handler.");
 
  175    for (
Node* subcall : uncaught_subcalls) {
 
  181      on_exception_nodes.
push_back(on_exception);
 
  184    DCHECK_EQ(subcall_count, 
static_cast<int>(on_exception_nodes.
size()));
 
  185    if (subcall_count > 0) {
 
  186      Node* control_output =
 
  188                           &on_exception_nodes.
front());
 
  190      values_effects = on_exception_nodes;
 
  191      values_effects.
push_back(control_output);
 
  194          subcall_count + 1, &values_effects.
front());
 
  195      Node* effect_output =
 
  197                           subcall_count + 1, &values_effects.
front());
 
  210    switch (input->opcode()) {
 
  211      case IrOpcode::kReturn:
 
  216      case IrOpcode::kDeoptimize:
 
  217      case IrOpcode::kTerminate:
 
  218      case IrOpcode::kThrow:
 
  230  if (!values.empty()) {
 
  231    int const input_count = 
static_cast<int>(controls.
size());
 
  233                                            input_count, &controls.
front());
 
  234    values.push_back(control_output);
 
  238        static_cast<int>(values.size()), &values.front());
 
  239    Node* effect_output =
 
  241                         static_cast<int>(effects.
size()), &effects.
front());
 
 
  254    OptionalBytecodeArrayRef maybe_bytecode_array, 
Node* context,
 
  256  const int argument_count_with_receiver =
 
  260  if (maybe_bytecode_array.has_value()) {
 
  261    bytecode_array_handle = maybe_bytecode_array->object();
 
  265          frame_state_type, argument_count_with_receiver, 0, 0, shared.object(),
 
  266          bytecode_array_handle);
 
  273  Node* params_node = 
nullptr;
 
  274#if V8_ENABLE_WEBASSEMBLY 
  275  const bool skip_params =
 
  276      frame_state_type == FrameStateType::kWasmInlinedIntoJS;
 
  278  const bool skip_params = 
false;
 
  294        node->InputAt(JSCallOrConstructNode::ReceiverOrNewTargetIndex()));
 
  295    for (
int i = 0; 
i < argument_count; 
i++) {
 
  300    params_node = 
graph()->
NewNode(op_param, 
static_cast<int>(params.size()),
 
  303  if (context == 
nullptr) context = 
jsgraph()->UndefinedConstant();
 
  304  if (callee == 
nullptr) {
 
  305    callee = node->
InputAt(JSCallOrConstructNode::TargetIndex());
 
 
  315  return !shared_info.construct_as_builtin() &&
 
  326  Node* target = node->
InputAt(JSCallOrConstructNode::TargetIndex());
 
  337    if (!function.feedback_vector(
broker()).has_value()) {
 
  350            broker()->target_native_context())) {
 
  354    return function.shared(
broker());
 
  362  if (match.IsJSCreateClosure()) {
 
  366  } 
else if (match.IsCheckClosure()) {
 
  368    return cell.shared_function_info(
broker());
 
 
  380                                                Node** context_out) {
 
  382  Node* target = node->
InputAt(JSCallOrConstructNode::TargetIndex());
 
  388    CHECK(function.feedback_vector(
broker()).has_value());
 
  393    return function.raw_feedback_cell(
broker());
 
  396  if (match.IsJSCreateClosure()) {
 
  405  } 
else if (match.IsCheckClosure()) {
 
  412        match.
node(), effect, control);
 
 
  422#if V8_ENABLE_WEBASSEMBLY 
  423JSInliner::WasmInlineResult JSInliner::TryWasmInlining(
 
  424    const JSWasmCallNode& call_node) {
 
  425  const JSWasmCallParameters& wasm_call_params = call_node.Parameters();
 
  427  const int fct_index = wasm_call_params.function_index();
 
  428  TRACE(
"Considering wasm function [" 
  430        << WasmFunctionNameForTrace(native_module, fct_index) << 
" of module " 
  431        << wasm_call_params.module() << 
" for inlining");
 
  436    TRACE(
"- not inlining: another wasm module is already used for inlining");
 
  444    TRACE(
"- not inlining: wasm inlining into try catch is not supported");
 
  449  TFGraph::SubgraphScope graph_scope(
graph());
 
  457  bool can_inline_body =
 
  458      builder.TryWasmInlining(fct_index, native_module, inlining_id);
 
  459  if (can_inline_body) {
 
  468Reduction JSInliner::ReduceJSWasmCall(Node* node) {
 
  469  JSWasmCallNode call_node(node);
 
  470  const JSWasmCallParameters& wasm_call_params = call_node.Parameters();
 
  471  int fct_index = wasm_call_params.function_index();
 
  472  wasm::NativeModule* native_module = wasm_call_params.native_module();
 
  473  const wasm::CanonicalSig* 
sig = wasm_call_params.signature();
 
  477  WasmInlineResult inline_result;
 
  482    inline_result = TryWasmInlining(call_node);
 
  486  Node* wrapper_start_node;
 
  487  Node* wrapper_end_node;
 
  488  size_t subgraph_min_node_id;
 
  490    TFGraph::SubgraphScope scope(
graph());
 
  496    Node* continuation_frame_state =
 
  497        CreateJSWasmCallBuiltinContinuationFrameState(
 
  498            jsgraph(), call_node.context(), call_node.frame_state(), 
sig);
 
  510    bool set_in_wasm_flag = !(inline_result.can_inline_body ||
 
  511                              v8_flags.turboshaft_wasm_in_js_inlining);
 
  520  StartNode 
start{wrapper_start_node};
 
  522  Node* exception_target = 
nullptr;
 
  529  if (exception_target != 
nullptr) {
 
  532    for (Node* subnode : inlined_nodes.reachable) {
 
  534      if (subnode->id() < subgraph_min_node_id) 
continue;
 
  540        DCHECK_EQ(2, subnode->op()->ControlOutputCount());
 
  541        uncaught_subcalls.push_back(subnode);
 
  550  Node* wasm_fct_call = 
nullptr;
 
  551  if (inline_result.can_inline_body ||
 
  552      v8_flags.turboshaft_wasm_in_js_inlining) {
 
  554    for (Node* subnode : inlined_nodes.reachable) {
 
  556      if (subnode->id() < subgraph_min_node_id) 
continue;
 
  558      if (subnode->opcode() == IrOpcode::kCall &&
 
  560        wasm_fct_call = subnode;
 
  564    DCHECK_IMPLIES(inline_result.can_inline_body, wasm_fct_call != 
nullptr);
 
  568    if (
v8_flags.turboshaft_wasm_in_js_inlining && wasm_fct_call) {
 
  570          {wasm_fct_call->id(), &wasm_call_params});
 
  583                       wrapper_end_node, exception_target, uncaught_subcalls);
 
  585  if (inline_result.can_inline_body) {
 
  586    InlineWasmFunction(wasm_fct_call, inline_result.body_start,
 
  587                       inline_result.body_end, call_node.frame_state(),
 
  588                       wasm_call_params.shared_fct_info(),
 
  589                       call_node.ArgumentCount(), context);
 
  594void JSInliner::InlineWasmFunction(Node* call, Node* inlinee_start,
 
  595                                   Node* inlinee_end, Node* frame_state,
 
  596                                   SharedFunctionInfoRef shared_fct_info,
 
  597                                   int argument_count, Node* context) {
 
  609  Node* callee = 
jsgraph()->UndefinedConstant();
 
  611      call, FrameState{frame_state}, argument_count,
 
  612      FrameStateType::kWasmInlinedIntoJS, shared_fct_info, {}, 
context, callee);
 
  614                                       frame_state_inside, effect, control);
 
  615  effect = check_point;
 
  617  for (Edge edge : inlinee_start->use_edges()) {
 
  618    Node* use = edge.from();
 
  619    if (use == 
nullptr) 
continue;
 
  620    switch (use->opcode()) {
 
  621      case IrOpcode::kParameter: {
 
  630          edge.UpdateTo(effect);
 
  634          edge.UpdateTo(use->opcode() == IrOpcode::kProjection
 
  647  DCHECK_EQ(inlinee_end->inputs().count(), 1);
 
  648  Node* terminator = *inlinee_end->inputs().begin();
 
  649  DCHECK_EQ(terminator->opcode(), IrOpcode::kReturn);
 
  658  int return_values = terminator->InputCount();
 
  662  int return_count = return_values - 3;
 
  663  Node* effect_output = terminator->InputAt(return_count + 1);
 
  664  Node* control_output = terminator->InputAt(return_count + 2);
 
  665  for (Edge use_edge : call->use_edges()) {
 
  667      Node* use = use_edge.from();
 
  682#if V8_ENABLE_WEBASSEMBLY 
  683  DCHECK_NE(node->opcode(), IrOpcode::kJSWasmCall);
 
  689  if (!shared_info.has_value()) 
return NoChange();
 
  695      shared_info->GetInlineability(
broker());
 
  701    TRACE(
"Not inlining " << *shared_info << 
" into " << outer_shared_info
 
  702                          << 
" because it had its optimization disabled.");
 
  709  if (node->opcode() == IrOpcode::kJSConstruct &&
 
  711    TRACE(
"Not inlining " << *shared_info << 
" into " << outer_shared_info
 
  712                          << 
" because constructor is not constructable.");
 
  718  if (node->opcode() == IrOpcode::kJSCall &&
 
  720    TRACE(
"Not inlining " << *shared_info << 
" into " << outer_shared_info
 
  721                          << 
" because callee is a class constructor.");
 
  727  int nesting_level = 0;
 
  728  for (
Node* frame_state = call.frame_state();
 
  729       frame_state->
opcode() == IrOpcode::kFrameState;
 
  732    if (nesting_level > kMaxDepthForInlining) {
 
  733      TRACE(
"Not inlining " 
  734            << *shared_info << 
" into " << outer_shared_info
 
  735            << 
" because call has exceeded the maximum depth for function " 
  741  Node* exception_target = 
nullptr;
 
  749  CHECK(shared_info->is_compiled());
 
  751  if (
info_->source_positions() &&
 
  752      !shared_info->object()->AreSourcePositionsAvailable(
 
  753          broker()->local_isolate_or_isolate())) {
 
  760    TRACE(
"Not inlining " << *shared_info << 
" into " << outer_shared_info
 
  761                          << 
" because source positions are missing.");
 
  769  TRACE(
"Inlining " << *shared_info << 
" into " << outer_shared_info
 
  770                    << ((exception_target != 
nullptr) ? 
" (inside try-block)" 
  782  if (
v8_flags.profile_guided_optimization &&
 
  788          v8_flags.invocation_count_for_early_optimization) {
 
  789    info_->set_could_not_inline_all_candidates();
 
  800    if (
info_->analyze_environment_liveness()) {
 
  803    if (
info_->bailout_on_uninitialized()) {
 
  825  if (exception_target != 
nullptr) {
 
  843  if (node->opcode() == IrOpcode::kJSConstruct) {
 
  859    if (NeedsImplicitReceiver(*shared_info)) {
 
  860      Effect effect = n.effect();
 
  862      Node* frame_state_inside;
 
  864      if (
m.HasResolvedValue() && 
m.Ref(
broker()).IsJSFunction()) {
 
  867        frame_state_inside = frame_state;
 
  870            node, frame_state, n.ArgumentCount(),
 
  876                           caller_context, frame_state_inside, effect, control);
 
  891                           check, node, create);
 
  899      Node* branch_is_receiver =
 
  901      Node* branch_is_receiver_true =
 
  903      Node* branch_is_receiver_false =
 
  907              Runtime::kThrowConstructorReturnedNonObject),
 
  909          branch_is_receiver_false);
 
  910      uncaught_subcalls.
push_back(branch_is_receiver_false);
 
  911      branch_is_receiver_false =
 
  913                           branch_is_receiver_false);
 
  917                       branch_is_receiver_true);
 
  921    node->ReplaceInput(JSCallNode::ReceiverIndex(), 
receiver);
 
  926        *shared_info, bytecode_array, caller_context);
 
  931  if (node->opcode() == IrOpcode::kJSCall &&
 
  932      is_sloppy(shared_info->language_mode()) && !shared_info->native()) {
 
  937          broker()->target_native_context().global_proxy_object(
broker()),
 
  943          global_proxy, effect, 
start);
 
  945                                        JSCallNode::ReceiverIndex());
 
  954            shared_info->internal_formal_parameter_count_without_receiver());
 
  958        node, frame_state, call.argument_count(),
 
  963                    exception_target, uncaught_subcalls, call.argument_count());
 
 
static constexpr BytecodeOffset None()
int AddInlinedFunction(IndirectHandle< SharedFunctionInfo > inlined_function, IndirectHandle< BytecodeArray > inlined_bytecode, SourcePosition pos)
IndirectHandle< SharedFunctionInfo > shared_info() const
CodeKind code_kind() const
InlinedFunctionList & inlined_functions()
TickCounter & tick_counter()
@ kHasOptimizationDisabled
void push_back(const T &value)
static FieldAccess ForJSFunctionContext()
void ReplaceWithValue(Node *node, Node *value, Node *effect=nullptr, Node *control=nullptr)
void MergeControlToEnd(TFGraph *graph, CommonOperatorBuilder *common, Node *node)
static Reduction Replace(Node *node)
IndirectHandle< BytecodeArray > object() const
uint16_t parameter_count_without_receiver() const
ConvertReceiverMode convert_mode() const
const Operator * StateValues(int arguments, SparseInputMask bitmask)
const Operator * FrameState(BytecodeOffset bailout_id, OutputFrameStateCombine state_combine, const FrameStateFunctionInfo *function_info)
const FrameStateFunctionInfo * CreateFrameStateFunctionInfo(FrameStateType type, uint16_t parameter_count, uint16_t max_arguments, int local_count, IndirectHandle< SharedFunctionInfo > shared_info, IndirectHandle< BytecodeArray > bytecode_array)
OptionalSharedFunctionInfoRef shared_function_info(JSHeapBroker *broker) const
OptionalFeedbackVectorRef feedback_vector(JSHeapBroker *broker) const
Node * outer_frame_state() const
static bool IsInlineeOpcode(Value value)
CallFrequency const & frequency() const
FrameState frame_state() const
JSCallAccessor(Node *call)
int argument_count() const
Node * new_target() const
const CallParameters & Parameters() const
int ArgumentCount() const override
static constexpr int kFeedbackVectorInputCount
static constexpr int kReceiverOrNewTargetInputCount
static constexpr bool kHaveIdenticalLayouts
static constexpr int ArgumentIndex(int i)
static constexpr int kExtraInputCount
int ArgumentCount() const
const ConstructParameters & Parameters() const
JSOperatorBuilder * javascript() const
SimplifiedOperatorBuilder * simplified() const
Node * ConstantNoHole(ObjectRef ref, JSHeapBroker *broker)
Reduction ReduceJSCall(Node *node)
JSHeapBroker * broker() const
FrameState CreateArtificialFrameState(Node *node, FrameState outer_frame_state, int parameter_count, FrameStateType frame_state_type, SharedFunctionInfoRef shared, OptionalBytecodeArrayRef maybe_bytecode_array, Node *context=nullptr, Node *callee=nullptr)
Reduction InlineCall(Node *call, Node *new_target, Node *context, Node *frame_state, StartNode start, Node *end, Node *exception_target, const NodeVector &uncaught_subcalls, int argument_count)
CommonOperatorBuilder * common() const
NodeOriginTable *const node_origins_
Isolate * isolate() const
SimplifiedOperatorBuilder * simplified() const
JSGraph * jsgraph() const
JSOperatorBuilder * javascript() const
JsWasmCallsSidetable * js_wasm_calls_sidetable_
const wasm::WasmModule * wasm_module_
bool inline_wasm_fct_if_supported_
OptionalSharedFunctionInfoRef DetermineCallTarget(Node *node)
FeedbackCellRef DetermineCallContext(Node *node, Node **context_out)
OptimizedCompilationInfo * info_
SourcePositionTable *const source_positions_
CommonOperatorBuilder * common() const
static void ReplaceEffectInput(Node *node, Node *effect, int index=0)
static bool IsControlEdge(Edge edge)
static void ReplaceControlInput(Node *node, Node *control, int index=0)
static void ReplaceUses(Node *node, Node *value, Node *effect=nullptr, Node *success=nullptr, Node *exception=nullptr)
static Node * GetEffectInput(Node *node, int index=0)
static Node * GetContextInput(Node *node)
static bool IsValueEdge(Edge edge)
static bool IsFrameStateEdge(Edge edge)
static Node * GetFrameStateInput(Node *node)
static bool CanBePrimitive(JSHeapBroker *broker, Node *receiver, Effect effect)
static Node * GetValueInput(Node *node, int index)
static bool IsEffectEdge(Edge edge)
static void ReplaceValueInput(Node *node, Node *value, int index)
static bool IsExceptionalCall(Node *node, Node **out_exception=nullptr)
static Node * GetControlInput(Node *node, int index=0)
static Node * FindSuccessfulControlProjection(Node *node)
constexpr IrOpcode::Value opcode() const
const Operator * op() const
Node * InputAt(int index) const
static OutputFrameStateCombine Ignore()
static Reduction Changed(Node *node)
static Reduction NoChange()
SourcePosition GetSourcePosition(Node *node) const
Node * NewNode(const Operator *op, int input_count, Node *const *inputs, bool incomplete=false)
const WasmModule * module() const
WasmEnabledFeatures enabled_features() const
DirectHandle< Object > new_target
FrameState outer_frame_state
ZoneVector< RpoNumber > & result
TNode< Oddball > UndefinedConstant(JSGraph *jsgraph)
CallDescriptor const * CallDescriptorOf(const Operator *const op)
ZoneVector< Node * > NodeVector
int ParameterIndexOf(const Operator *const op)
const CallParameters & CallParametersOf(const Operator *op)
Handle< FeedbackCell > FeedbackCellOf(const Operator *op)
void BuildInlinedJSToWasmWrapper(Zone *zone, MachineGraph *mcgraph, const wasm::CanonicalSig *signature, Isolate *isolate, compiler::SourcePositionTable *spt, Node *frame_state, bool set_in_wasm_flag)
void BuildGraphFromBytecode(JSHeapBroker *broker, Zone *local_zone, SharedFunctionInfoRef shared_info, BytecodeArrayRef bytecode, FeedbackCellRef feedback_cell, BytecodeOffset osr_offset, JSGraph *jsgraph, CallFrequency const &invocation_frequency, SourcePositionTable *source_positions, NodeOriginTable *node_origins, int inlining_id, CodeKind code_kind, BytecodeGraphBuilderFlags flags, TickCounter *tick_counter, ObserveNodeInfo const &observe_node_info)
ref_traits< T >::ref_type MakeRef(JSHeapBroker *broker, Tagged< T > object)
@ kSkipFirstStackAndTierupCheck
@ kAnalyzeEnvironmentLiveness
@ kBailoutOnUninitialized
bool is_asmjs_module(const WasmModule *module)
Signature< ValueType > FunctionSig
bool is_sloppy(LanguageMode language_mode)
bool IsClassConstructor(FunctionKind kind)
bool IsDerivedConstructor(FunctionKind kind)
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
bool IsConstructable(FunctionKind kind)
V8_EXPORT_PRIVATE FlagValues v8_flags
static constexpr RelaxedLoadTag kRelaxedLoad
#define DCHECK_LE(v1, v2)
#define CHECK_LE(lhs, rhs)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
HeapObjectRef Ref(JSHeapBroker *broker) const
const Operator * op() const
bool HasResolvedValue() const