LCOV - code coverage report
Current view: top level - src/compiler - wasm-compiler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1982 2374 83.5 %
Date: 2019-01-20 Functions: 186 233 79.8 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/wasm-compiler.h"
       6             : 
       7             : #include <memory>
       8             : 
       9             : #include "src/assembler-inl.h"
      10             : #include "src/assembler.h"
      11             : #include "src/base/optional.h"
      12             : #include "src/base/platform/elapsed-timer.h"
      13             : #include "src/base/platform/platform.h"
      14             : #include "src/base/v8-fallthrough.h"
      15             : #include "src/builtins/builtins.h"
      16             : #include "src/code-factory.h"
      17             : #include "src/compiler/backend/code-generator.h"
      18             : #include "src/compiler/backend/instruction-selector.h"
      19             : #include "src/compiler/common-operator.h"
      20             : #include "src/compiler/compiler-source-position-table.h"
      21             : #include "src/compiler/diamond.h"
      22             : #include "src/compiler/graph-visualizer.h"
      23             : #include "src/compiler/graph.h"
      24             : #include "src/compiler/int64-lowering.h"
      25             : #include "src/compiler/js-graph.h"
      26             : #include "src/compiler/js-operator.h"
      27             : #include "src/compiler/linkage.h"
      28             : #include "src/compiler/machine-operator.h"
      29             : #include "src/compiler/node-matchers.h"
      30             : #include "src/compiler/node-origin-table.h"
      31             : #include "src/compiler/pipeline.h"
      32             : #include "src/compiler/simd-scalar-lowering.h"
      33             : #include "src/compiler/zone-stats.h"
      34             : #include "src/counters.h"
      35             : #include "src/heap/factory.h"
      36             : #include "src/interface-descriptors.h"
      37             : #include "src/isolate-inl.h"
      38             : #include "src/log-inl.h"
      39             : #include "src/objects/heap-number.h"
      40             : #include "src/optimized-compilation-info.h"
      41             : #include "src/tracing/trace-event.h"
      42             : #include "src/trap-handler/trap-handler.h"
      43             : #include "src/wasm/function-body-decoder.h"
      44             : #include "src/wasm/function-compiler.h"
      45             : #include "src/wasm/graph-builder-interface.h"
      46             : #include "src/wasm/jump-table-assembler.h"
      47             : #include "src/wasm/memory-tracing.h"
      48             : #include "src/wasm/object-access.h"
      49             : #include "src/wasm/wasm-code-manager.h"
      50             : #include "src/wasm/wasm-limits.h"
      51             : #include "src/wasm/wasm-linkage.h"
      52             : #include "src/wasm/wasm-module.h"
      53             : #include "src/wasm/wasm-objects-inl.h"
      54             : #include "src/wasm/wasm-opcodes.h"
      55             : #include "src/wasm/wasm-text.h"
      56             : 
      57             : namespace v8 {
      58             : namespace internal {
      59             : namespace compiler {
      60             : 
      61             : namespace {
      62             : 
      63             : // TODO(titzer): pull WASM_64 up to a common header.
      64             : #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64
      65             : #define WASM_64 1
      66             : #else
      67             : #define WASM_64 0
      68             : #endif
      69             : 
      70             : #define FATAL_UNSUPPORTED_OPCODE(opcode)        \
      71             :   FATAL("Unsupported opcode 0x%x:%s", (opcode), \
      72             :         wasm::WasmOpcodes::OpcodeName(opcode));
      73             : 
      74             : MachineType assert_size(int expected_size, MachineType type) {
      75             :   DCHECK_EQ(expected_size, ElementSizeInBytes(type.representation()));
      76             :   return type;
      77             : }
      78             : 
      79             : #define WASM_INSTANCE_OBJECT_SIZE(name)     \
      80             :   (WasmInstanceObject::k##name##OffsetEnd - \
      81             :    WasmInstanceObject::k##name##Offset + 1)  // NOLINT(whitespace/indent)
      82             : 
      83             : #define WASM_INSTANCE_OBJECT_OFFSET(name) \
      84             :   wasm::ObjectAccess::ToTagged(WasmInstanceObject::k##name##Offset)
      85             : 
      86             : #define LOAD_RAW(base_pointer, byte_offset, type)                             \
      87             :   SetEffect(graph()->NewNode(mcgraph()->machine()->Load(type), base_pointer,  \
      88             :                              mcgraph()->Int32Constant(byte_offset), Effect(), \
      89             :                              Control()))
      90             : 
      91             : #define LOAD_INSTANCE_FIELD(name, type)                             \
      92             :   LOAD_RAW(instance_node_.get(), WASM_INSTANCE_OBJECT_OFFSET(name), \
      93             :            assert_size(WASM_INSTANCE_OBJECT_SIZE(name), type))
      94             : 
      95             : #define LOAD_TAGGED_POINTER(base_pointer, byte_offset) \
      96             :   LOAD_RAW(base_pointer, byte_offset, MachineType::TaggedPointer())
      97             : 
      98             : #define LOAD_TAGGED_ANY(base_pointer, byte_offset) \
      99             :   LOAD_RAW(base_pointer, byte_offset, MachineType::AnyTagged())
     100             : 
     101             : #define LOAD_FIXED_ARRAY_SLOT(array_node, index, type) \
     102             :   LOAD_RAW(array_node,                                 \
     103             :            wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(index), type)
     104             : 
     105             : #define LOAD_FIXED_ARRAY_SLOT_SMI(array_node, index) \
     106             :   LOAD_FIXED_ARRAY_SLOT(array_node, index, MachineType::TaggedSigned())
     107             : 
     108             : #define LOAD_FIXED_ARRAY_SLOT_PTR(array_node, index) \
     109             :   LOAD_FIXED_ARRAY_SLOT(array_node, index, MachineType::TaggedPointer())
     110             : 
     111             : #define LOAD_FIXED_ARRAY_SLOT_ANY(array_node, index) \
     112             :   LOAD_FIXED_ARRAY_SLOT(array_node, index, MachineType::AnyTagged())
     113             : 
     114             : // This can be used to store tagged Smi values only.
     115             : #define STORE_FIXED_ARRAY_SLOT_SMI(array_node, index, value)           \
     116             :   SetEffect(graph()->NewNode(                                          \
     117             :       mcgraph()->machine()->Store(StoreRepresentation(                 \
     118             :           MachineRepresentation::kTaggedSigned, kNoWriteBarrier)),     \
     119             :       array_node,                                                      \
     120             :       mcgraph()->Int32Constant(                                        \
     121             :           wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(index)), \
     122             :       value, Effect(), Control()))
     123             : 
     124             : // This can be used to store any tagged (Smi and HeapObject) value.
     125             : #define STORE_FIXED_ARRAY_SLOT_ANY(array_node, index, value)           \
     126             :   SetEffect(graph()->NewNode(                                          \
     127             :       mcgraph()->machine()->Store(StoreRepresentation(                 \
     128             :           MachineRepresentation::kTagged, kFullWriteBarrier)),         \
     129             :       array_node,                                                      \
     130             :       mcgraph()->Int32Constant(                                        \
     131             :           wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(index)), \
     132             :       value, Effect(), Control()))
     133             : 
     134     2629972 : void MergeControlToEnd(MachineGraph* mcgraph, Node* node) {
     135     1314986 :   Graph* g = mcgraph->graph();
     136     1314986 :   if (g->end()) {
     137       87013 :     NodeProperties::MergeControlToEnd(g, mcgraph->common(), node);
     138             :   } else {
     139     1227973 :     g->SetEnd(g->NewNode(mcgraph->common()->End(1), node));
     140             :   }
     141     1315062 : }
     142             : 
     143             : bool ContainsSimd(wasm::FunctionSig* sig) {
     144     2928623 :   for (auto type : sig->all()) {
     145     1464284 :     if (type == wasm::kWasmS128) return true;
     146             :   }
     147             :   return false;
     148             : }
     149             : 
     150             : bool ContainsInt64(wasm::FunctionSig* sig) {
     151        3886 :   for (auto type : sig->all()) {
     152        1964 :     if (type == wasm::kWasmI64) return true;
     153             :   }
     154             :   return false;
     155             : }
     156             : }  // namespace
     157             : 
     158     1233795 : WasmGraphBuilder::WasmGraphBuilder(
     159             :     wasm::CompilationEnv* env, Zone* zone, MachineGraph* mcgraph,
     160             :     wasm::FunctionSig* sig,
     161             :     compiler::SourcePositionTable* source_position_table)
     162             :     : zone_(zone),
     163             :       mcgraph_(mcgraph),
     164             :       env_(env),
     165             :       cur_buffer_(def_buffer_),
     166             :       cur_bufsize_(kDefaultBufferSize),
     167             :       has_simd_(ContainsSimd(sig)),
     168             :       untrusted_code_mitigations_(FLAG_untrusted_code_mitigations),
     169             :       sig_(sig),
     170     2467590 :       source_position_table_(source_position_table) {
     171             :   DCHECK_IMPLIES(use_trap_handler(), trap_handler::IsTrapHandlerEnabled());
     172             :   DCHECK_NOT_NULL(mcgraph_);
     173     1233795 : }
     174             : 
     175           0 : Node* WasmGraphBuilder::Error() { return mcgraph()->Dead(); }
     176             : 
     177     2467878 : Node* WasmGraphBuilder::Start(unsigned params) {
     178     2467878 :   Node* start = graph()->NewNode(mcgraph()->common()->Start(params));
     179             :   graph()->SetStart(start);
     180     1233815 :   return start;
     181             : }
     182             : 
     183     1477800 : Node* WasmGraphBuilder::Param(unsigned index) {
     184             :   return graph()->NewNode(mcgraph()->common()->Parameter(index),
     185     2955583 :                           graph()->start());
     186             : }
     187             : 
     188       10673 : Node* WasmGraphBuilder::Loop(Node* entry) {
     189       21348 :   return graph()->NewNode(mcgraph()->common()->Loop(1), entry);
     190             : }
     191             : 
     192       21353 : Node* WasmGraphBuilder::TerminateLoop(Node* effect, Node* control) {
     193             :   Node* terminate =
     194       10677 :       graph()->NewNode(mcgraph()->common()->Terminate(), effect, control);
     195       10676 :   MergeControlToEnd(mcgraph(), terminate);
     196       10674 :   return terminate;
     197             : }
     198             : 
     199        2031 : Node* WasmGraphBuilder::TerminateThrow(Node* effect, Node* control) {
     200             :   Node* terminate =
     201        1015 :       graph()->NewNode(mcgraph()->common()->Throw(), effect, control);
     202        1016 :   MergeControlToEnd(mcgraph(), terminate);
     203        1016 :   return terminate;
     204             : }
     205             : 
     206     2761956 : bool WasmGraphBuilder::IsPhiWithMerge(Node* phi, Node* merge) {
     207     3027842 :   return phi && IrOpcode::IsPhiOpcode(phi->opcode()) &&
     208     1646863 :          NodeProperties::GetControlInput(phi) == merge;
     209             : }
     210             : 
     211        1187 : bool WasmGraphBuilder::ThrowsException(Node* node, Node** if_success,
     212        1295 :                                        Node** if_exception) {
     213        1187 :   if (node->op()->HasProperty(compiler::Operator::kNoThrow)) {
     214             :     return false;
     215             :   }
     216             : 
     217        1295 :   *if_success = graph()->NewNode(mcgraph()->common()->IfSuccess(), node);
     218             :   *if_exception =
     219        1295 :       graph()->NewNode(mcgraph()->common()->IfException(), node, node);
     220             : 
     221         648 :   return true;
     222             : }
     223             : 
     224      484562 : void WasmGraphBuilder::AppendToMerge(Node* merge, Node* from) {
     225             :   DCHECK(IrOpcode::IsMergeOpcode(merge->opcode()));
     226      242279 :   merge->AppendInput(mcgraph()->zone(), from);
     227             :   int new_size = merge->InputCount();
     228             :   NodeProperties::ChangeOp(
     229      242283 :       merge, mcgraph()->common()->ResizeMergeOrPhi(merge->op(), new_size));
     230      242279 : }
     231             : 
     232      379687 : void WasmGraphBuilder::AppendToPhi(Node* phi, Node* from) {
     233             :   DCHECK(IrOpcode::IsPhiOpcode(phi->opcode()));
     234             :   int new_size = phi->InputCount();
     235      253122 :   phi->InsertInput(mcgraph()->zone(), phi->InputCount() - 1, from);
     236             :   NodeProperties::ChangeOp(
     237      126565 :       phi, mcgraph()->common()->ResizeMergeOrPhi(phi->op(), new_size));
     238      126561 : }
     239             : 
     240       94410 : Node* WasmGraphBuilder::Merge(unsigned count, Node** controls) {
     241      141615 :   return graph()->NewNode(mcgraph()->common()->Merge(count), count, controls);
     242             : }
     243             : 
     244      115311 : Node* WasmGraphBuilder::Phi(wasm::ValueType type, unsigned count, Node** vals,
     245      115310 :                             Node* control) {
     246             :   DCHECK(IrOpcode::IsMergeOpcode(control->opcode()));
     247      115311 :   Node** buf = Realloc(vals, count, count + 1);
     248      115313 :   buf[count] = control;
     249             :   return graph()->NewNode(
     250             :       mcgraph()->common()->Phi(wasm::ValueTypes::MachineRepresentationFor(type),
     251             :                                count),
     252      345933 :       count + 1, buf);
     253             : }
     254             : 
     255       36377 : Node* WasmGraphBuilder::EffectPhi(unsigned count, Node** effects,
     256       36380 :                                   Node* control) {
     257             :   DCHECK(IrOpcode::IsMergeOpcode(control->opcode()));
     258       36377 :   Node** buf = Realloc(effects, count, count + 1);
     259       36380 :   buf[count] = control;
     260             :   return graph()->NewNode(mcgraph()->common()->EffectPhi(count), count + 1,
     261      109139 :                           buf);
     262             : }
     263             : 
     264         900 : Node* WasmGraphBuilder::RefNull() {
     265         540 :   return LOAD_INSTANCE_FIELD(NullValue, MachineType::TaggedPointer());
     266             : }
     267             : 
     268        3285 : Node* WasmGraphBuilder::NoContextConstant() {
     269             :   // TODO(titzer): avoiding a dependency on JSGraph here. Refactor.
     270        3285 :   return mcgraph()->IntPtrConstant(0);
     271             : }
     272             : 
     273        1538 : Node* WasmGraphBuilder::Uint32Constant(uint32_t value) {
     274           0 :   return mcgraph()->Uint32Constant(value);
     275             : }
     276             : 
     277     3090024 : Node* WasmGraphBuilder::Int32Constant(int32_t value) {
     278     3090374 :   return mcgraph()->Int32Constant(value);
     279             : }
     280             : 
     281       40391 : Node* WasmGraphBuilder::Int64Constant(int64_t value) {
     282       40391 :   return mcgraph()->Int64Constant(value);
     283             : }
     284             : 
     285       38706 : Node* WasmGraphBuilder::IntPtrConstant(intptr_t value) {
     286       38706 :   return mcgraph()->IntPtrConstant(value);
     287             : }
     288             : 
     289       28330 : void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position,
     290      195189 :                                   Node** effect, Node** control) {
     291             :   DCHECK_NOT_NULL(env_);  // Wrappers don't get stack checks.
     292       28330 :   if (FLAG_wasm_no_stack_checks || !env_->runtime_exception_support) {
     293        6220 :     return;
     294             :   }
     295       22110 :   if (effect == nullptr) effect = effect_;
     296       22110 :   if (control == nullptr) control = control_;
     297             : 
     298             :   // This instruction sequence is matched in the instruction selector to
     299             :   // load the stack pointer directly on some platforms. Hence, when modifying
     300             :   // please also fix WasmStackCheckMatcher in node-matchers.h
     301             : 
     302             :   Node* limit_address = graph()->NewNode(
     303             :       mcgraph()->machine()->Load(MachineType::Pointer()), instance_node_.get(),
     304             :       mcgraph()->Int32Constant(WASM_INSTANCE_OBJECT_OFFSET(StackLimitAddress)),
     305       66347 :       *effect, *control);
     306             :   Node* limit = graph()->NewNode(
     307             :       mcgraph()->machine()->Load(MachineType::Pointer()), limit_address,
     308       66398 :       mcgraph()->IntPtrConstant(0), limit_address, *control);
     309       22135 :   *effect = limit;
     310       22135 :   Node* pointer = graph()->NewNode(mcgraph()->machine()->LoadStackPointer());
     311             : 
     312             :   Node* check =
     313       22122 :       graph()->NewNode(mcgraph()->machine()->UintLessThan(), limit, pointer);
     314             : 
     315       44234 :   Diamond stack_check(graph(), mcgraph()->common(), check, BranchHint::kTrue);
     316       22119 :   stack_check.Chain(*control);
     317             : 
     318       22125 :   if (stack_check_call_operator_ == nullptr) {
     319             :     // Build and cache the stack check call operator and the constant
     320             :     // representing the stack check code.
     321             :     auto call_descriptor = Linkage::GetStubCallDescriptor(
     322             :         mcgraph()->zone(),                    // zone
     323             :         NoContextDescriptor{},                // descriptor
     324             :         0,                                    // stack parameter count
     325             :         CallDescriptor::kNoFlags,             // flags
     326             :         Operator::kNoProperties,              // properties
     327       26871 :         StubCallMode::kCallWasmRuntimeStub);  // stub call mode
     328             :     // A direct call to a wasm runtime stub defined in this module.
     329             :     // Just encode the stub index. This will be patched at relocation.
     330             :     stack_check_code_node_.set(mcgraph()->RelocatableIntPtrConstant(
     331       13429 :         wasm::WasmCode::kWasmStackGuard, RelocInfo::WASM_STUB_CALL));
     332       13444 :     stack_check_call_operator_ = mcgraph()->common()->Call(call_descriptor);
     333             :   }
     334             : 
     335             :   Node* call = graph()->NewNode(stack_check_call_operator_.get(),
     336             :                                 stack_check_code_node_.get(), *effect,
     337       22129 :                                 stack_check.if_false);
     338             : 
     339       22132 :   SetSourcePosition(call, position);
     340             : 
     341       22134 :   Node* ephi = stack_check.EffectPhi(*effect, call);
     342             : 
     343       22133 :   *control = stack_check.merge;
     344       22133 :   *effect = ephi;
     345             : }
     346             : 
     347     1060550 : void WasmGraphBuilder::PatchInStackCheckIfNeeded() {
     348     2109280 :   if (!needs_stack_check_) return;
     349             : 
     350       17664 :   Node* start = graph()->start();
     351             :   // Place a stack check which uses a dummy node as control and effect.
     352       17664 :   Node* dummy = graph()->NewNode(mcgraph()->common()->Dead());
     353       17673 :   Node* control = dummy;
     354       17673 :   Node* effect = dummy;
     355             :   // The function-prologue stack check is associated with position 0, which
     356             :   // is never a position of any instruction in the function.
     357       17673 :   StackCheck(0, &effect, &control);
     358             : 
     359             :   // In testing, no steck checks were emitted. Nothing to rewire then.
     360       17685 :   if (effect == dummy) return;
     361             : 
     362             :   // Now patch all control uses of {start} to use {control} and all effect uses
     363             :   // to use {effect} instead. Then rewire the dummy node to use start instead.
     364       11841 :   NodeProperties::ReplaceUses(start, start, effect, control);
     365       11840 :   NodeProperties::ReplaceUses(dummy, nullptr, start, start);
     366             : }
     367             : 
     368     1464901 : Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
     369     1464901 :                               wasm::WasmCodePosition position) {
     370             :   const Operator* op;
     371     1464901 :   MachineOperatorBuilder* m = mcgraph()->machine();
     372     1464901 :   switch (opcode) {
     373             :     case wasm::kExprI32Add:
     374      142480 :       op = m->Int32Add();
     375      142474 :       break;
     376             :     case wasm::kExprI32Sub:
     377       51123 :       op = m->Int32Sub();
     378       51123 :       break;
     379             :     case wasm::kExprI32Mul:
     380       39770 :       op = m->Int32Mul();
     381       39770 :       break;
     382             :     case wasm::kExprI32DivS:
     383       35303 :       return BuildI32DivS(left, right, position);
     384             :     case wasm::kExprI32DivU:
     385       35173 :       return BuildI32DivU(left, right, position);
     386             :     case wasm::kExprI32RemS:
     387       35157 :       return BuildI32RemS(left, right, position);
     388             :     case wasm::kExprI32RemU:
     389       35128 :       return BuildI32RemU(left, right, position);
     390             :     case wasm::kExprI32And:
     391      148494 :       op = m->Word32And();
     392      148494 :       break;
     393             :     case wasm::kExprI32Ior:
     394       40267 :       op = m->Word32Or();
     395       40267 :       break;
     396             :     case wasm::kExprI32Xor:
     397       34723 :       op = m->Word32Xor();
     398       34723 :       break;
     399             :     case wasm::kExprI32Shl:
     400       48881 :       op = m->Word32Shl();
     401       48881 :       right = MaskShiftCount32(right);
     402       48881 :       break;
     403             :     case wasm::kExprI32ShrU:
     404       53394 :       op = m->Word32Shr();
     405       53394 :       right = MaskShiftCount32(right);
     406       53394 :       break;
     407             :     case wasm::kExprI32ShrS:
     408       36896 :       op = m->Word32Sar();
     409       36896 :       right = MaskShiftCount32(right);
     410       36896 :       break;
     411             :     case wasm::kExprI32Ror:
     412       67328 :       op = m->Word32Ror();
     413       67328 :       right = MaskShiftCount32(right);
     414       67328 :       break;
     415             :     case wasm::kExprI32Rol:
     416       33664 :       right = MaskShiftCount32(right);
     417       33664 :       return BuildI32Rol(left, right);
     418             :     case wasm::kExprI32Eq:
     419      149838 :       op = m->Word32Equal();
     420      149838 :       break;
     421             :     case wasm::kExprI32Ne:
     422       74913 :       return Invert(Binop(wasm::kExprI32Eq, left, right));
     423             :     case wasm::kExprI32LtS:
     424       35977 :       op = m->Int32LessThan();
     425       35977 :       break;
     426             :     case wasm::kExprI32LeS:
     427       34679 :       op = m->Int32LessThanOrEqual();
     428       34679 :       break;
     429             :     case wasm::kExprI32LtU:
     430       38823 :       op = m->Uint32LessThan();
     431       38823 :       break;
     432             :     case wasm::kExprI32LeU:
     433       33847 :       op = m->Uint32LessThanOrEqual();
     434       33847 :       break;
     435             :     case wasm::kExprI32GtS:
     436       36251 :       op = m->Int32LessThan();
     437             :       std::swap(left, right);
     438             :       break;
     439             :     case wasm::kExprI32GeS:
     440       34341 :       op = m->Int32LessThanOrEqual();
     441             :       std::swap(left, right);
     442             :       break;
     443             :     case wasm::kExprI32GtU:
     444       35711 :       op = m->Uint32LessThan();
     445             :       std::swap(left, right);
     446             :       break;
     447             :     case wasm::kExprI32GeU:
     448       33835 :       op = m->Uint32LessThanOrEqual();
     449             :       std::swap(left, right);
     450             :       break;
     451             :     case wasm::kExprI64And:
     452         233 :       op = m->Word64And();
     453         233 :       break;
     454             :     case wasm::kExprI64Add:
     455        1564 :       op = m->Int64Add();
     456        1564 :       break;
     457             :     case wasm::kExprI64Sub:
     458        1758 :       op = m->Int64Sub();
     459        1758 :       break;
     460             :     case wasm::kExprI64Mul:
     461        1718 :       op = m->Int64Mul();
     462        1718 :       break;
     463             :     case wasm::kExprI64DivS:
     464        1663 :       return BuildI64DivS(left, right, position);
     465             :     case wasm::kExprI64DivU:
     466        1535 :       return BuildI64DivU(left, right, position);
     467             :     case wasm::kExprI64RemS:
     468        1517 :       return BuildI64RemS(left, right, position);
     469             :     case wasm::kExprI64RemU:
     470        1517 :       return BuildI64RemU(left, right, position);
     471             :     case wasm::kExprI64Ior:
     472       12932 :       op = m->Word64Or();
     473       12931 :       break;
     474             :     case wasm::kExprI64Xor:
     475         113 :       op = m->Word64Xor();
     476         113 :       break;
     477             :     case wasm::kExprI64Shl:
     478       14437 :       op = m->Word64Shl();
     479       14437 :       right = MaskShiftCount64(right);
     480       14440 :       break;
     481             :     case wasm::kExprI64ShrU:
     482        1584 :       op = m->Word64Shr();
     483        1584 :       right = MaskShiftCount64(right);
     484        1584 :       break;
     485             :     case wasm::kExprI64ShrS:
     486        1521 :       op = m->Word64Sar();
     487        1521 :       right = MaskShiftCount64(right);
     488        1521 :       break;
     489             :     case wasm::kExprI64Eq:
     490         308 :       op = m->Word64Equal();
     491         308 :       break;
     492             :     case wasm::kExprI64Ne:
     493          93 :       return Invert(Binop(wasm::kExprI64Eq, left, right));
     494             :     case wasm::kExprI64LtS:
     495          80 :       op = m->Int64LessThan();
     496          80 :       break;
     497             :     case wasm::kExprI64LeS:
     498          53 :       op = m->Int64LessThanOrEqual();
     499          53 :       break;
     500             :     case wasm::kExprI64LtU:
     501          62 :       op = m->Uint64LessThan();
     502          62 :       break;
     503             :     case wasm::kExprI64LeU:
     504          71 :       op = m->Uint64LessThanOrEqual();
     505          71 :       break;
     506             :     case wasm::kExprI64GtS:
     507          62 :       op = m->Int64LessThan();
     508             :       std::swap(left, right);
     509             :       break;
     510             :     case wasm::kExprI64GeS:
     511          53 :       op = m->Int64LessThanOrEqual();
     512             :       std::swap(left, right);
     513             :       break;
     514             :     case wasm::kExprI64GtU:
     515          62 :       op = m->Uint64LessThan();
     516             :       std::swap(left, right);
     517             :       break;
     518             :     case wasm::kExprI64GeU:
     519          53 :       op = m->Uint64LessThanOrEqual();
     520             :       std::swap(left, right);
     521             :       break;
     522             :     case wasm::kExprI64Ror:
     523         196 :       op = m->Word64Ror();
     524         196 :       right = MaskShiftCount64(right);
     525         196 :       break;
     526             :     case wasm::kExprI64Rol:
     527          98 :       return BuildI64Rol(left, right);
     528             :     case wasm::kExprF32CopySign:
     529          47 :       return BuildF32CopySign(left, right);
     530             :     case wasm::kExprF64CopySign:
     531          47 :       return BuildF64CopySign(left, right);
     532             :     case wasm::kExprF32Add:
     533         560 :       op = m->Float32Add();
     534         560 :       break;
     535             :     case wasm::kExprF32Sub:
     536         366 :       op = m->Float32Sub();
     537         366 :       break;
     538             :     case wasm::kExprF32Mul:
     539         490 :       op = m->Float32Mul();
     540         490 :       break;
     541             :     case wasm::kExprF32Div:
     542         410 :       op = m->Float32Div();
     543         410 :       break;
     544             :     case wasm::kExprF32Eq:
     545        1394 :       op = m->Float32Equal();
     546        1394 :       break;
     547             :     case wasm::kExprF32Ne:
     548        1247 :       return Invert(Binop(wasm::kExprF32Eq, left, right));
     549             :     case wasm::kExprF32Lt:
     550         448 :       op = m->Float32LessThan();
     551         448 :       break;
     552             :     case wasm::kExprF32Ge:
     553         130 :       op = m->Float32LessThanOrEqual();
     554             :       std::swap(left, right);
     555             :       break;
     556             :     case wasm::kExprF32Gt:
     557         397 :       op = m->Float32LessThan();
     558             :       std::swap(left, right);
     559             :       break;
     560             :     case wasm::kExprF32Le:
     561         148 :       op = m->Float32LessThanOrEqual();
     562         148 :       break;
     563             :     case wasm::kExprF64Add:
     564        4973 :       op = m->Float64Add();
     565        4973 :       break;
     566             :     case wasm::kExprF64Sub:
     567        3466 :       op = m->Float64Sub();
     568        3466 :       break;
     569             :     case wasm::kExprF64Mul:
     570        7713 :       op = m->Float64Mul();
     571        7712 :       break;
     572             :     case wasm::kExprF64Div:
     573         747 :       op = m->Float64Div();
     574         747 :       break;
     575             :     case wasm::kExprF64Eq:
     576        1008 :       op = m->Float64Equal();
     577        1008 :       break;
     578             :     case wasm::kExprF64Ne:
     579         621 :       return Invert(Binop(wasm::kExprF64Eq, left, right));
     580             :     case wasm::kExprF64Lt:
     581         909 :       op = m->Float64LessThan();
     582         909 :       break;
     583             :     case wasm::kExprF64Le:
     584         357 :       op = m->Float64LessThanOrEqual();
     585         357 :       break;
     586             :     case wasm::kExprF64Gt:
     587         835 :       op = m->Float64LessThan();
     588             :       std::swap(left, right);
     589             :       break;
     590             :     case wasm::kExprF64Ge:
     591         365 :       op = m->Float64LessThanOrEqual();
     592             :       std::swap(left, right);
     593             :       break;
     594             :     case wasm::kExprF32Min:
     595          98 :       op = m->Float32Min();
     596          98 :       break;
     597             :     case wasm::kExprF64Min:
     598         104 :       op = m->Float64Min();
     599         104 :       break;
     600             :     case wasm::kExprF32Max:
     601          93 :       op = m->Float32Max();
     602          93 :       break;
     603             :     case wasm::kExprF64Max:
     604         100 :       op = m->Float64Max();
     605         100 :       break;
     606             :     case wasm::kExprF64Pow:
     607          11 :       return BuildF64Pow(left, right);
     608             :     case wasm::kExprF64Atan2:
     609          20 :       op = m->Float64Atan2();
     610          20 :       break;
     611             :     case wasm::kExprF64Mod:
     612          25 :       return BuildF64Mod(left, right);
     613             :     case wasm::kExprI32AsmjsDivS:
     614         512 :       return BuildI32AsmjsDivS(left, right);
     615             :     case wasm::kExprI32AsmjsDivU:
     616         169 :       return BuildI32AsmjsDivU(left, right);
     617             :     case wasm::kExprI32AsmjsRemS:
     618         566 :       return BuildI32AsmjsRemS(left, right);
     619             :     case wasm::kExprI32AsmjsRemU:
     620         228 :       return BuildI32AsmjsRemU(left, right);
     621             :     case wasm::kExprI32AsmjsStoreMem8:
     622        3555 :       return BuildAsmjsStoreMem(MachineType::Int8(), left, right);
     623             :     case wasm::kExprI32AsmjsStoreMem16:
     624        1638 :       return BuildAsmjsStoreMem(MachineType::Int16(), left, right);
     625             :     case wasm::kExprI32AsmjsStoreMem:
     626       37038 :       return BuildAsmjsStoreMem(MachineType::Int32(), left, right);
     627             :     case wasm::kExprF32AsmjsStoreMem:
     628        3960 :       return BuildAsmjsStoreMem(MachineType::Float32(), left, right);
     629             :     case wasm::kExprF64AsmjsStoreMem:
     630         827 :       return BuildAsmjsStoreMem(MachineType::Float64(), left, right);
     631             :     default:
     632           0 :       FATAL_UNSUPPORTED_OPCODE(opcode);
     633             :   }
     634     1158627 :   return graph()->NewNode(op, left, right);
     635             : }
     636             : 
     637      204372 : Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input,
     638      293508 :                              wasm::WasmCodePosition position) {
     639             :   const Operator* op;
     640      204372 :   MachineOperatorBuilder* m = mcgraph()->machine();
     641      204372 :   switch (opcode) {
     642             :     case wasm::kExprI32Eqz:
     643       88948 :       op = m->Word32Equal();
     644      177899 :       return graph()->NewNode(op, input, mcgraph()->Int32Constant(0));
     645             :     case wasm::kExprF32Abs:
     646          94 :       op = m->Float32Abs();
     647          94 :       break;
     648             :     case wasm::kExprF32Neg: {
     649         265 :       op = m->Float32Neg();
     650         265 :       break;
     651             :     }
     652             :     case wasm::kExprF32Sqrt:
     653         209 :       op = m->Float32Sqrt();
     654         209 :       break;
     655             :     case wasm::kExprF64Abs:
     656         124 :       op = m->Float64Abs();
     657         124 :       break;
     658             :     case wasm::kExprF64Neg: {
     659        1259 :       op = m->Float64Neg();
     660        1259 :       break;
     661             :     }
     662             :     case wasm::kExprF64Sqrt:
     663         308 :       op = m->Float64Sqrt();
     664         308 :       break;
     665             :     case wasm::kExprI32SConvertF32:
     666             :     case wasm::kExprI32UConvertF32:
     667             :     case wasm::kExprI32SConvertF64:
     668             :     case wasm::kExprI32UConvertF64:
     669             :     case wasm::kExprI32SConvertSatF64:
     670             :     case wasm::kExprI32UConvertSatF64:
     671             :     case wasm::kExprI32SConvertSatF32:
     672             :     case wasm::kExprI32UConvertSatF32:
     673         631 :       return BuildIntConvertFloat(input, position, opcode);
     674             :     case wasm::kExprI32AsmjsSConvertF64:
     675         124 :       return BuildI32AsmjsSConvertF64(input);
     676             :     case wasm::kExprI32AsmjsUConvertF64:
     677          15 :       return BuildI32AsmjsUConvertF64(input);
     678             :     case wasm::kExprF32ConvertF64:
     679        4121 :       op = m->TruncateFloat64ToFloat32();
     680        4121 :       break;
     681             :     case wasm::kExprF64SConvertI32:
     682         783 :       op = m->ChangeInt32ToFloat64();
     683         783 :       break;
     684             :     case wasm::kExprF64UConvertI32:
     685         342 :       op = m->ChangeUint32ToFloat64();
     686         342 :       break;
     687             :     case wasm::kExprF32SConvertI32:
     688         325 :       op = m->RoundInt32ToFloat32();
     689         325 :       break;
     690             :     case wasm::kExprF32UConvertI32:
     691         121 :       op = m->RoundUint32ToFloat32();
     692         121 :       break;
     693             :     case wasm::kExprI32AsmjsSConvertF32:
     694          15 :       return BuildI32AsmjsSConvertF32(input);
     695             :     case wasm::kExprI32AsmjsUConvertF32:
     696          15 :       return BuildI32AsmjsUConvertF32(input);
     697             :     case wasm::kExprF64ConvertF32:
     698        6646 :       op = m->ChangeFloat32ToFloat64();
     699        6646 :       break;
     700             :     case wasm::kExprF32ReinterpretI32:
     701         242 :       op = m->BitcastInt32ToFloat32();
     702         242 :       break;
     703             :     case wasm::kExprI32ReinterpretF32:
     704         556 :       op = m->BitcastFloat32ToInt32();
     705         556 :       break;
     706             :     case wasm::kExprI32Clz:
     707         702 :       op = m->Word32Clz();
     708         702 :       break;
     709             :     case wasm::kExprI32Ctz: {
     710         746 :       if (m->Word32Ctz().IsSupported()) {
     711         746 :         op = m->Word32Ctz().op();
     712         746 :         break;
     713           0 :       } else if (m->Word32ReverseBits().IsSupported()) {
     714           0 :         Node* reversed = graph()->NewNode(m->Word32ReverseBits().op(), input);
     715           0 :         Node* result = graph()->NewNode(m->Word32Clz(), reversed);
     716           0 :         return result;
     717             :       } else {
     718           0 :         return BuildI32Ctz(input);
     719             :       }
     720             :     }
     721             :     case wasm::kExprI32Popcnt: {
     722         133 :       if (m->Word32Popcnt().IsSupported()) {
     723         133 :         op = m->Word32Popcnt().op();
     724         133 :         break;
     725             :       } else {
     726           0 :         return BuildI32Popcnt(input);
     727             :       }
     728             :     }
     729             :     case wasm::kExprF32Floor: {
     730          64 :       if (!m->Float32RoundDown().IsSupported()) return BuildF32Floor(input);
     731          64 :       op = m->Float32RoundDown().op();
     732          64 :       break;
     733             :     }
     734             :     case wasm::kExprF32Ceil: {
     735          64 :       if (!m->Float32RoundUp().IsSupported()) return BuildF32Ceil(input);
     736          64 :       op = m->Float32RoundUp().op();
     737          64 :       break;
     738             :     }
     739             :     case wasm::kExprF32Trunc: {
     740         353 :       if (!m->Float32RoundTruncate().IsSupported()) return BuildF32Trunc(input);
     741         353 :       op = m->Float32RoundTruncate().op();
     742         353 :       break;
     743             :     }
     744             :     case wasm::kExprF32NearestInt: {
     745          33 :       if (!m->Float32RoundTiesEven().IsSupported())
     746           0 :         return BuildF32NearestInt(input);
     747          33 :       op = m->Float32RoundTiesEven().op();
     748          33 :       break;
     749             :     }
     750             :     case wasm::kExprF64Floor: {
     751         117 :       if (!m->Float64RoundDown().IsSupported()) return BuildF64Floor(input);
     752         117 :       op = m->Float64RoundDown().op();
     753         117 :       break;
     754             :     }
     755             :     case wasm::kExprF64Ceil: {
     756          82 :       if (!m->Float64RoundUp().IsSupported()) return BuildF64Ceil(input);
     757          82 :       op = m->Float64RoundUp().op();
     758          82 :       break;
     759             :     }
     760             :     case wasm::kExprF64Trunc: {
     761         344 :       if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input);
     762         344 :       op = m->Float64RoundTruncate().op();
     763         344 :       break;
     764             :     }
     765             :     case wasm::kExprF64NearestInt: {
     766          33 :       if (!m->Float64RoundTiesEven().IsSupported())
     767           0 :         return BuildF64NearestInt(input);
     768          33 :       op = m->Float64RoundTiesEven().op();
     769          33 :       break;
     770             :     }
     771             :     case wasm::kExprF64Acos: {
     772          25 :       return BuildF64Acos(input);
     773             :     }
     774             :     case wasm::kExprF64Asin: {
     775          25 :       return BuildF64Asin(input);
     776             :     }
     777             :     case wasm::kExprF64Atan:
     778          25 :       op = m->Float64Atan();
     779          25 :       break;
     780             :     case wasm::kExprF64Cos: {
     781         175 :       op = m->Float64Cos();
     782         175 :       break;
     783             :     }
     784             :     case wasm::kExprF64Sin: {
     785         175 :       op = m->Float64Sin();
     786         175 :       break;
     787             :     }
     788             :     case wasm::kExprF64Tan: {
     789          25 :       op = m->Float64Tan();
     790          25 :       break;
     791             :     }
     792             :     case wasm::kExprF64Exp: {
     793          25 :       op = m->Float64Exp();
     794          25 :       break;
     795             :     }
     796             :     case wasm::kExprF64Log:
     797          25 :       op = m->Float64Log();
     798          25 :       break;
     799             :     case wasm::kExprI32ConvertI64:
     800        1513 :       op = m->TruncateInt64ToInt32();
     801        1513 :       break;
     802             :     case wasm::kExprI64SConvertI32:
     803          61 :       op = m->ChangeInt32ToInt64();
     804          61 :       break;
     805             :     case wasm::kExprI64UConvertI32:
     806       25703 :       op = m->ChangeUint32ToUint64();
     807       25703 :       break;
     808             :     case wasm::kExprF64ReinterpretI64:
     809         197 :       op = m->BitcastInt64ToFloat64();
     810         197 :       break;
     811             :     case wasm::kExprI64ReinterpretF64:
     812         502 :       op = m->BitcastFloat64ToInt64();
     813         502 :       break;
     814             :     case wasm::kExprI64Clz:
     815          47 :       op = m->Word64Clz();
     816          47 :       break;
     817             :     case wasm::kExprI64Ctz: {
     818         218 :       OptionalOperator ctz64 = m->Word64Ctz();
     819         218 :       if (ctz64.IsSupported()) {
     820             :         op = ctz64.op();
     821         218 :         break;
     822           0 :       } else if (m->Is32() && m->Word32Ctz().IsSupported()) {
     823             :         op = ctz64.placeholder();
     824             :         break;
     825           0 :       } else if (m->Word64ReverseBits().IsSupported()) {
     826           0 :         Node* reversed = graph()->NewNode(m->Word64ReverseBits().op(), input);
     827           0 :         Node* result = graph()->NewNode(m->Word64Clz(), reversed);
     828           0 :         return result;
     829             :       } else {
     830           0 :         return BuildI64Ctz(input);
     831             :       }
     832             :     }
     833             :     case wasm::kExprI64Popcnt: {
     834          62 :       OptionalOperator popcnt64 = m->Word64Popcnt();
     835          62 :       if (popcnt64.IsSupported()) {
     836             :         op = popcnt64.op();
     837           0 :       } else if (m->Is32() && m->Word32Popcnt().IsSupported()) {
     838             :         op = popcnt64.placeholder();
     839             :       } else {
     840           0 :         return BuildI64Popcnt(input);
     841             :       }
     842          62 :       break;
     843             :     }
     844             :     case wasm::kExprI64Eqz:
     845         188 :       op = m->Word64Equal();
     846         376 :       return graph()->NewNode(op, input, mcgraph()->Int64Constant(0));
     847             :     case wasm::kExprF32SConvertI64:
     848          78 :       if (m->Is32()) {
     849           0 :         return BuildF32SConvertI64(input);
     850             :       }
     851          78 :       op = m->RoundInt64ToFloat32();
     852          78 :       break;
     853             :     case wasm::kExprF32UConvertI64:
     854          42 :       if (m->Is32()) {
     855           0 :         return BuildF32UConvertI64(input);
     856             :       }
     857          42 :       op = m->RoundUint64ToFloat32();
     858          42 :       break;
     859             :     case wasm::kExprF64SConvertI64:
     860         108 :       if (m->Is32()) {
     861           0 :         return BuildF64SConvertI64(input);
     862             :       }
     863         108 :       op = m->RoundInt64ToFloat64();
     864         108 :       break;
     865             :     case wasm::kExprF64UConvertI64:
     866         158 :       if (m->Is32()) {
     867           0 :         return BuildF64UConvertI64(input);
     868             :       }
     869         158 :       op = m->RoundUint64ToFloat64();
     870         158 :       break;
     871             :     case wasm::kExprI32SExtendI8:
     872          10 :       op = m->SignExtendWord8ToInt32();
     873          10 :       break;
     874             :     case wasm::kExprI32SExtendI16:
     875          10 :       op = m->SignExtendWord16ToInt32();
     876          10 :       break;
     877             :     case wasm::kExprI64SExtendI8:
     878          10 :       op = m->SignExtendWord8ToInt64();
     879          10 :       break;
     880             :     case wasm::kExprI64SExtendI16:
     881          10 :       op = m->SignExtendWord16ToInt64();
     882          10 :       break;
     883             :     case wasm::kExprI64SExtendI32:
     884          10 :       op = m->SignExtendWord32ToInt64();
     885          10 :       break;
     886             :     case wasm::kExprI64SConvertF32:
     887             :     case wasm::kExprI64UConvertF32:
     888             :     case wasm::kExprI64SConvertF64:
     889             :     case wasm::kExprI64UConvertF64:
     890             :     case wasm::kExprI64SConvertSatF32:
     891             :     case wasm::kExprI64UConvertSatF32:
     892             :     case wasm::kExprI64SConvertSatF64:
     893             :     case wasm::kExprI64UConvertSatF64:
     894             :       return mcgraph()->machine()->Is32()
     895             :                  ? BuildCcallConvertFloat(input, position, opcode)
     896         954 :                  : BuildIntConvertFloat(input, position, opcode);
     897             :     case wasm::kExprRefIsNull:
     898          72 :       return graph()->NewNode(m->WordEqual(), input, RefNull());
     899             :     case wasm::kExprI32AsmjsLoadMem8S:
     900        3284 :       return BuildAsmjsLoadMem(MachineType::Int8(), input);
     901             :     case wasm::kExprI32AsmjsLoadMem8U:
     902        2459 :       return BuildAsmjsLoadMem(MachineType::Uint8(), input);
     903             :     case wasm::kExprI32AsmjsLoadMem16S:
     904        1114 :       return BuildAsmjsLoadMem(MachineType::Int16(), input);
     905             :     case wasm::kExprI32AsmjsLoadMem16U:
     906         624 :       return BuildAsmjsLoadMem(MachineType::Uint16(), input);
     907             :     case wasm::kExprI32AsmjsLoadMem:
     908       51261 :       return BuildAsmjsLoadMem(MachineType::Int32(), input);
     909             :     case wasm::kExprF32AsmjsLoadMem:
     910        6482 :       return BuildAsmjsLoadMem(MachineType::Float32(), input);
     911             :     case wasm::kExprF64AsmjsLoadMem:
     912         917 :       return BuildAsmjsLoadMem(MachineType::Float64(), input);
     913             :     default:
     914           0 :       FATAL_UNSUPPORTED_OPCODE(opcode);
     915             :   }
     916       47248 :   return graph()->NewNode(op, input);
     917             : }
     918             : 
     919        4625 : Node* WasmGraphBuilder::Float32Constant(float value) {
     920        4625 :   return mcgraph()->Float32Constant(value);
     921             : }
     922             : 
     923       13428 : Node* WasmGraphBuilder::Float64Constant(double value) {
     924       13428 :   return mcgraph()->Float64Constant(value);
     925             : }
     926             : 
     927             : namespace {
     928      891475 : Node* Branch(MachineGraph* mcgraph, Node* cond, Node** true_node,
     929             :              Node** false_node, Node* control, BranchHint hint) {
     930             :   DCHECK_NOT_NULL(cond);
     931             :   DCHECK_NOT_NULL(control);
     932             :   Node* branch =
     933      148573 :       mcgraph->graph()->NewNode(mcgraph->common()->Branch(hint), cond, control);
     934      297167 :   *true_node = mcgraph->graph()->NewNode(mcgraph->common()->IfTrue(), branch);
     935      297166 :   *false_node = mcgraph->graph()->NewNode(mcgraph->common()->IfFalse(), branch);
     936      148583 :   return branch;
     937             : }
     938             : }  // namespace
     939             : 
     940      111607 : Node* WasmGraphBuilder::BranchNoHint(Node* cond, Node** true_node,
     941      223214 :                                      Node** false_node) {
     942             :   return Branch(mcgraph(), cond, true_node, false_node, Control(),
     943      111607 :                 BranchHint::kNone);
     944             : }
     945             : 
     946           0 : Node* WasmGraphBuilder::BranchExpectTrue(Node* cond, Node** true_node,
     947           0 :                                          Node** false_node) {
     948             :   return Branch(mcgraph(), cond, true_node, false_node, Control(),
     949           0 :                 BranchHint::kTrue);
     950             : }
     951             : 
     952           0 : Node* WasmGraphBuilder::BranchExpectFalse(Node* cond, Node** true_node,
     953       73932 :                                           Node** false_node) {
     954             :   return Branch(mcgraph(), cond, true_node, false_node, Control(),
     955       36966 :                 BranchHint::kFalse);
     956             : }
     957             : 
     958       47854 : TrapId WasmGraphBuilder::GetTrapIdForTrap(wasm::TrapReason reason) {
     959             :   // TODO(wasm): "!env_" should not happen when compiling an actual wasm
     960             :   // function.
     961       47854 :   if (!env_ || !env_->runtime_exception_support) {
     962             :     // We use TrapId::kInvalid as a marker to tell the code generator
     963             :     // to generate a call to a testing c-function instead of a runtime
     964             :     // stub. This code should only be called from a cctest.
     965             :     return TrapId::kInvalid;
     966             :   }
     967             : 
     968       24977 :   switch (reason) {
     969             : #define TRAPREASON_TO_TRAPID(name)                                             \
     970             :   case wasm::k##name:                                                          \
     971             :     static_assert(                                                             \
     972             :         static_cast<int>(TrapId::k##name) == wasm::WasmCode::kThrowWasm##name, \
     973             :         "trap id mismatch");                                                   \
     974             :     return TrapId::k##name;
     975       10659 :     FOREACH_WASM_TRAPREASON(TRAPREASON_TO_TRAPID)
     976             : #undef TRAPREASON_TO_TRAPID
     977             :     default:
     978           0 :       UNREACHABLE();
     979             :   }
     980             : }
     981             : 
     982       11368 : Node* WasmGraphBuilder::TrapIfTrue(wasm::TrapReason reason, Node* cond,
     983       45492 :                                    wasm::WasmCodePosition position) {
     984       11368 :   TrapId trap_id = GetTrapIdForTrap(reason);
     985             :   Node* node = SetControl(graph()->NewNode(mcgraph()->common()->TrapIf(trap_id),
     986       11370 :                                            cond, Effect(), Control()));
     987       11382 :   SetSourcePosition(node, position);
     988       11386 :   return node;
     989             : }
     990             : 
     991       36488 : Node* WasmGraphBuilder::TrapIfFalse(wasm::TrapReason reason, Node* cond,
     992      146042 :                                     wasm::WasmCodePosition position) {
     993       36488 :   TrapId trap_id = GetTrapIdForTrap(reason);
     994             :   Node* node = SetControl(graph()->NewNode(
     995       36503 :       mcgraph()->common()->TrapUnless(trap_id), cond, Effect(), Control()));
     996       36533 :   SetSourcePosition(node, position);
     997       36541 :   return node;
     998             : }
     999             : 
    1000             : // Add a check that traps if {node} is equal to {val}.
    1001      176082 : Node* WasmGraphBuilder::TrapIfEq32(wasm::TrapReason reason, Node* node,
    1002             :                                    int32_t val,
    1003        4486 :                                    wasm::WasmCodePosition position) {
    1004             :   Int32Matcher m(node);
    1005      510150 :   if (m.HasValue() && !m.Is(val)) return graph()->start();
    1006       10521 :   if (val == 0) {
    1007        8278 :     return TrapIfFalse(reason, node, position);
    1008             :   } else {
    1009             :     return TrapIfTrue(reason,
    1010             :                       graph()->NewNode(mcgraph()->machine()->Word32Equal(),
    1011             :                                        node, mcgraph()->Int32Constant(val)),
    1012        6729 :                       position);
    1013             :   }
    1014             : }
    1015             : 
    1016             : // Add a check that traps if {node} is zero.
    1017           0 : Node* WasmGraphBuilder::ZeroCheck32(wasm::TrapReason reason, Node* node,
    1018             :                                     wasm::WasmCodePosition position) {
    1019      140761 :   return TrapIfEq32(reason, node, 0, position);
    1020             : }
    1021             : 
    1022             : // Add a check that traps if {node} is equal to {val}.
    1023        8786 : Node* WasmGraphBuilder::TrapIfEq64(wasm::TrapReason reason, Node* node,
    1024             :                                    int64_t val,
    1025       16938 :                                    wasm::WasmCodePosition position) {
    1026             :   Int64Matcher m(node);
    1027        9454 :   if (m.HasValue() && !m.Is(val)) return graph()->start();
    1028             :   return TrapIfTrue(reason,
    1029             :                     graph()->NewNode(mcgraph()->machine()->Word64Equal(), node,
    1030             :                                      mcgraph()->Int64Constant(val)),
    1031       25415 :                     position);
    1032             : }
    1033             : 
    1034             : // Add a check that traps if {node} is zero.
    1035           0 : Node* WasmGraphBuilder::ZeroCheck64(wasm::TrapReason reason, Node* node,
    1036             :                                     wasm::WasmCodePosition position) {
    1037        7124 :   return TrapIfEq64(reason, node, 0, position);
    1038             : }
    1039             : 
    1040       22434 : Node* WasmGraphBuilder::Switch(unsigned count, Node* key) {
    1041       33651 :   return graph()->NewNode(mcgraph()->common()->Switch(count), key, Control());
    1042             : }
    1043             : 
    1044      254235 : Node* WasmGraphBuilder::IfValue(int32_t value, Node* sw) {
    1045             :   DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
    1046      508471 :   return graph()->NewNode(mcgraph()->common()->IfValue(value), sw);
    1047             : }
    1048             : 
    1049       11216 : Node* WasmGraphBuilder::IfDefault(Node* sw) {
    1050             :   DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
    1051       22433 :   return graph()->NewNode(mcgraph()->common()->IfDefault(), sw);
    1052             : }
    1053             : 
    1054     7820661 : Node* WasmGraphBuilder::Return(unsigned count, Node** vals) {
    1055             :   static const int kStackAllocatedNodeBufferSize = 8;
    1056             :   Node* stack_buffer[kStackAllocatedNodeBufferSize];
    1057             :   std::vector<Node*> heap_buffer;
    1058             : 
    1059             :   Node** buf = stack_buffer;
    1060     1303299 :   if (count + 3 > kStackAllocatedNodeBufferSize) {
    1061           0 :     heap_buffer.resize(count + 3);
    1062             :     buf = heap_buffer.data();
    1063             :   }
    1064             : 
    1065     1303299 :   buf[0] = mcgraph()->Int32Constant(0);
    1066     1303508 :   memcpy(buf + 1, vals, sizeof(void*) * count);
    1067     2607016 :   buf[count + 1] = Effect();
    1068     2607016 :   buf[count + 2] = Control();
    1069             :   Node* ret =
    1070     3910276 :       graph()->NewNode(mcgraph()->common()->Return(count), count + 3, buf);
    1071             : 
    1072     1303539 :   MergeControlToEnd(mcgraph(), ret);
    1073     1303381 :   return ret;
    1074             : }
    1075             : 
    1076        1866 : Node* WasmGraphBuilder::ReturnVoid() { return Return(0, nullptr); }
    1077             : 
    1078        1794 : Node* WasmGraphBuilder::Unreachable(wasm::WasmCodePosition position) {
    1079        1794 :   TrapIfFalse(wasm::TrapReason::kTrapUnreachable, Int32Constant(0), position);
    1080             :   ReturnVoid();
    1081        1794 :   return nullptr;
    1082             : }
    1083             : 
    1084      240193 : Node* WasmGraphBuilder::MaskShiftCount32(Node* node) {
    1085             :   static const int32_t kMask32 = 0x1F;
    1086      480326 :   if (!mcgraph()->machine()->Word32ShiftIsSafe()) {
    1087             :     // Shifts by constants are so common we pattern-match them here.
    1088             :     Int32Matcher match(node);
    1089          30 :     if (match.HasValue()) {
    1090           0 :       int32_t masked = (match.Value() & kMask32);
    1091           0 :       if (match.Value() != masked) node = mcgraph()->Int32Constant(masked);
    1092             :     } else {
    1093             :       node = graph()->NewNode(mcgraph()->machine()->Word32And(), node,
    1094          60 :                               mcgraph()->Int32Constant(kMask32));
    1095             :     }
    1096             :   }
    1097      240163 :   return node;
    1098             : }
    1099             : 
    1100       17763 : Node* WasmGraphBuilder::MaskShiftCount64(Node* node) {
    1101             :   static const int64_t kMask64 = 0x3F;
    1102       35476 :   if (!mcgraph()->machine()->Word32ShiftIsSafe()) {
    1103             :     // Shifts by constants are so common we pattern-match them here.
    1104             :     Int64Matcher match(node);
    1105          25 :     if (match.HasValue()) {
    1106           0 :       int64_t masked = (match.Value() & kMask64);
    1107           0 :       if (match.Value() != masked) node = mcgraph()->Int64Constant(masked);
    1108             :     } else {
    1109             :       node = graph()->NewNode(mcgraph()->machine()->Word64And(), node,
    1110          50 :                               mcgraph()->Int64Constant(kMask64));
    1111             :     }
    1112             :   }
    1113       17738 :   return node;
    1114             : }
    1115             : 
    1116             : static bool ReverseBytesSupported(MachineOperatorBuilder* m,
    1117             :                                   size_t size_in_bytes) {
    1118           0 :   switch (size_in_bytes) {
    1119             :     case 4:
    1120             :     case 16:
    1121             :       return true;
    1122             :     case 8:
    1123             :       return m->Is64();
    1124             :     default:
    1125             :       break;
    1126             :   }
    1127             :   return false;
    1128             : }
    1129             : 
    1130           0 : Node* WasmGraphBuilder::BuildChangeEndiannessStore(
    1131           0 :     Node* node, MachineRepresentation mem_rep, wasm::ValueType wasmtype) {
    1132             :   Node* result;
    1133             :   Node* value = node;
    1134           0 :   MachineOperatorBuilder* m = mcgraph()->machine();
    1135           0 :   int valueSizeInBytes = wasm::ValueTypes::ElementSizeInBytes(wasmtype);
    1136           0 :   int valueSizeInBits = 8 * valueSizeInBytes;
    1137             :   bool isFloat = false;
    1138             : 
    1139           0 :   switch (wasmtype) {
    1140             :     case wasm::kWasmF64:
    1141           0 :       value = graph()->NewNode(m->BitcastFloat64ToInt64(), node);
    1142             :       isFloat = true;
    1143             :       V8_FALLTHROUGH;
    1144             :     case wasm::kWasmI64:
    1145           0 :       result = mcgraph()->Int64Constant(0);
    1146           0 :       break;
    1147             :     case wasm::kWasmF32:
    1148           0 :       value = graph()->NewNode(m->BitcastFloat32ToInt32(), node);
    1149             :       isFloat = true;
    1150             :       V8_FALLTHROUGH;
    1151             :     case wasm::kWasmI32:
    1152           0 :       result = mcgraph()->Int32Constant(0);
    1153           0 :       break;
    1154             :     case wasm::kWasmS128:
    1155             :       DCHECK(ReverseBytesSupported(m, valueSizeInBytes));
    1156             :       break;
    1157             :     default:
    1158           0 :       UNREACHABLE();
    1159             :       break;
    1160             :   }
    1161             : 
    1162           0 :   if (mem_rep == MachineRepresentation::kWord8) {
    1163             :     // No need to change endianness for byte size, return original node
    1164             :     return node;
    1165             :   }
    1166           0 :   if (wasmtype == wasm::kWasmI64 && mem_rep < MachineRepresentation::kWord64) {
    1167             :     // In case we store lower part of WasmI64 expression, we can truncate
    1168             :     // upper 32bits
    1169           0 :     value = graph()->NewNode(m->TruncateInt64ToInt32(), value);
    1170           0 :     valueSizeInBytes = wasm::ValueTypes::ElementSizeInBytes(wasm::kWasmI32);
    1171           0 :     valueSizeInBits = 8 * valueSizeInBytes;
    1172           0 :     if (mem_rep == MachineRepresentation::kWord16) {
    1173             :       value =
    1174           0 :           graph()->NewNode(m->Word32Shl(), value, mcgraph()->Int32Constant(16));
    1175             :     }
    1176           0 :   } else if (wasmtype == wasm::kWasmI32 &&
    1177           0 :              mem_rep == MachineRepresentation::kWord16) {
    1178             :     value =
    1179           0 :         graph()->NewNode(m->Word32Shl(), value, mcgraph()->Int32Constant(16));
    1180             :   }
    1181             : 
    1182             :   int i;
    1183             :   uint32_t shiftCount;
    1184             : 
    1185           0 :   if (ReverseBytesSupported(m, valueSizeInBytes)) {
    1186           0 :     switch (valueSizeInBytes) {
    1187             :       case 4:
    1188           0 :         result = graph()->NewNode(m->Word32ReverseBytes(), value);
    1189           0 :         break;
    1190             :       case 8:
    1191           0 :         result = graph()->NewNode(m->Word64ReverseBytes(), value);
    1192           0 :         break;
    1193             :       case 16: {
    1194             :         Node* byte_reversed_lanes[4];
    1195           0 :         for (int lane = 0; lane < 4; lane++) {
    1196             :           byte_reversed_lanes[lane] = graph()->NewNode(
    1197             :               m->Word32ReverseBytes(),
    1198             :               graph()->NewNode(mcgraph()->machine()->I32x4ExtractLane(lane),
    1199           0 :                                value));
    1200             :         }
    1201             : 
    1202             :         // This is making a copy of the value.
    1203             :         result =
    1204           0 :             graph()->NewNode(mcgraph()->machine()->S128And(), value, value);
    1205             : 
    1206           0 :         for (int lane = 0; lane < 4; lane++) {
    1207             :           result =
    1208             :               graph()->NewNode(mcgraph()->machine()->I32x4ReplaceLane(3 - lane),
    1209           0 :                                result, byte_reversed_lanes[lane]);
    1210             :         }
    1211             : 
    1212             :         break;
    1213             :       }
    1214             :       default:
    1215           0 :         UNREACHABLE();
    1216             :         break;
    1217             :     }
    1218             :   } else {
    1219           0 :     for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2;
    1220             :          i += 8, shiftCount -= 16) {
    1221             :       Node* shiftLower;
    1222             :       Node* shiftHigher;
    1223             :       Node* lowerByte;
    1224             :       Node* higherByte;
    1225             : 
    1226             :       DCHECK_LT(0, shiftCount);
    1227             :       DCHECK_EQ(0, (shiftCount + 8) % 16);
    1228             : 
    1229           0 :       if (valueSizeInBits > 32) {
    1230             :         shiftLower = graph()->NewNode(m->Word64Shl(), value,
    1231           0 :                                       mcgraph()->Int64Constant(shiftCount));
    1232             :         shiftHigher = graph()->NewNode(m->Word64Shr(), value,
    1233           0 :                                        mcgraph()->Int64Constant(shiftCount));
    1234             :         lowerByte = graph()->NewNode(
    1235             :             m->Word64And(), shiftLower,
    1236             :             mcgraph()->Int64Constant(static_cast<uint64_t>(0xFF)
    1237           0 :                                      << (valueSizeInBits - 8 - i)));
    1238             :         higherByte = graph()->NewNode(
    1239             :             m->Word64And(), shiftHigher,
    1240           0 :             mcgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i));
    1241           0 :         result = graph()->NewNode(m->Word64Or(), result, lowerByte);
    1242           0 :         result = graph()->NewNode(m->Word64Or(), result, higherByte);
    1243             :       } else {
    1244             :         shiftLower = graph()->NewNode(m->Word32Shl(), value,
    1245           0 :                                       mcgraph()->Int32Constant(shiftCount));
    1246             :         shiftHigher = graph()->NewNode(m->Word32Shr(), value,
    1247           0 :                                        mcgraph()->Int32Constant(shiftCount));
    1248             :         lowerByte = graph()->NewNode(
    1249             :             m->Word32And(), shiftLower,
    1250             :             mcgraph()->Int32Constant(static_cast<uint32_t>(0xFF)
    1251           0 :                                      << (valueSizeInBits - 8 - i)));
    1252             :         higherByte = graph()->NewNode(
    1253             :             m->Word32And(), shiftHigher,
    1254           0 :             mcgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i));
    1255           0 :         result = graph()->NewNode(m->Word32Or(), result, lowerByte);
    1256           0 :         result = graph()->NewNode(m->Word32Or(), result, higherByte);
    1257             :       }
    1258             :     }
    1259             :   }
    1260             : 
    1261           0 :   if (isFloat) {
    1262           0 :     switch (wasmtype) {
    1263             :       case wasm::kWasmF64:
    1264           0 :         result = graph()->NewNode(m->BitcastInt64ToFloat64(), result);
    1265           0 :         break;
    1266             :       case wasm::kWasmF32:
    1267           0 :         result = graph()->NewNode(m->BitcastInt32ToFloat32(), result);
    1268           0 :         break;
    1269             :       default:
    1270           0 :         UNREACHABLE();
    1271             :         break;
    1272             :     }
    1273             :   }
    1274             : 
    1275           0 :   return result;
    1276             : }
    1277             : 
    1278           0 : Node* WasmGraphBuilder::BuildChangeEndiannessLoad(Node* node,
    1279             :                                                   MachineType memtype,
    1280           0 :                                                   wasm::ValueType wasmtype) {
    1281             :   Node* result;
    1282             :   Node* value = node;
    1283           0 :   MachineOperatorBuilder* m = mcgraph()->machine();
    1284             :   int valueSizeInBytes = ElementSizeInBytes(memtype.representation());
    1285           0 :   int valueSizeInBits = 8 * valueSizeInBytes;
    1286             :   bool isFloat = false;
    1287             : 
    1288           0 :   switch (memtype.representation()) {
    1289             :     case MachineRepresentation::kFloat64:
    1290           0 :       value = graph()->NewNode(m->BitcastFloat64ToInt64(), node);
    1291             :       isFloat = true;
    1292             :       V8_FALLTHROUGH;
    1293             :     case MachineRepresentation::kWord64:
    1294           0 :       result = mcgraph()->Int64Constant(0);
    1295           0 :       break;
    1296             :     case MachineRepresentation::kFloat32:
    1297           0 :       value = graph()->NewNode(m->BitcastFloat32ToInt32(), node);
    1298             :       isFloat = true;
    1299             :       V8_FALLTHROUGH;
    1300             :     case MachineRepresentation::kWord32:
    1301             :     case MachineRepresentation::kWord16:
    1302           0 :       result = mcgraph()->Int32Constant(0);
    1303           0 :       break;
    1304             :     case MachineRepresentation::kWord8:
    1305             :       // No need to change endianness for byte size, return original node
    1306             :       return node;
    1307             :       break;
    1308             :     case MachineRepresentation::kSimd128:
    1309             :       DCHECK(ReverseBytesSupported(m, valueSizeInBytes));
    1310             :       break;
    1311             :     default:
    1312           0 :       UNREACHABLE();
    1313             :       break;
    1314             :   }
    1315             : 
    1316             :   int i;
    1317             :   uint32_t shiftCount;
    1318             : 
    1319           0 :   if (ReverseBytesSupported(m, valueSizeInBytes < 4 ? 4 : valueSizeInBytes)) {
    1320           0 :     switch (valueSizeInBytes) {
    1321             :       case 2:
    1322             :         result =
    1323             :             graph()->NewNode(m->Word32ReverseBytes(),
    1324             :                              graph()->NewNode(m->Word32Shl(), value,
    1325           0 :                                               mcgraph()->Int32Constant(16)));
    1326           0 :         break;
    1327             :       case 4:
    1328           0 :         result = graph()->NewNode(m->Word32ReverseBytes(), value);
    1329           0 :         break;
    1330             :       case 8:
    1331           0 :         result = graph()->NewNode(m->Word64ReverseBytes(), value);
    1332           0 :         break;
    1333             :       case 16: {
    1334             :         Node* byte_reversed_lanes[4];
    1335           0 :         for (int lane = 0; lane < 4; lane++) {
    1336             :           byte_reversed_lanes[lane] = graph()->NewNode(
    1337             :               m->Word32ReverseBytes(),
    1338             :               graph()->NewNode(mcgraph()->machine()->I32x4ExtractLane(lane),
    1339           0 :                                value));
    1340             :         }
    1341             : 
    1342             :         // This is making a copy of the value.
    1343             :         result =
    1344           0 :             graph()->NewNode(mcgraph()->machine()->S128And(), value, value);
    1345             : 
    1346           0 :         for (int lane = 0; lane < 4; lane++) {
    1347             :           result =
    1348             :               graph()->NewNode(mcgraph()->machine()->I32x4ReplaceLane(3 - lane),
    1349           0 :                                result, byte_reversed_lanes[lane]);
    1350             :         }
    1351             : 
    1352             :         break;
    1353             :       }
    1354             :       default:
    1355           0 :         UNREACHABLE();
    1356             :     }
    1357             :   } else {
    1358           0 :     for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2;
    1359             :          i += 8, shiftCount -= 16) {
    1360             :       Node* shiftLower;
    1361             :       Node* shiftHigher;
    1362             :       Node* lowerByte;
    1363             :       Node* higherByte;
    1364             : 
    1365             :       DCHECK_LT(0, shiftCount);
    1366             :       DCHECK_EQ(0, (shiftCount + 8) % 16);
    1367             : 
    1368           0 :       if (valueSizeInBits > 32) {
    1369             :         shiftLower = graph()->NewNode(m->Word64Shl(), value,
    1370           0 :                                       mcgraph()->Int64Constant(shiftCount));
    1371             :         shiftHigher = graph()->NewNode(m->Word64Shr(), value,
    1372           0 :                                        mcgraph()->Int64Constant(shiftCount));
    1373             :         lowerByte = graph()->NewNode(
    1374             :             m->Word64And(), shiftLower,
    1375             :             mcgraph()->Int64Constant(static_cast<uint64_t>(0xFF)
    1376           0 :                                      << (valueSizeInBits - 8 - i)));
    1377             :         higherByte = graph()->NewNode(
    1378             :             m->Word64And(), shiftHigher,
    1379           0 :             mcgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i));
    1380           0 :         result = graph()->NewNode(m->Word64Or(), result, lowerByte);
    1381           0 :         result = graph()->NewNode(m->Word64Or(), result, higherByte);
    1382             :       } else {
    1383             :         shiftLower = graph()->NewNode(m->Word32Shl(), value,
    1384           0 :                                       mcgraph()->Int32Constant(shiftCount));
    1385             :         shiftHigher = graph()->NewNode(m->Word32Shr(), value,
    1386           0 :                                        mcgraph()->Int32Constant(shiftCount));
    1387             :         lowerByte = graph()->NewNode(
    1388             :             m->Word32And(), shiftLower,
    1389             :             mcgraph()->Int32Constant(static_cast<uint32_t>(0xFF)
    1390           0 :                                      << (valueSizeInBits - 8 - i)));
    1391             :         higherByte = graph()->NewNode(
    1392             :             m->Word32And(), shiftHigher,
    1393           0 :             mcgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i));
    1394           0 :         result = graph()->NewNode(m->Word32Or(), result, lowerByte);
    1395           0 :         result = graph()->NewNode(m->Word32Or(), result, higherByte);
    1396             :       }
    1397             :     }
    1398             :   }
    1399             : 
    1400           0 :   if (isFloat) {
    1401           0 :     switch (memtype.representation()) {
    1402             :       case MachineRepresentation::kFloat64:
    1403           0 :         result = graph()->NewNode(m->BitcastInt64ToFloat64(), result);
    1404           0 :         break;
    1405             :       case MachineRepresentation::kFloat32:
    1406           0 :         result = graph()->NewNode(m->BitcastInt32ToFloat32(), result);
    1407           0 :         break;
    1408             :       default:
    1409           0 :         UNREACHABLE();
    1410             :         break;
    1411             :     }
    1412             :   }
    1413             : 
    1414             :   // We need to sign extend the value
    1415           0 :   if (memtype.IsSigned()) {
    1416             :     DCHECK(!isFloat);
    1417           0 :     if (valueSizeInBits < 32) {
    1418             :       Node* shiftBitCount;
    1419             :       // Perform sign extension using following trick
    1420             :       // result = (x << machine_width - type_width) >> (machine_width -
    1421             :       // type_width)
    1422           0 :       if (wasmtype == wasm::kWasmI64) {
    1423           0 :         shiftBitCount = mcgraph()->Int32Constant(64 - valueSizeInBits);
    1424             :         result = graph()->NewNode(
    1425             :             m->Word64Sar(),
    1426             :             graph()->NewNode(m->Word64Shl(),
    1427             :                              graph()->NewNode(m->ChangeInt32ToInt64(), result),
    1428             :                              shiftBitCount),
    1429           0 :             shiftBitCount);
    1430           0 :       } else if (wasmtype == wasm::kWasmI32) {
    1431           0 :         shiftBitCount = mcgraph()->Int32Constant(32 - valueSizeInBits);
    1432             :         result = graph()->NewNode(
    1433             :             m->Word32Sar(),
    1434             :             graph()->NewNode(m->Word32Shl(), result, shiftBitCount),
    1435           0 :             shiftBitCount);
    1436             :       }
    1437             :     }
    1438             :   }
    1439             : 
    1440           0 :   return result;
    1441             : }
    1442             : 
    1443          94 : Node* WasmGraphBuilder::BuildF32CopySign(Node* left, Node* right) {
    1444             :   Node* result = Unop(
    1445             :       wasm::kExprF32ReinterpretI32,
    1446             :       Binop(wasm::kExprI32Ior,
    1447             :             Binop(wasm::kExprI32And, Unop(wasm::kExprI32ReinterpretF32, left),
    1448             :                   mcgraph()->Int32Constant(0x7FFFFFFF)),
    1449             :             Binop(wasm::kExprI32And, Unop(wasm::kExprI32ReinterpretF32, right),
    1450          94 :                   mcgraph()->Int32Constant(0x80000000))));
    1451             : 
    1452          47 :   return result;
    1453             : }
    1454             : 
    1455          94 : Node* WasmGraphBuilder::BuildF64CopySign(Node* left, Node* right) {
    1456             : #if WASM_64
    1457             :   Node* result = Unop(
    1458             :       wasm::kExprF64ReinterpretI64,
    1459             :       Binop(wasm::kExprI64Ior,
    1460             :             Binop(wasm::kExprI64And, Unop(wasm::kExprI64ReinterpretF64, left),
    1461             :                   mcgraph()->Int64Constant(0x7FFFFFFFFFFFFFFF)),
    1462             :             Binop(wasm::kExprI64And, Unop(wasm::kExprI64ReinterpretF64, right),
    1463          94 :                   mcgraph()->Int64Constant(0x8000000000000000))));
    1464             : 
    1465          47 :   return result;
    1466             : #else
    1467             :   MachineOperatorBuilder* m = mcgraph()->machine();
    1468             : 
    1469             :   Node* high_word_left = graph()->NewNode(m->Float64ExtractHighWord32(), left);
    1470             :   Node* high_word_right =
    1471             :       graph()->NewNode(m->Float64ExtractHighWord32(), right);
    1472             : 
    1473             :   Node* new_high_word = Binop(wasm::kExprI32Ior,
    1474             :                               Binop(wasm::kExprI32And, high_word_left,
    1475             :                                     mcgraph()->Int32Constant(0x7FFFFFFF)),
    1476             :                               Binop(wasm::kExprI32And, high_word_right,
    1477             :                                     mcgraph()->Int32Constant(0x80000000)));
    1478             : 
    1479             :   return graph()->NewNode(m->Float64InsertHighWord32(), left, new_high_word);
    1480             : #endif
    1481             : }
    1482             : 
    1483             : namespace {
    1484             : 
    1485        1587 : MachineType IntConvertType(wasm::WasmOpcode opcode) {
    1486        1587 :   switch (opcode) {
    1487             :     case wasm::kExprI32SConvertF32:
    1488             :     case wasm::kExprI32SConvertF64:
    1489             :     case wasm::kExprI32SConvertSatF32:
    1490             :     case wasm::kExprI32SConvertSatF64:
    1491             :       return MachineType::Int32();
    1492             :     case wasm::kExprI32UConvertF32:
    1493             :     case wasm::kExprI32UConvertF64:
    1494             :     case wasm::kExprI32UConvertSatF32:
    1495             :     case wasm::kExprI32UConvertSatF64:
    1496             :       return MachineType::Uint32();
    1497             :     case wasm::kExprI64SConvertF32:
    1498             :     case wasm::kExprI64SConvertF64:
    1499             :     case wasm::kExprI64SConvertSatF32:
    1500             :     case wasm::kExprI64SConvertSatF64:
    1501             :       return MachineType::Int64();
    1502             :     case wasm::kExprI64UConvertF32:
    1503             :     case wasm::kExprI64UConvertF64:
    1504             :     case wasm::kExprI64UConvertSatF32:
    1505             :     case wasm::kExprI64UConvertSatF64:
    1506             :       return MachineType::Uint64();
    1507             :     default:
    1508           0 :       UNREACHABLE();
    1509             :   }
    1510             : }
    1511             : 
    1512        1587 : MachineType FloatConvertType(wasm::WasmOpcode opcode) {
    1513        1587 :   switch (opcode) {
    1514             :     case wasm::kExprI32SConvertF32:
    1515             :     case wasm::kExprI32UConvertF32:
    1516             :     case wasm::kExprI32SConvertSatF32:
    1517             :     case wasm::kExprI64SConvertF32:
    1518             :     case wasm::kExprI64UConvertF32:
    1519             :     case wasm::kExprI32UConvertSatF32:
    1520             :     case wasm::kExprI64SConvertSatF32:
    1521             :     case wasm::kExprI64UConvertSatF32:
    1522             :       return MachineType::Float32();
    1523             :     case wasm::kExprI32SConvertF64:
    1524             :     case wasm::kExprI32UConvertF64:
    1525             :     case wasm::kExprI64SConvertF64:
    1526             :     case wasm::kExprI64UConvertF64:
    1527             :     case wasm::kExprI32SConvertSatF64:
    1528             :     case wasm::kExprI32UConvertSatF64:
    1529             :     case wasm::kExprI64SConvertSatF64:
    1530             :     case wasm::kExprI64UConvertSatF64:
    1531             :       return MachineType::Float64();
    1532             :     default:
    1533           0 :       UNREACHABLE();
    1534             :   }
    1535             : }
    1536             : 
    1537        3174 : const Operator* ConvertOp(WasmGraphBuilder* builder, wasm::WasmOpcode opcode) {
    1538        1587 :   switch (opcode) {
    1539             :     case wasm::kExprI32SConvertF32:
    1540             :     case wasm::kExprI32SConvertSatF32:
    1541         245 :       return builder->mcgraph()->machine()->TruncateFloat32ToInt32();
    1542             :     case wasm::kExprI32UConvertF32:
    1543             :     case wasm::kExprI32UConvertSatF32:
    1544          75 :       return builder->mcgraph()->machine()->TruncateFloat32ToUint32();
    1545             :     case wasm::kExprI32SConvertF64:
    1546             :     case wasm::kExprI32SConvertSatF64:
    1547         245 :       return builder->mcgraph()->machine()->ChangeFloat64ToInt32();
    1548             :     case wasm::kExprI32UConvertF64:
    1549             :     case wasm::kExprI32UConvertSatF64:
    1550          66 :       return builder->mcgraph()->machine()->TruncateFloat64ToUint32();
    1551             :     case wasm::kExprI64SConvertF32:
    1552             :     case wasm::kExprI64SConvertSatF32:
    1553          66 :       return builder->mcgraph()->machine()->TryTruncateFloat32ToInt64();
    1554             :     case wasm::kExprI64UConvertF32:
    1555             :     case wasm::kExprI64UConvertSatF32:
    1556          66 :       return builder->mcgraph()->machine()->TryTruncateFloat32ToUint64();
    1557             :     case wasm::kExprI64SConvertF64:
    1558             :     case wasm::kExprI64SConvertSatF64:
    1559         749 :       return builder->mcgraph()->machine()->TryTruncateFloat64ToInt64();
    1560             :     case wasm::kExprI64UConvertF64:
    1561             :     case wasm::kExprI64UConvertSatF64:
    1562          75 :       return builder->mcgraph()->machine()->TryTruncateFloat64ToUint64();
    1563             :     default:
    1564           0 :       UNREACHABLE();
    1565             :   }
    1566             : }
    1567             : 
    1568         631 : wasm::WasmOpcode ConvertBackOp(wasm::WasmOpcode opcode) {
    1569         631 :   switch (opcode) {
    1570             :     case wasm::kExprI32SConvertF32:
    1571             :     case wasm::kExprI32SConvertSatF32:
    1572             :       return wasm::kExprF32SConvertI32;
    1573             :     case wasm::kExprI32UConvertF32:
    1574             :     case wasm::kExprI32UConvertSatF32:
    1575          75 :       return wasm::kExprF32UConvertI32;
    1576             :     case wasm::kExprI32SConvertF64:
    1577             :     case wasm::kExprI32SConvertSatF64:
    1578         245 :       return wasm::kExprF64SConvertI32;
    1579             :     case wasm::kExprI32UConvertF64:
    1580             :     case wasm::kExprI32UConvertSatF64:
    1581          66 :       return wasm::kExprF64UConvertI32;
    1582             :     default:
    1583           0 :       UNREACHABLE();
    1584             :   }
    1585             : }
    1586             : 
    1587        1584 : bool IsTrappingConvertOp(wasm::WasmOpcode opcode) {
    1588        1584 :   switch (opcode) {
    1589             :     case wasm::kExprI32SConvertF32:
    1590             :     case wasm::kExprI32UConvertF32:
    1591             :     case wasm::kExprI32SConvertF64:
    1592             :     case wasm::kExprI32UConvertF64:
    1593             :     case wasm::kExprI64SConvertF32:
    1594             :     case wasm::kExprI64UConvertF32:
    1595             :     case wasm::kExprI64SConvertF64:
    1596             :     case wasm::kExprI64UConvertF64:
    1597             :       return true;
    1598             :     case wasm::kExprI32SConvertSatF64:
    1599             :     case wasm::kExprI32UConvertSatF64:
    1600             :     case wasm::kExprI32SConvertSatF32:
    1601             :     case wasm::kExprI32UConvertSatF32:
    1602             :     case wasm::kExprI64SConvertSatF32:
    1603             :     case wasm::kExprI64UConvertSatF32:
    1604             :     case wasm::kExprI64SConvertSatF64:
    1605             :     case wasm::kExprI64UConvertSatF64:
    1606         120 :       return false;
    1607             :     default:
    1608           0 :       UNREACHABLE();
    1609             :   }
    1610             : }
    1611             : 
    1612         240 : Node* Zero(WasmGraphBuilder* builder, const MachineType& ty) {
    1613         240 :   switch (ty.representation()) {
    1614             :     case MachineRepresentation::kWord32:
    1615          60 :       return builder->Int32Constant(0);
    1616             :     case MachineRepresentation::kWord64:
    1617          60 :       return builder->Int64Constant(0);
    1618             :     case MachineRepresentation::kFloat32:
    1619          60 :       return builder->Float32Constant(0.0);
    1620             :     case MachineRepresentation::kFloat64:
    1621          60 :       return builder->Float64Constant(0.0);
    1622             :     default:
    1623           0 :       UNREACHABLE();
    1624             :   }
    1625             : }
    1626             : 
    1627         120 : Node* Min(WasmGraphBuilder* builder, const MachineType& ty) {
    1628         120 :   switch (ty.semantic()) {
    1629             :     case MachineSemantic::kInt32:
    1630          30 :       return builder->Int32Constant(std::numeric_limits<int32_t>::min());
    1631             :     case MachineSemantic::kUint32:
    1632          30 :       return builder->Int32Constant(std::numeric_limits<uint32_t>::min());
    1633             :     case MachineSemantic::kInt64:
    1634          30 :       return builder->Int64Constant(std::numeric_limits<int64_t>::min());
    1635             :     case MachineSemantic::kUint64:
    1636          30 :       return builder->Int64Constant(std::numeric_limits<uint64_t>::min());
    1637             :     default:
    1638           0 :       UNREACHABLE();
    1639             :   }
    1640             : }
    1641             : 
    1642         120 : Node* Max(WasmGraphBuilder* builder, const MachineType& ty) {
    1643         120 :   switch (ty.semantic()) {
    1644             :     case MachineSemantic::kInt32:
    1645          30 :       return builder->Int32Constant(std::numeric_limits<int32_t>::max());
    1646             :     case MachineSemantic::kUint32:
    1647          30 :       return builder->Int32Constant(std::numeric_limits<uint32_t>::max());
    1648             :     case MachineSemantic::kInt64:
    1649          30 :       return builder->Int64Constant(std::numeric_limits<int64_t>::max());
    1650             :     case MachineSemantic::kUint64:
    1651          30 :       return builder->Int64Constant(std::numeric_limits<uint64_t>::max());
    1652             :     default:
    1653           0 :       UNREACHABLE();
    1654             :   }
    1655             : }
    1656             : 
    1657         631 : wasm::WasmOpcode TruncOp(const MachineType& ty) {
    1658         631 :   switch (ty.representation()) {
    1659             :     case MachineRepresentation::kFloat32:
    1660             :       return wasm::kExprF32Trunc;
    1661             :     case MachineRepresentation::kFloat64:
    1662         311 :       return wasm::kExprF64Trunc;
    1663             :     default:
    1664           0 :       UNREACHABLE();
    1665             :   }
    1666             : }
    1667             : 
    1668         751 : wasm::WasmOpcode NeOp(const MachineType& ty) {
    1669         751 :   switch (ty.representation()) {
    1670             :     case MachineRepresentation::kFloat32:
    1671             :       return wasm::kExprF32Ne;
    1672             :     case MachineRepresentation::kFloat64:
    1673         371 :       return wasm::kExprF64Ne;
    1674             :     default:
    1675           0 :       UNREACHABLE();
    1676             :   }
    1677             : }
    1678             : 
    1679         120 : wasm::WasmOpcode LtOp(const MachineType& ty) {
    1680         120 :   switch (ty.representation()) {
    1681             :     case MachineRepresentation::kFloat32:
    1682             :       return wasm::kExprF32Lt;
    1683             :     case MachineRepresentation::kFloat64:
    1684          60 :       return wasm::kExprF64Lt;
    1685             :     default:
    1686           0 :       UNREACHABLE();
    1687             :   }
    1688             : }
    1689             : 
    1690        1587 : Node* ConvertTrapTest(WasmGraphBuilder* builder, wasm::WasmOpcode opcode,
    1691        1587 :                       const MachineType& int_ty, const MachineType& float_ty,
    1692             :                       Node* trunc, Node* converted_value) {
    1693        1587 :   if (int_ty.representation() == MachineRepresentation::kWord32) {
    1694         631 :     Node* check = builder->Unop(ConvertBackOp(opcode), converted_value);
    1695         631 :     return builder->Binop(NeOp(float_ty), trunc, check);
    1696             :   }
    1697             :   return builder->graph()->NewNode(builder->mcgraph()->common()->Projection(1),
    1698        1919 :                                    trunc, builder->graph()->start());
    1699             : }
    1700             : 
    1701         120 : Node* ConvertSaturateTest(WasmGraphBuilder* builder, wasm::WasmOpcode opcode,
    1702         120 :                           const MachineType& int_ty,
    1703             :                           const MachineType& float_ty, Node* trunc,
    1704             :                           Node* converted_value) {
    1705             :   Node* test = ConvertTrapTest(builder, opcode, int_ty, float_ty, trunc,
    1706         120 :                                converted_value);
    1707         120 :   if (int_ty.representation() == MachineRepresentation::kWord64) {
    1708          60 :     test = builder->Binop(wasm::kExprI64Eq, test, builder->Int64Constant(0));
    1709             :   }
    1710         120 :   return test;
    1711             : }
    1712             : 
    1713             : }  // namespace
    1714             : 
    1715        1584 : Node* WasmGraphBuilder::BuildIntConvertFloat(Node* input,
    1716             :                                              wasm::WasmCodePosition position,
    1717         480 :                                              wasm::WasmOpcode opcode) {
    1718        1584 :   const MachineType int_ty = IntConvertType(opcode);
    1719        1587 :   const MachineType float_ty = FloatConvertType(opcode);
    1720        1587 :   const Operator* conv_op = ConvertOp(this, opcode);
    1721             :   Node* trunc = nullptr;
    1722             :   Node* converted_value = nullptr;
    1723             :   const bool is_int32 =
    1724        1586 :       int_ty.representation() == MachineRepresentation::kWord32;
    1725        1586 :   if (is_int32) {
    1726         631 :     trunc = Unop(TruncOp(float_ty), input);
    1727             :     converted_value = graph()->NewNode(conv_op, trunc);
    1728             :   } else {
    1729             :     trunc = graph()->NewNode(conv_op, input);
    1730             :     converted_value = graph()->NewNode(mcgraph()->common()->Projection(0),
    1731         958 :                                        trunc, graph()->start());
    1732             :   }
    1733        1593 :   if (IsTrappingConvertOp(opcode)) {
    1734             :     Node* test =
    1735        1470 :         ConvertTrapTest(this, opcode, int_ty, float_ty, trunc, converted_value);
    1736        1463 :     if (is_int32) {
    1737         571 :       TrapIfTrue(wasm::kTrapFloatUnrepresentable, test, position);
    1738             :     } else {
    1739             :       ZeroCheck64(wasm::kTrapFloatUnrepresentable, test, position);
    1740             :     }
    1741        1478 :     return converted_value;
    1742             :   }
    1743             :   Node* test = ConvertSaturateTest(this, opcode, int_ty, float_ty, trunc,
    1744         120 :                                    converted_value);
    1745         240 :   Diamond tl_d(graph(), mcgraph()->common(), test, BranchHint::kFalse);
    1746         120 :   tl_d.Chain(Control());
    1747         120 :   Node* nan_test = Binop(NeOp(float_ty), input, input);
    1748         240 :   Diamond nan_d(graph(), mcgraph()->common(), nan_test, BranchHint::kFalse);
    1749         120 :   nan_d.Nest(tl_d, true);
    1750         120 :   Node* neg_test = Binop(LtOp(float_ty), input, Zero(this, float_ty));
    1751         240 :   Diamond sat_d(graph(), mcgraph()->common(), neg_test, BranchHint::kNone);
    1752         120 :   sat_d.Nest(nan_d, false);
    1753             :   Node* sat_val =
    1754         120 :       sat_d.Phi(int_ty.representation(), Min(this, int_ty), Max(this, int_ty));
    1755             :   Node* nan_val =
    1756         120 :       nan_d.Phi(int_ty.representation(), Zero(this, int_ty), sat_val);
    1757         120 :   return tl_d.Phi(int_ty.representation(), nan_val, converted_value);
    1758             : }
    1759             : 
    1760          15 : Node* WasmGraphBuilder::BuildI32AsmjsSConvertF32(Node* input) {
    1761          15 :   MachineOperatorBuilder* m = mcgraph()->machine();
    1762             :   // asm.js must use the wacky JS semantics.
    1763          15 :   input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
    1764          30 :   return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
    1765             : }
    1766             : 
    1767         124 : Node* WasmGraphBuilder::BuildI32AsmjsSConvertF64(Node* input) {
    1768         124 :   MachineOperatorBuilder* m = mcgraph()->machine();
    1769             :   // asm.js must use the wacky JS semantics.
    1770         248 :   return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
    1771             : }
    1772             : 
    1773          15 : Node* WasmGraphBuilder::BuildI32AsmjsUConvertF32(Node* input) {
    1774          15 :   MachineOperatorBuilder* m = mcgraph()->machine();
    1775             :   // asm.js must use the wacky JS semantics.
    1776          15 :   input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
    1777          30 :   return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
    1778             : }
    1779             : 
    1780          15 : Node* WasmGraphBuilder::BuildI32AsmjsUConvertF64(Node* input) {
    1781          15 :   MachineOperatorBuilder* m = mcgraph()->machine();
    1782             :   // asm.js must use the wacky JS semantics.
    1783          30 :   return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
    1784             : }
    1785             : 
    1786           0 : Node* WasmGraphBuilder::BuildBitCountingCall(Node* input, ExternalReference ref,
    1787           0 :                                              MachineRepresentation input_type) {
    1788             :   Node* stack_slot_param =
    1789           0 :       graph()->NewNode(mcgraph()->machine()->StackSlot(input_type));
    1790             : 
    1791             :   const Operator* store_op = mcgraph()->machine()->Store(
    1792           0 :       StoreRepresentation(input_type, kNoWriteBarrier));
    1793             :   SetEffect(graph()->NewNode(store_op, stack_slot_param,
    1794             :                              mcgraph()->Int32Constant(0), input, Effect(),
    1795           0 :                              Control()));
    1796             : 
    1797           0 :   MachineType sig_types[] = {MachineType::Int32(), MachineType::Pointer()};
    1798             :   MachineSignature sig(1, 1, sig_types);
    1799             : 
    1800           0 :   Node* function = graph()->NewNode(mcgraph()->common()->ExternalConstant(ref));
    1801             : 
    1802           0 :   return BuildCCall(&sig, function, stack_slot_param);
    1803             : }
    1804             : 
    1805           0 : Node* WasmGraphBuilder::BuildI32Ctz(Node* input) {
    1806             :   return BuildBitCountingCall(input, ExternalReference::wasm_word32_ctz(),
    1807           0 :                               MachineRepresentation::kWord32);
    1808             : }
    1809             : 
    1810           0 : Node* WasmGraphBuilder::BuildI64Ctz(Node* input) {
    1811             :   return Unop(wasm::kExprI64UConvertI32,
    1812             :               BuildBitCountingCall(input, ExternalReference::wasm_word64_ctz(),
    1813           0 :                                    MachineRepresentation::kWord64));
    1814             : }
    1815             : 
    1816           0 : Node* WasmGraphBuilder::BuildI32Popcnt(Node* input) {
    1817             :   return BuildBitCountingCall(input, ExternalReference::wasm_word32_popcnt(),
    1818           0 :                               MachineRepresentation::kWord32);
    1819             : }
    1820             : 
    1821           0 : Node* WasmGraphBuilder::BuildI64Popcnt(Node* input) {
    1822             :   return Unop(
    1823             :       wasm::kExprI64UConvertI32,
    1824             :       BuildBitCountingCall(input, ExternalReference::wasm_word64_popcnt(),
    1825           0 :                            MachineRepresentation::kWord64));
    1826             : }
    1827             : 
    1828           0 : Node* WasmGraphBuilder::BuildF32Trunc(Node* input) {
    1829           0 :   MachineType type = MachineType::Float32();
    1830           0 :   ExternalReference ref = ExternalReference::wasm_f32_trunc();
    1831             : 
    1832           0 :   return BuildCFuncInstruction(ref, type, input);
    1833             : }
    1834             : 
    1835           0 : Node* WasmGraphBuilder::BuildF32Floor(Node* input) {
    1836           0 :   MachineType type = MachineType::Float32();
    1837           0 :   ExternalReference ref = ExternalReference::wasm_f32_floor();
    1838           0 :   return BuildCFuncInstruction(ref, type, input);
    1839             : }
    1840             : 
    1841           0 : Node* WasmGraphBuilder::BuildF32Ceil(Node* input) {
    1842           0 :   MachineType type = MachineType::Float32();
    1843           0 :   ExternalReference ref = ExternalReference::wasm_f32_ceil();
    1844           0 :   return BuildCFuncInstruction(ref, type, input);
    1845             : }
    1846             : 
    1847           0 : Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) {
    1848           0 :   MachineType type = MachineType::Float32();
    1849           0 :   ExternalReference ref = ExternalReference::wasm_f32_nearest_int();
    1850           0 :   return BuildCFuncInstruction(ref, type, input);
    1851             : }
    1852             : 
    1853           0 : Node* WasmGraphBuilder::BuildF64Trunc(Node* input) {
    1854           0 :   MachineType type = MachineType::Float64();
    1855           0 :   ExternalReference ref = ExternalReference::wasm_f64_trunc();
    1856           0 :   return BuildCFuncInstruction(ref, type, input);
    1857             : }
    1858             : 
    1859           0 : Node* WasmGraphBuilder::BuildF64Floor(Node* input) {
    1860           0 :   MachineType type = MachineType::Float64();
    1861           0 :   ExternalReference ref = ExternalReference::wasm_f64_floor();
    1862           0 :   return BuildCFuncInstruction(ref, type, input);
    1863             : }
    1864             : 
    1865           0 : Node* WasmGraphBuilder::BuildF64Ceil(Node* input) {
    1866           0 :   MachineType type = MachineType::Float64();
    1867           0 :   ExternalReference ref = ExternalReference::wasm_f64_ceil();
    1868           0 :   return BuildCFuncInstruction(ref, type, input);
    1869             : }
    1870             : 
    1871           0 : Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) {
    1872           0 :   MachineType type = MachineType::Float64();
    1873           0 :   ExternalReference ref = ExternalReference::wasm_f64_nearest_int();
    1874           0 :   return BuildCFuncInstruction(ref, type, input);
    1875             : }
    1876             : 
    1877          25 : Node* WasmGraphBuilder::BuildF64Acos(Node* input) {
    1878          25 :   MachineType type = MachineType::Float64();
    1879          25 :   ExternalReference ref = ExternalReference::f64_acos_wrapper_function();
    1880          25 :   return BuildCFuncInstruction(ref, type, input);
    1881             : }
    1882             : 
    1883          25 : Node* WasmGraphBuilder::BuildF64Asin(Node* input) {
    1884          25 :   MachineType type = MachineType::Float64();
    1885          25 :   ExternalReference ref = ExternalReference::f64_asin_wrapper_function();
    1886          25 :   return BuildCFuncInstruction(ref, type, input);
    1887             : }
    1888             : 
    1889          11 : Node* WasmGraphBuilder::BuildF64Pow(Node* left, Node* right) {
    1890          11 :   MachineType type = MachineType::Float64();
    1891          11 :   ExternalReference ref = ExternalReference::wasm_float64_pow();
    1892          11 :   return BuildCFuncInstruction(ref, type, left, right);
    1893             : }
    1894             : 
    1895          25 : Node* WasmGraphBuilder::BuildF64Mod(Node* left, Node* right) {
    1896          25 :   MachineType type = MachineType::Float64();
    1897          25 :   ExternalReference ref = ExternalReference::f64_mod_wrapper_function();
    1898          25 :   return BuildCFuncInstruction(ref, type, left, right);
    1899             : }
    1900             : 
    1901          86 : Node* WasmGraphBuilder::BuildCFuncInstruction(ExternalReference ref,
    1902             :                                               MachineType type, Node* input0,
    1903        1176 :                                               Node* input1) {
    1904             :   // We do truncation by calling a C function which calculates the result.
    1905             :   // The input is passed to the C function as a byte buffer holding the two
    1906             :   // input doubles. We reserve this byte buffer as a stack slot, store the
    1907             :   // parameters in this buffer slots, pass a pointer to the buffer to the C
    1908             :   // function, and after calling the C function we collect the return value from
    1909             :   // the buffer.
    1910             : 
    1911             :   const int type_size = ElementSizeInBytes(type.representation());
    1912          86 :   const int stack_slot_bytes = (input1 == nullptr ? 1 : 2) * type_size;
    1913             :   Node* stack_slot =
    1914          86 :       graph()->NewNode(mcgraph()->machine()->StackSlot(stack_slot_bytes));
    1915             : 
    1916             :   const Operator* store_op = mcgraph()->machine()->Store(
    1917          86 :       StoreRepresentation(type.representation(), kNoWriteBarrier));
    1918             :   SetEffect(graph()->NewNode(store_op, stack_slot, mcgraph()->Int32Constant(0),
    1919          86 :                              input0, Effect(), Control()));
    1920             : 
    1921          86 :   Node* function = graph()->NewNode(mcgraph()->common()->ExternalConstant(ref));
    1922             : 
    1923          86 :   if (input1 != nullptr) {
    1924             :     SetEffect(graph()->NewNode(store_op, stack_slot,
    1925             :                                mcgraph()->Int32Constant(type_size), input1,
    1926          36 :                                Effect(), Control()));
    1927             :   }
    1928             : 
    1929          86 :   MachineType sig_types[] = {MachineType::Pointer()};
    1930             :   MachineSignature sig(0, 1, sig_types);
    1931          86 :   BuildCCall(&sig, function, stack_slot);
    1932             : 
    1933             :   return SetEffect(graph()->NewNode(mcgraph()->machine()->Load(type),
    1934             :                                     stack_slot, mcgraph()->Int32Constant(0),
    1935         258 :                                     Effect(), Control()));
    1936             : }
    1937             : 
    1938           0 : Node* WasmGraphBuilder::BuildF32SConvertI64(Node* input) {
    1939             :   // TODO(titzer/bradnelson): Check handlng of asm.js case.
    1940             :   return BuildIntToFloatConversionInstruction(
    1941             :       input, ExternalReference::wasm_int64_to_float32(),
    1942           0 :       MachineRepresentation::kWord64, MachineType::Float32());
    1943             : }
    1944           0 : Node* WasmGraphBuilder::BuildF32UConvertI64(Node* input) {
    1945             :   // TODO(titzer/bradnelson): Check handlng of asm.js case.
    1946             :   return BuildIntToFloatConversionInstruction(
    1947             :       input, ExternalReference::wasm_uint64_to_float32(),
    1948           0 :       MachineRepresentation::kWord64, MachineType::Float32());
    1949             : }
    1950           0 : Node* WasmGraphBuilder::BuildF64SConvertI64(Node* input) {
    1951             :   return BuildIntToFloatConversionInstruction(
    1952             :       input, ExternalReference::wasm_int64_to_float64(),
    1953           0 :       MachineRepresentation::kWord64, MachineType::Float64());
    1954             : }
    1955           0 : Node* WasmGraphBuilder::BuildF64UConvertI64(Node* input) {
    1956             :   return BuildIntToFloatConversionInstruction(
    1957             :       input, ExternalReference::wasm_uint64_to_float64(),
    1958           0 :       MachineRepresentation::kWord64, MachineType::Float64());
    1959             : }
    1960             : 
    1961           0 : Node* WasmGraphBuilder::BuildIntToFloatConversionInstruction(
    1962             :     Node* input, ExternalReference ref,
    1963             :     MachineRepresentation parameter_representation,
    1964           0 :     const MachineType result_type) {
    1965             :   int stack_slot_size =
    1966             :       std::max(ElementSizeInBytes(parameter_representation),
    1967           0 :                ElementSizeInBytes(result_type.representation()));
    1968             :   Node* stack_slot =
    1969           0 :       graph()->NewNode(mcgraph()->machine()->StackSlot(stack_slot_size));
    1970             :   const Operator* store_op = mcgraph()->machine()->Store(
    1971           0 :       StoreRepresentation(parameter_representation, kNoWriteBarrier));
    1972             :   SetEffect(graph()->NewNode(store_op, stack_slot, mcgraph()->Int32Constant(0),
    1973           0 :                              input, Effect(), Control()));
    1974           0 :   MachineType sig_types[] = {MachineType::Pointer()};
    1975             :   MachineSignature sig(0, 1, sig_types);
    1976           0 :   Node* function = graph()->NewNode(mcgraph()->common()->ExternalConstant(ref));
    1977           0 :   BuildCCall(&sig, function, stack_slot);
    1978             :   return SetEffect(graph()->NewNode(mcgraph()->machine()->Load(result_type),
    1979             :                                     stack_slot, mcgraph()->Int32Constant(0),
    1980           0 :                                     Effect(), Control()));
    1981             : }
    1982             : 
    1983             : namespace {
    1984             : 
    1985           0 : ExternalReference convert_ccall_ref(WasmGraphBuilder* builder,
    1986             :                                     wasm::WasmOpcode opcode) {
    1987           0 :   switch (opcode) {
    1988             :     case wasm::kExprI64SConvertF32:
    1989             :     case wasm::kExprI64SConvertSatF32:
    1990           0 :       return ExternalReference::wasm_float32_to_int64();
    1991             :     case wasm::kExprI64UConvertF32:
    1992             :     case wasm::kExprI64UConvertSatF32:
    1993           0 :       return ExternalReference::wasm_float32_to_uint64();
    1994             :     case wasm::kExprI64SConvertF64:
    1995             :     case wasm::kExprI64SConvertSatF64:
    1996           0 :       return ExternalReference::wasm_float64_to_int64();
    1997             :     case wasm::kExprI64UConvertF64:
    1998             :     case wasm::kExprI64UConvertSatF64:
    1999           0 :       return ExternalReference::wasm_float64_to_uint64();
    2000             :     default:
    2001           0 :       UNREACHABLE();
    2002             :   }
    2003             : }
    2004             : 
    2005             : }  // namespace
    2006             : 
    2007           0 : Node* WasmGraphBuilder::BuildCcallConvertFloat(Node* input,
    2008             :                                                wasm::WasmCodePosition position,
    2009           0 :                                                wasm::WasmOpcode opcode) {
    2010           0 :   const MachineType int_ty = IntConvertType(opcode);
    2011           0 :   const MachineType float_ty = FloatConvertType(opcode);
    2012           0 :   ExternalReference call_ref = convert_ccall_ref(this, opcode);
    2013           0 :   int stack_slot_size = std::max(ElementSizeInBytes(int_ty.representation()),
    2014           0 :                                  ElementSizeInBytes(float_ty.representation()));
    2015             :   Node* stack_slot =
    2016           0 :       graph()->NewNode(mcgraph()->machine()->StackSlot(stack_slot_size));
    2017             :   const Operator* store_op = mcgraph()->machine()->Store(
    2018           0 :       StoreRepresentation(float_ty.representation(), kNoWriteBarrier));
    2019             :   SetEffect(graph()->NewNode(store_op, stack_slot, Int32Constant(0), input,
    2020             :                              Effect(), Control()));
    2021           0 :   MachineType sig_types[] = {MachineType::Int32(), MachineType::Pointer()};
    2022             :   MachineSignature sig(1, 1, sig_types);
    2023             :   Node* function =
    2024           0 :       graph()->NewNode(mcgraph()->common()->ExternalConstant(call_ref));
    2025           0 :   Node* overflow = BuildCCall(&sig, function, stack_slot);
    2026           0 :   if (IsTrappingConvertOp(opcode)) {
    2027             :     ZeroCheck32(wasm::kTrapFloatUnrepresentable, overflow, position);
    2028             :     return SetEffect(graph()->NewNode(mcgraph()->machine()->Load(int_ty),
    2029             :                                       stack_slot, Int32Constant(0), Effect(),
    2030           0 :                                       Control()));
    2031             :   }
    2032           0 :   Node* test = Binop(wasm::kExprI32Eq, overflow, Int32Constant(0), position);
    2033           0 :   Diamond tl_d(graph(), mcgraph()->common(), test, BranchHint::kFalse);
    2034           0 :   tl_d.Chain(Control());
    2035           0 :   Node* nan_test = Binop(NeOp(float_ty), input, input);
    2036           0 :   Diamond nan_d(graph(), mcgraph()->common(), nan_test, BranchHint::kFalse);
    2037           0 :   nan_d.Nest(tl_d, true);
    2038           0 :   Node* neg_test = Binop(LtOp(float_ty), input, Zero(this, float_ty));
    2039           0 :   Diamond sat_d(graph(), mcgraph()->common(), neg_test, BranchHint::kNone);
    2040           0 :   sat_d.Nest(nan_d, false);
    2041             :   Node* sat_val =
    2042           0 :       sat_d.Phi(int_ty.representation(), Min(this, int_ty), Max(this, int_ty));
    2043             :   Node* load =
    2044             :       SetEffect(graph()->NewNode(mcgraph()->machine()->Load(int_ty), stack_slot,
    2045           0 :                                  Int32Constant(0), Effect(), Control()));
    2046             :   Node* nan_val =
    2047           0 :       nan_d.Phi(int_ty.representation(), Zero(this, int_ty), sat_val);
    2048           0 :   return tl_d.Phi(int_ty.representation(), nan_val, load);
    2049             : }
    2050             : 
    2051       10240 : Node* WasmGraphBuilder::MemoryGrow(Node* input) {
    2052        1280 :   needs_stack_check_ = true;
    2053             : 
    2054             :   WasmMemoryGrowDescriptor interface_descriptor;
    2055             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    2056             :       mcgraph()->zone(),                              // zone
    2057             :       interface_descriptor,                           // descriptor
    2058             :       interface_descriptor.GetStackParameterCount(),  // stack parameter count
    2059             :       CallDescriptor::kNoFlags,                       // flags
    2060             :       Operator::kNoProperties,                        // properties
    2061        1280 :       StubCallMode::kCallWasmRuntimeStub);            // stub call mode
    2062             :   // A direct call to a wasm runtime stub defined in this module.
    2063             :   // Just encode the stub index. This will be patched at relocation.
    2064             :   Node* call_target = mcgraph()->RelocatableIntPtrConstant(
    2065        1280 :       wasm::WasmCode::kWasmMemoryGrow, RelocInfo::WASM_STUB_CALL);
    2066             :   return SetEffect(
    2067             :       SetControl(graph()->NewNode(mcgraph()->common()->Call(call_descriptor),
    2068        2560 :                                   call_target, input, Effect(), Control())));
    2069             : }
    2070             : 
    2071             : #ifdef DEBUG
    2072             : 
    2073             : namespace {
    2074             : 
    2075             : constexpr uint32_t kBytesPerExceptionValuesArrayElement = 2;
    2076             : 
    2077             : size_t ComputeEncodedElementSize(wasm::ValueType type) {
    2078             :   size_t byte_size =
    2079             :       static_cast<size_t>(wasm::ValueTypes::ElementSizeInBytes(type));
    2080             :   DCHECK_EQ(byte_size % kBytesPerExceptionValuesArrayElement, 0);
    2081             :   DCHECK_LE(1, byte_size / kBytesPerExceptionValuesArrayElement);
    2082             :   return byte_size / kBytesPerExceptionValuesArrayElement;
    2083             : }
    2084             : 
    2085             : }  // namespace
    2086             : 
    2087             : #endif  // DEBUG
    2088             : 
    2089         538 : uint32_t WasmGraphBuilder::GetExceptionEncodedSize(
    2090             :     const wasm::WasmException* exception) const {
    2091        1670 :   const wasm::WasmExceptionSig* sig = exception->sig;
    2092             :   uint32_t encoded_size = 0;
    2093        1670 :   for (size_t i = 0; i < sig->parameter_count(); ++i) {
    2094         297 :     switch (sig->GetParam(i)) {
    2095             :       case wasm::kWasmI32:
    2096             :       case wasm::kWasmF32:
    2097             :         DCHECK_EQ(2, ComputeEncodedElementSize(sig->GetParam(i)));
    2098         207 :         encoded_size += 2;
    2099         207 :         break;
    2100             :       case wasm::kWasmI64:
    2101             :       case wasm::kWasmF64:
    2102             :         DCHECK_EQ(4, ComputeEncodedElementSize(sig->GetParam(i)));
    2103          36 :         encoded_size += 4;
    2104          36 :         break;
    2105             :       case wasm::kWasmS128:
    2106             :         DCHECK_EQ(8, ComputeEncodedElementSize(sig->GetParam(i)));
    2107          18 :         encoded_size += 8;
    2108          18 :         break;
    2109             :       case wasm::kWasmAnyRef:
    2110          36 :         encoded_size += 1;
    2111          36 :         break;
    2112             :       default:
    2113           0 :         UNREACHABLE();
    2114             :     }
    2115             :   }
    2116         538 :   return encoded_size;
    2117             : }
    2118             : 
    2119         538 : Node* WasmGraphBuilder::Throw(uint32_t exception_index,
    2120             :                               const wasm::WasmException* exception,
    2121        4495 :                               const Vector<Node*> values) {
    2122         538 :   needs_stack_check_ = true;
    2123         538 :   uint32_t encoded_size = GetExceptionEncodedSize(exception);
    2124             :   Node* create_parameters[] = {
    2125         538 :       LoadExceptionTagFromTable(exception_index),
    2126        1078 :       BuildChangeUint31ToSmi(Uint32Constant(encoded_size))};
    2127             :   Node* except_obj =
    2128             :       BuildCallToRuntime(Runtime::kWasmThrowCreate, create_parameters,
    2129         538 :                          arraysize(create_parameters));
    2130             :   Node* values_array =
    2131         540 :       BuildCallToRuntime(Runtime::kWasmExceptionGetValues, &except_obj, 1);
    2132         538 :   uint32_t index = 0;
    2133        1669 :   const wasm::WasmExceptionSig* sig = exception->sig;
    2134         538 :   MachineOperatorBuilder* m = mcgraph()->machine();
    2135        1670 :   for (size_t i = 0; i < sig->parameter_count(); ++i) {
    2136         592 :     Node* value = values[i];
    2137         296 :     switch (sig->GetParam(i)) {
    2138             :       case wasm::kWasmF32:
    2139          18 :         value = graph()->NewNode(m->BitcastFloat32ToInt32(), value);
    2140             :         V8_FALLTHROUGH;
    2141             :       case wasm::kWasmI32:
    2142         206 :         BuildEncodeException32BitValue(values_array, &index, value);
    2143         207 :         break;
    2144             :       case wasm::kWasmF64:
    2145          18 :         value = graph()->NewNode(m->BitcastFloat64ToInt64(), value);
    2146             :         V8_FALLTHROUGH;
    2147             :       case wasm::kWasmI64: {
    2148             :         Node* upper32 = graph()->NewNode(
    2149             :             m->TruncateInt64ToInt32(),
    2150          36 :             Binop(wasm::kExprI64ShrU, value, Int64Constant(32)));
    2151          36 :         BuildEncodeException32BitValue(values_array, &index, upper32);
    2152          36 :         Node* lower32 = graph()->NewNode(m->TruncateInt64ToInt32(), value);
    2153          36 :         BuildEncodeException32BitValue(values_array, &index, lower32);
    2154          36 :         break;
    2155             :       }
    2156             :       case wasm::kWasmS128:
    2157             :         BuildEncodeException32BitValue(
    2158             :             values_array, &index,
    2159          36 :             graph()->NewNode(m->I32x4ExtractLane(0), value));
    2160             :         BuildEncodeException32BitValue(
    2161             :             values_array, &index,
    2162          36 :             graph()->NewNode(m->I32x4ExtractLane(1), value));
    2163             :         BuildEncodeException32BitValue(
    2164             :             values_array, &index,
    2165          36 :             graph()->NewNode(m->I32x4ExtractLane(2), value));
    2166             :         BuildEncodeException32BitValue(
    2167             :             values_array, &index,
    2168          36 :             graph()->NewNode(m->I32x4ExtractLane(3), value));
    2169          18 :         break;
    2170             :       case wasm::kWasmAnyRef:
    2171         144 :         STORE_FIXED_ARRAY_SLOT_ANY(values_array, index, value);
    2172          36 :         ++index;
    2173          36 :         break;
    2174             :       default:
    2175           0 :         UNREACHABLE();
    2176             :     }
    2177             :   }
    2178             :   DCHECK_EQ(encoded_size, index);
    2179             :   WasmThrowDescriptor interface_descriptor;
    2180             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    2181             :       mcgraph()->zone(), interface_descriptor,
    2182             :       interface_descriptor.GetStackParameterCount(), CallDescriptor::kNoFlags,
    2183         539 :       Operator::kNoProperties, StubCallMode::kCallWasmRuntimeStub);
    2184             :   Node* call_target = mcgraph()->RelocatableIntPtrConstant(
    2185         538 :       wasm::WasmCode::kWasmThrow, RelocInfo::WASM_STUB_CALL);
    2186             :   return SetEffect(SetControl(
    2187             :       graph()->NewNode(mcgraph()->common()->Call(call_descriptor), call_target,
    2188        1620 :                        except_obj, Effect(), Control())));
    2189             : }
    2190             : 
    2191         350 : void WasmGraphBuilder::BuildEncodeException32BitValue(Node* values_array,
    2192             :                                                       uint32_t* index,
    2193        3855 :                                                       Node* value) {
    2194         350 :   MachineOperatorBuilder* machine = mcgraph()->machine();
    2195             :   Node* upper_halfword_as_smi = BuildChangeUint31ToSmi(
    2196         702 :       graph()->NewNode(machine->Word32Shr(), value, Int32Constant(16)));
    2197        1400 :   STORE_FIXED_ARRAY_SLOT_SMI(values_array, *index, upper_halfword_as_smi);
    2198         350 :   ++(*index);
    2199             :   Node* lower_halfword_as_smi = BuildChangeUint31ToSmi(
    2200         702 :       graph()->NewNode(machine->Word32And(), value, Int32Constant(0xFFFFu)));
    2201        1404 :   STORE_FIXED_ARRAY_SLOT_SMI(values_array, *index, lower_halfword_as_smi);
    2202         351 :   ++(*index);
    2203         351 : }
    2204             : 
    2205         306 : Node* WasmGraphBuilder::BuildDecodeException32BitValue(Node* values_array,
    2206        3060 :                                                        uint32_t* index) {
    2207         306 :   MachineOperatorBuilder* machine = mcgraph()->machine();
    2208             :   Node* upper =
    2209        1224 :       BuildChangeSmiToInt32(LOAD_FIXED_ARRAY_SLOT_SMI(values_array, *index));
    2210         306 :   (*index)++;
    2211         306 :   upper = graph()->NewNode(machine->Word32Shl(), upper, Int32Constant(16));
    2212             :   Node* lower =
    2213        1224 :       BuildChangeSmiToInt32(LOAD_FIXED_ARRAY_SLOT_SMI(values_array, *index));
    2214         306 :   (*index)++;
    2215         306 :   Node* value = graph()->NewNode(machine->Word32Or(), upper, lower);
    2216         306 :   return value;
    2217             : }
    2218             : 
    2219          18 : Node* WasmGraphBuilder::BuildDecodeException64BitValue(Node* values_array,
    2220             :                                                        uint32_t* index) {
    2221             :   Node* upper = Binop(wasm::kExprI64Shl,
    2222             :                       Unop(wasm::kExprI64UConvertI32,
    2223             :                            BuildDecodeException32BitValue(values_array, index)),
    2224          18 :                       Int64Constant(32));
    2225             :   Node* lower = Unop(wasm::kExprI64UConvertI32,
    2226          18 :                      BuildDecodeException32BitValue(values_array, index));
    2227          18 :   return Binop(wasm::kExprI64Ior, upper, lower);
    2228             : }
    2229             : 
    2230        3816 : Node* WasmGraphBuilder::Rethrow(Node* except_obj) {
    2231         477 :   needs_stack_check_ = true;
    2232             :   WasmThrowDescriptor interface_descriptor;
    2233             :   auto call_descriptor = Linkage::GetStubCallDescriptor(
    2234             :       mcgraph()->zone(), interface_descriptor,
    2235             :       interface_descriptor.GetStackParameterCount(), CallDescriptor::kNoFlags,
    2236         477 :       Operator::kNoProperties, StubCallMode::kCallWasmRuntimeStub);
    2237             :   Node* call_target = mcgraph()->RelocatableIntPtrConstant(
    2238         477 :       wasm::WasmCode::kWasmThrow, RelocInfo::WASM_STUB_CALL);
    2239             :   return SetEffect(SetControl(
    2240             :       graph()->NewNode(mcgraph()->common()->Call(call_descriptor), call_target,
    2241         954 :                        except_obj, Effect(), Control())));
    2242             : }
    2243             : 
    2244         423 : Node* WasmGraphBuilder::ExceptionTagEqual(Node* caught_tag,
    2245         423 :                                           Node* expected_tag) {
    2246         423 :   MachineOperatorBuilder* machine = mcgraph()->machine();
    2247         846 :   return graph()->NewNode(machine->WordEqual(), caught_tag, expected_tag);
    2248             : }
    2249             : 
    2250        9620 : Node* WasmGraphBuilder::LoadExceptionTagFromTable(uint32_t exception_index) {
    2251             :   Node* exceptions_table =
    2252        1922 :       LOAD_INSTANCE_FIELD(ExceptionsTable, MachineType::TaggedPointer());
    2253        2888 :   Node* tag = LOAD_FIXED_ARRAY_SLOT_PTR(exceptions_table, exception_index);
    2254         962 :   return tag;
    2255             : }
    2256             : 
    2257         422 : Node* WasmGraphBuilder::GetExceptionTag(Node* except_obj) {
    2258         422 :   needs_stack_check_ = true;
    2259         422 :   return BuildCallToRuntime(Runtime::kWasmExceptionGetTag, &except_obj, 1);
    2260             : }
    2261             : 
    2262         423 : Node** WasmGraphBuilder::GetExceptionValues(
    2263         126 :     Node* except_obj, const wasm::WasmException* exception) {
    2264             :   Node* values_array =
    2265         423 :       BuildCallToRuntime(Runtime::kWasmExceptionGetValues, &except_obj, 1);
    2266         423 :   uint32_t index = 0;
    2267        1404 :   const wasm::WasmExceptionSig* sig = exception->sig;
    2268         423 :   Node** values = Buffer(sig->parameter_count());
    2269        1404 :   for (size_t i = 0; i < sig->parameter_count(); ++i) {
    2270             :     Node* value;
    2271         279 :     switch (sig->GetParam(i)) {
    2272             :       case wasm::kWasmI32:
    2273         225 :         value = BuildDecodeException32BitValue(values_array, &index);
    2274         225 :         break;
    2275             :       case wasm::kWasmI64:
    2276           9 :         value = BuildDecodeException64BitValue(values_array, &index);
    2277           9 :         break;
    2278             :       case wasm::kWasmF32: {
    2279             :         value = Unop(wasm::kExprF32ReinterpretI32,
    2280           9 :                      BuildDecodeException32BitValue(values_array, &index));
    2281           9 :         break;
    2282             :       }
    2283             :       case wasm::kWasmF64: {
    2284             :         value = Unop(wasm::kExprF64ReinterpretI64,
    2285           9 :                      BuildDecodeException64BitValue(values_array, &index));
    2286           9 :         break;
    2287             :       }
    2288             :       case wasm::kWasmS128:
    2289             :         value = graph()->NewNode(
    2290             :             mcgraph()->machine()->I32x4Splat(),
    2291          18 :             BuildDecodeException32BitValue(values_array, &index));
    2292             :         value = graph()->NewNode(
    2293             :             mcgraph()->machine()->I32x4ReplaceLane(1), value,
    2294          18 :             BuildDecodeException32BitValue(values_array, &index));
    2295             :         value = graph()->NewNode(
    2296             :             mcgraph()->machine()->I32x4ReplaceLane(2), value,
    2297          18 :             BuildDecodeException32BitValue(values_array, &index));
    2298             :         value = graph()->NewNode(
    2299             :             mcgraph()->machine()->I32x4ReplaceLane(3), value,
    2300          18 :             BuildDecodeException32BitValue(values_array, &index));
    2301           9 :         break;
    2302             :       case wasm::kWasmAnyRef:
    2303          54 :         value = LOAD_FIXED_ARRAY_SLOT_ANY(values_array, index);
    2304          18 :         ++index;
    2305          18 :         break;
    2306             :       default:
    2307           0 :         UNREACHABLE();
    2308             :     }
    2309         279 :     values[i] = value;
    2310             :   }
    2311             :   DCHECK_EQ(index, GetExceptionEncodedSize(exception));
    2312         423 :   return values;
    2313             : }
    2314             : 
    2315       35303 : Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right,
    2316      216304 :                                      wasm::WasmCodePosition position) {
    2317       35303 :   MachineOperatorBuilder* m = mcgraph()->machine();
    2318             :   ZeroCheck32(wasm::kTrapDivByZero, right, position);
    2319             :   Node* before = Control();
    2320             :   Node* denom_is_m1;
    2321             :   Node* denom_is_not_m1;
    2322             :   BranchExpectFalse(
    2323             :       graph()->NewNode(m->Word32Equal(), right, mcgraph()->Int32Constant(-1)),
    2324       35303 :       &denom_is_m1, &denom_is_not_m1);
    2325       35303 :   SetControl(denom_is_m1);
    2326       35303 :   TrapIfEq32(wasm::kTrapDivUnrepresentable, left, kMinInt, position);
    2327       35303 :   if (Control() != denom_is_m1) {
    2328             :     SetControl(graph()->NewNode(mcgraph()->common()->Merge(2), denom_is_not_m1,
    2329        4486 :                                 Control()));
    2330             :   } else {
    2331             :     SetControl(before);
    2332             :   }
    2333       70606 :   return graph()->NewNode(m->Int32Div(), left, right, Control());
    2334             : }
    2335             : 
    2336       35157 : Node* WasmGraphBuilder::BuildI32RemS(Node* left, Node* right,
    2337      175785 :                                      wasm::WasmCodePosition position) {
    2338       35157 :   MachineOperatorBuilder* m = mcgraph()->machine();
    2339             : 
    2340             :   ZeroCheck32(wasm::kTrapRemByZero, right, position);
    2341             : 
    2342             :   Diamond d(
    2343             :       graph(), mcgraph()->common(),
    2344             :       graph()->NewNode(m->Word32Equal(), right, mcgraph()->Int32Constant(-1)),
    2345      105471 :       BranchHint::kFalse);
    2346       35157 :   d.Chain(Control());
    2347             : 
    2348             :   return d.Phi(MachineRepresentation::kWord32, mcgraph()->Int32Constant(0),
    2349       70314 :                graph()->NewNode(m->Int32Mod(), left, right, d.if_false));
    2350             : }
    2351             : 
    2352       35173 : Node* WasmGraphBuilder::BuildI32DivU(Node* left, Node* right,
    2353       35173 :                                      wasm::WasmCodePosition position) {
    2354       35173 :   MachineOperatorBuilder* m = mcgraph()->machine();
    2355             :   return graph()->NewNode(m->Uint32Div(), left, right,
    2356       70346 :                           ZeroCheck32(wasm::kTrapDivByZero, right, position));
    2357             : }
    2358             : 
    2359       35128 : Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right,
    2360       35128 :                                      wasm::WasmCodePosition position) {
    2361       35128 :   MachineOperatorBuilder* m = mcgraph()->machine();
    2362             :   return graph()->NewNode(m->Uint32Mod(), left, right,
    2363       70256 :                           ZeroCheck32(wasm::kTrapRemByZero, right, position));
    2364             : }
    2365             : 
    2366        1310 : Node* WasmGraphBuilder::BuildI32AsmjsDivS(Node* left, Node* right) {
    2367         512 :   MachineOperatorBuilder* m = mcgraph()->machine();
    2368             : 
    2369             :   Int32Matcher mr(right);
    2370         512 :   if (mr.HasValue()) {
    2371         430 :     if (mr.Value() == 0) {
    2372          21 :       return mcgraph()->Int32Constant(0);
    2373         409 :     } else if (mr.Value() == -1) {
    2374             :       // The result is the negation of the left input.
    2375          42 :       return graph()->NewNode(m->Int32Sub(), mcgraph()->Int32Constant(0), left);
    2376             :     }
    2377         776 :     return graph()->NewNode(m->Int32Div(), left, right, Control());
    2378             :   }
    2379             : 
    2380             :   // asm.js semantics return 0 on divide or mod by zero.
    2381          82 :   if (m->Int32DivIsSafe()) {
    2382             :     // The hardware instruction does the right thing (e.g. arm).
    2383           0 :     return graph()->NewNode(m->Int32Div(), left, right, graph()->start());
    2384             :   }
    2385             : 
    2386             :   // Check denominator for zero.
    2387             :   Diamond z(
    2388             :       graph(), mcgraph()->common(),
    2389             :       graph()->NewNode(m->Word32Equal(), right, mcgraph()->Int32Constant(0)),
    2390         246 :       BranchHint::kFalse);
    2391             : 
    2392             :   // Check numerator for -1. (avoid minint / -1 case).
    2393             :   Diamond n(
    2394             :       graph(), mcgraph()->common(),
    2395             :       graph()->NewNode(m->Word32Equal(), right, mcgraph()->Int32Constant(-1)),
    2396         246 :       BranchHint::kFalse);
    2397             : 
    2398          82 :   Node* div = graph()->NewNode(m->Int32Div(), left, right, z.if_false);
    2399             :   Node* neg =
    2400          82 :       graph()->NewNode(m->Int32Sub(), mcgraph()->Int32Constant(0), left);
    2401             : 
    2402             :   return n.Phi(
    2403             :       MachineRepresentation::kWord32, neg,
    2404          82 :       z.Phi(MachineRepresentation::kWord32, mcgraph()->Int32Constant(0), div));
    2405             : }
    2406             : 
    2407        1090 : Node* WasmGraphBuilder::BuildI32AsmjsRemS(Node* left, Node* right) {
    2408         566 :   CommonOperatorBuilder* c = mcgraph()->common();
    2409         566 :   MachineOperatorBuilder* m = mcgraph()->machine();
    2410         566 :   Node* const zero = mcgraph()->Int32Constant(0);
    2411             : 
    2412             :   Int32Matcher mr(right);
    2413         566 :   if (mr.HasValue()) {
    2414         488 :     if (mr.Value() == 0 || mr.Value() == -1) {
    2415             :       return zero;
    2416             :     }
    2417         892 :     return graph()->NewNode(m->Int32Mod(), left, right, Control());
    2418             :   }
    2419             : 
    2420             :   // General case for signed integer modulus, with optimization for (unknown)
    2421             :   // power of 2 right hand side.
    2422             :   //
    2423             :   //   if 0 < right then
    2424             :   //     msk = right - 1
    2425             :   //     if right & msk != 0 then
    2426             :   //       left % right
    2427             :   //     else
    2428             :   //       if left < 0 then
    2429             :   //         -(-left & msk)
    2430             :   //       else
    2431             :   //         left & msk
    2432             :   //   else
    2433             :   //     if right < -1 then
    2434             :   //       left % right
    2435             :   //     else
    2436             :   //       zero
    2437             :   //
    2438             :   // Note: We do not use the Diamond helper class here, because it really hurts
    2439             :   // readability with nested diamonds.
    2440          78 :   Node* const minus_one = mcgraph()->Int32Constant(-1);
    2441             : 
    2442          78 :   const Operator* const merge_op = c->Merge(2);
    2443          78 :   const Operator* const phi_op = c->Phi(MachineRepresentation::kWord32, 2);
    2444             : 
    2445          78 :   Node* check0 = graph()->NewNode(m->Int32LessThan(), zero, right);
    2446             :   Node* branch0 =
    2447          78 :       graph()->NewNode(c->Branch(BranchHint::kTrue), check0, graph()->start());
    2448             : 
    2449          78 :   Node* if_true0 = graph()->NewNode(c->IfTrue(), branch0);
    2450             :   Node* true0;
    2451             :   {
    2452          78 :     Node* msk = graph()->NewNode(m->Int32Add(), right, minus_one);
    2453             : 
    2454          78 :     Node* check1 = graph()->NewNode(m->Word32And(), right, msk);
    2455          78 :     Node* branch1 = graph()->NewNode(c->Branch(), check1, if_true0);
    2456             : 
    2457          78 :     Node* if_true1 = graph()->NewNode(c->IfTrue(), branch1);
    2458          78 :     Node* true1 = graph()->NewNode(m->Int32Mod(), left, right, if_true1);
    2459             : 
    2460          78 :     Node* if_false1 = graph()->NewNode(c->IfFalse(), branch1);
    2461             :     Node* false1;
    2462             :     {
    2463          78 :       Node* check2 = graph()->NewNode(m->Int32LessThan(), left, zero);
    2464             :       Node* branch2 =
    2465          78 :           graph()->NewNode(c->Branch(BranchHint::kFalse), check2, if_false1);
    2466             : 
    2467          78 :       Node* if_true2 = graph()->NewNode(c->IfTrue(), branch2);
    2468             :       Node* true2 = graph()->NewNode(
    2469             :           m->Int32Sub(), zero,
    2470             :           graph()->NewNode(m->Word32And(),
    2471         234 :                            graph()->NewNode(m->Int32Sub(), zero, left), msk));
    2472             : 
    2473          78 :       Node* if_false2 = graph()->NewNode(c->IfFalse(), branch2);
    2474          78 :       Node* false2 = graph()->NewNode(m->Word32And(), left, msk);
    2475             : 
    2476             :       if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
    2477             :       false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
    2478             :     }
    2479             : 
    2480             :     if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
    2481             :     true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
    2482             :   }
    2483             : 
    2484          78 :   Node* if_false0 = graph()->NewNode(c->IfFalse(), branch0);
    2485             :   Node* false0;
    2486             :   {
    2487          78 :     Node* check1 = graph()->NewNode(m->Int32LessThan(), right, minus_one);
    2488             :     Node* branch1 =
    2489          78 :         graph()->NewNode(c->Branch(BranchHint::kTrue), check1, if_false0);
    2490             : 
    2491          78 :     Node* if_true1 = graph()->NewNode(c->IfTrue(), branch1);
    2492          78 :     Node* true1 = graph()->NewNode(m->Int32Mod(), left, right, if_true1);
    2493             : 
    2494          78 :     Node* if_false1 = graph()->NewNode(c->IfFalse(), branch1);
    2495             :     Node* false1 = zero;
    2496             : 
    2497             :     if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
    2498             :     false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
    2499             :   }
    2500             : 
    2501             :   Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
    2502          78 :   return graph()->NewNode(phi_op, true0, false0, merge0);
    2503             : }
    2504             : 
    2505         676 : Node* WasmGraphBuilder::BuildI32AsmjsDivU(Node* left, Node* right) {
    2506         169 :   MachineOperatorBuilder* m = mcgraph()->machine();
    2507             :   // asm.js semantics return 0 on divide or mod by zero.
    2508         169 :   if (m->Uint32DivIsSafe()) {
    2509             :     // The hardware instruction does the right thing (e.g. arm).
    2510           0 :     return graph()->NewNode(m->Uint32Div(), left, right, graph()->start());
    2511             :   }
    2512             : 
    2513             :   // Explicit check for x % 0.
    2514             :   Diamond z(
    2515             :       graph(), mcgraph()->common(),
    2516             :       graph()->NewNode(m->Word32Equal(), right, mcgraph()->Int32Constant(0)),
    2517         507 :       BranchHint::kFalse);
    2518             : 
    2519             :   return z.Phi(MachineRepresentation::kWord32, mcgraph()->Int32Constant(0),
    2520             :                graph()->NewNode(mcgraph()->machine()->Uint32Div(), left, right,
    2521         507 :                                 z.if_false));
    2522             : }
    2523             : 
    2524         912 : Node* WasmGraphBuilder::BuildI32AsmjsRemU(Node* left, Node* right) {
    2525         228 :   MachineOperatorBuilder* m = mcgraph()->machine();
    2526             :   // asm.js semantics return 0 on divide or mod by zero.
    2527             :   // Explicit check for x % 0.
    2528             :   Diamond z(
    2529             :       graph(), mcgraph()->common(),
    2530             :       graph()->NewNode(m->Word32Equal(), right, mcgraph()->Int32Constant(0)),
    2531         684 :       BranchHint::kFalse);
    2532             : 
    2533             :   Node* rem = graph()->NewNode(mcgraph()->machine()->Uint32Mod(), left, right,
    2534         456 :                                z.if_false);
    2535             :   return z.Phi(MachineRepresentation::kWord32, mcgraph()->Int32Constant(0),
    2536         228 :                rem);
    2537             : }
    2538             : 
    2539        1663 : Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right,
    2540       16610 :                                      wasm::WasmCodePosition position) {
    2541        3326 :   if (mcgraph()->machine()->Is32()) {
    2542             :     return BuildDiv64Call(left, right, ExternalReference::wasm_int64_div(),
    2543           0 :                           MachineType::Int64(), wasm::kTrapDivByZero, position);
    2544             :   }
    2545             :   ZeroCheck64(wasm::kTrapDivByZero, right, position);
    2546             :   Node* before = Control();
    2547             :   Node* denom_is_m1;
    2548             :   Node* denom_is_not_m1;
    2549             :   BranchExpectFalse(graph()->NewNode(mcgraph()->machine()->Word64Equal(), right,
    2550             :                                      mcgraph()->Int64Constant(-1)),
    2551        3326 :                     &denom_is_m1, &denom_is_not_m1);
    2552        1663 :   SetControl(denom_is_m1);
    2553             :   TrapIfEq64(wasm::kTrapDivUnrepresentable, left,
    2554        1663 :              std::numeric_limits<int64_t>::min(), position);
    2555        1663 :   if (Control() != denom_is_m1) {
    2556             :     SetControl(graph()->NewNode(mcgraph()->common()->Merge(2), denom_is_not_m1,
    2557        3306 :                                 Control()));
    2558             :   } else {
    2559             :     SetControl(before);
    2560             :   }
    2561             :   return graph()->NewNode(mcgraph()->machine()->Int64Div(), left, right,
    2562        3326 :                           Control());
    2563             : }
    2564             : 
    2565        1517 : Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right,
    2566       10619 :                                      wasm::WasmCodePosition position) {
    2567        3034 :   if (mcgraph()->machine()->Is32()) {
    2568             :     return BuildDiv64Call(left, right, ExternalReference::wasm_int64_mod(),
    2569           0 :                           MachineType::Int64(), wasm::kTrapRemByZero, position);
    2570             :   }
    2571             :   ZeroCheck64(wasm::kTrapRemByZero, right, position);
    2572             :   Diamond d(mcgraph()->graph(), mcgraph()->common(),
    2573             :             graph()->NewNode(mcgraph()->machine()->Word64Equal(), right,
    2574        4551 :                              mcgraph()->Int64Constant(-1)));
    2575             : 
    2576        1517 :   d.Chain(Control());
    2577             : 
    2578             :   Node* rem = graph()->NewNode(mcgraph()->machine()->Int64Mod(), left, right,
    2579        3034 :                                d.if_false);
    2580             : 
    2581             :   return d.Phi(MachineRepresentation::kWord64, mcgraph()->Int64Constant(0),
    2582        1517 :                rem);
    2583             : }
    2584             : 
    2585        1535 : Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right,
    2586        3070 :                                      wasm::WasmCodePosition position) {
    2587        3070 :   if (mcgraph()->machine()->Is32()) {
    2588             :     return BuildDiv64Call(left, right, ExternalReference::wasm_uint64_div(),
    2589           0 :                           MachineType::Int64(), wasm::kTrapDivByZero, position);
    2590             :   }
    2591             :   return graph()->NewNode(mcgraph()->machine()->Uint64Div(), left, right,
    2592        3070 :                           ZeroCheck64(wasm::kTrapDivByZero, right, position));
    2593             : }
    2594        1517 : Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right,
    2595        3034 :                                      wasm::WasmCodePosition position) {
    2596        3034 :   if (mcgraph()->machine()->Is32()) {
    2597             :     return BuildDiv64Call(left, right, ExternalReference::wasm_uint64_mod(),
    2598           0 :                           MachineType::Int64(), wasm::kTrapRemByZero, position);
    2599             :   }
    2600             :   return graph()->NewNode(mcgraph()->machine()->Uint64Mod(), left, right,
    2601        3034 :                           ZeroCheck64(wasm::kTrapRemByZero, right, position));
    2602             : }
    2603             : 
    2604           0 : Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right,
    2605             :                                        ExternalReference ref,
    2606             :                                        MachineType result_type,
    2607             :                                        wasm::TrapReason trap_zero,
    2608           0 :                                        wasm::WasmCodePosition position) {
    2609             :   Node* stack_slot =
    2610           0 :       graph()->NewNode(mcgraph()->machine()->StackSlot(2 * sizeof(double)));
    2611             : 
    2612             :   const Operator* store_op = mcgraph()->machine()->Store(
    2613           0 :       StoreRepresentation(MachineRepresentation::kWord64, kNoWriteBarrier));
    2614             :   SetEffect(graph()->NewNode(store_op, stack_slot, mcgraph()->Int32Constant(0),
    2615           0 :                              left, Effect(), Control()));
    2616             :   SetEffect(graph()->NewNode(store_op, stack_slot,
    2617             :                              mcgraph()->Int32Constant(sizeof(double)), right,
    2618           0 :                              Effect(), Control()));
    2619             : 
    2620           0 :   MachineType sig_types[] = {MachineType::Int32(), MachineType::Pointer()};
    2621             :   MachineSignature sig(1, 1, sig_types);
    2622             : 
    2623           0 :   Node* function = graph()->NewNode(mcgraph()->common()->ExternalConstant(ref));
    2624           0 :   Node* call = BuildCCall(&sig, function, stack_slot);
    2625             : 
    2626             :   ZeroCheck32(trap_zero, call, position);
    2627           0 :   TrapIfEq32(wasm::kTrapDivUnrepresentable, call, -1, position);
    2628             :   return SetEffect(graph()->NewNode(mcgraph()->machine()->Load(result_type),
    2629             :                                     stack_slot, mcgraph()->Int32Constant(0),
    2630           0 :                                     Effect(), Control()));
    2631             : }
    2632             : 
    2633             : template <typename... Args>
    2634         185 : Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node* function,
    2635         495 :                                    Args... args) {
    2636             :   DCHECK_LE(sig->return_count(), 1);
    2637             :   DCHECK_EQ(sizeof...(args), sig->parameter_count());
    2638         555 :   Node* const call_args[] = {function, args..., Effect(), Control()};
    2639             : 
    2640             :   auto call_descriptor =
    2641         185 :       Linkage::GetSimplifiedCDescriptor(mcgraph()->zone(), sig);
    2642             : 
    2643         185 :   const Operator* op = mcgraph()->common()->Call(call_descriptor);
    2644         370 :   return SetEffect(graph()->NewNode(op, arraysize(call_args), call_args));
    2645             : }
    2646             : 
    2647      586961 : Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args,
    2648             :                                       Node*** rets,
    2649             :                                       wasm::WasmCodePosition position,
    2650             :                                       Node* instance_node,
    2651      978278 :                                       UseRetpoline use_retpoline) {
    2652      195650 :   if (instance_node == nullptr) {
    2653             :     DCHECK_NOT_NULL(instance_node_);
    2654             :     instance_node = instance_node_.get();
    2655             :   }
    2656      195650 :   needs_stack_check_ = true;
    2657             :   const size_t params = sig->parameter_count();
    2658             :   const size_t extra = 3;  // instance_node, effect, and control.
    2659      195650 :   const size_t count = 1 + params + extra;
    2660             : 
    2661             :   // Reallocate the buffer to make space for extra inputs.
    2662      195650 :   args = Realloc(args, 1 + params, count);
    2663             : 
    2664             :   // Make room for the instance_node parameter at index 1, just after code.
    2665      195653 :   memmove(&args[2], &args[1], params * sizeof(Node*));
    2666      195653 :   args[1] = instance_node;
    2667             : 
    2668             :   // Add effect and control inputs.
    2669      391306 :   args[params + 2] = Effect();
    2670      391306 :   args[params + 3] = Control();
    2671             : 
    2672             :   auto call_descriptor =
    2673      391306 :       GetWasmCallDescriptor(mcgraph()->zone(), sig, use_retpoline);
    2674      195653 :   const Operator* op = mcgraph()->common()->Call(call_descriptor);
    2675      391332 :   Node* call = SetEffect(graph()->NewNode(op, static_cast<int>(count), args));
    2676             :   DCHECK(position == wasm::kNoCodePosition || position > 0);
    2677      195666 :   if (position > 0) SetSourcePosition(call, position);
    2678             : 
    2679             :   size_t ret_count = sig->return_count();
    2680      195661 :   if (ret_count == 0) return call;  // No return value.
    2681             : 
    2682       45660 :   *rets = Buffer(ret_count);
    2683       45660 :   if (ret_count == 1) {
    2684             :     // Only a single return value.
    2685       43602 :     (*rets)[0] = call;
    2686             :   } else {
    2687             :     // Create projections for all return values.
    2688        4134 :     for (size_t i = 0; i < ret_count; i++) {
    2689        4134 :       (*rets)[i] = graph()->NewNode(mcgraph()->common()->Projection(i), call,
    2690        8268 :                                     graph()->start());
    2691             :     }
    2692             :   }
    2693             :   return call;
    2694             : }
    2695             : 
    2696        8672 : Node* WasmGraphBuilder::BuildImportCall(wasm::FunctionSig* sig, Node** args,
    2697             :                                         Node*** rets,
    2698             :                                         wasm::WasmCodePosition position,
    2699      173438 :                                         int func_index) {
    2700             :   // Load the imported function refs array from the instance.
    2701             :   Node* imported_function_refs =
    2702       17342 :       LOAD_INSTANCE_FIELD(ImportedFunctionRefs, MachineType::TaggedPointer());
    2703             :   Node* ref_node =
    2704       17344 :       LOAD_FIXED_ARRAY_SLOT_PTR(imported_function_refs, func_index);
    2705             : 
    2706             :   // Load the target from the imported_targets array at a known offset.
    2707             :   Node* imported_targets =
    2708       17344 :       LOAD_INSTANCE_FIELD(ImportedFunctionTargets, MachineType::Pointer());
    2709             :   Node* target_node = SetEffect(graph()->NewNode(
    2710             :       mcgraph()->machine()->Load(MachineType::Pointer()), imported_targets,
    2711             :       mcgraph()->Int32Constant(func_index * kSystemPointerSize), Effect(),
    2712       26016 :       Control()));
    2713        8672 :   args[0] = target_node;
    2714             :   return BuildWasmCall(sig, args, rets, position, ref_node,
    2715        8672 :                        untrusted_code_mitigations_ ? kRetpoline : kNoRetpoline);
    2716             : }
    2717             : 
    2718         522 : Node* WasmGraphBuilder::BuildImportCall(wasm::FunctionSig* sig, Node** args,
    2719             :                                         Node*** rets,
    2720             :                                         wasm::WasmCodePosition position,
    2721       11484 :                                         Node* func_index) {
    2722             :   // Load the imported function refs array from the instance.
    2723             :   Node* imported_function_refs =
    2724        1044 :       LOAD_INSTANCE_FIELD(ImportedFunctionRefs, MachineType::TaggedPointer());
    2725             :   // Access fixed array at {header_size - tag + func_index * kTaggedSize}.
    2726             :   Node* imported_instances_data = graph()->NewNode(
    2727             :       mcgraph()->machine()->IntAdd(), imported_function_refs,
    2728             :       mcgraph()->IntPtrConstant(
    2729        1044 :           wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(0)));
    2730             :   Node* func_index_times_tagged_size = graph()->NewNode(
    2731             :       mcgraph()->machine()->IntMul(), Uint32ToUintptr(func_index),
    2732        1044 :       mcgraph()->Int32Constant(kTaggedSize));
    2733             :   Node* ref_node = SetEffect(
    2734             :       graph()->NewNode(mcgraph()->machine()->Load(MachineType::TaggedPointer()),
    2735             :                        imported_instances_data, func_index_times_tagged_size,
    2736         522 :                        Effect(), Control()));
    2737             : 
    2738             :   // Load the target from the imported_targets array at the offset of
    2739             :   // {func_index}.
    2740             :   STATIC_ASSERT(kTaggedSize == kSystemPointerSize);
    2741             :   Node* func_index_times_pointersize = func_index_times_tagged_size;
    2742             :   Node* imported_targets =
    2743        1044 :       LOAD_INSTANCE_FIELD(ImportedFunctionTargets, MachineType::Pointer());
    2744             :   Node* target_node = SetEffect(graph()->NewNode(
    2745             :       mcgraph()->machine()->Load(MachineType::Pointer()), imported_targets,
    2746         522 :       func_index_times_pointersize, Effect(), Control()));
    2747         522 :   args[0] = target_node;
    2748             :   return BuildWasmCall(sig, args, rets, position, ref_node,
    2749         522 :                        untrusted_code_mitigations_ ? kRetpoline : kNoRetpoline);
    2750             : }
    2751             : 
    2752       35531 : Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, Node*** rets,
    2753       26859 :                                    wasm::WasmCodePosition position) {
    2754             :   DCHECK_NULL(args[0]);
    2755       71062 :   wasm::FunctionSig* sig = env_->module->functions[index].sig;
    2756             : 
    2757       35531 :   if (env_ && index < env_->module->num_imported_functions) {
    2758             :     // Call to an imported function.
    2759        8672 :     return BuildImportCall(sig, args, rets, position, index);
    2760             :   }
    2761             : 
    2762             :   // A direct call to a wasm function defined in this module.
    2763             :   // Just encode the function index. This will be patched at instantiation.
    2764             :   Address code = static_cast<Address>(index);
    2765       53718 :   args[0] = mcgraph()->RelocatableIntPtrConstant(code, RelocInfo::WASM_CALL);
    2766             : 
    2767       26864 :   return BuildWasmCall(sig, args, rets, position, nullptr, kNoRetpoline);
    2768             : }
    2769             : 
    2770        3965 : Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args,
    2771             :                                      Node*** rets,
    2772      119044 :                                      wasm::WasmCodePosition position) {
    2773             :   DCHECK_NOT_NULL(args[0]);
    2774             :   DCHECK_NOT_NULL(env_);
    2775             : 
    2776             :   // Assume only one table for now.
    2777        7930 :   wasm::FunctionSig* sig = env_->module->signatures[sig_index];
    2778             : 
    2779             :   Node* ift_size =
    2780        7934 :       LOAD_INSTANCE_FIELD(IndirectFunctionTableSize, MachineType::Uint32());
    2781             : 
    2782        3968 :   MachineOperatorBuilder* machine = mcgraph()->machine();
    2783        3968 :   Node* key = args[0];
    2784             : 
    2785             :   // Bounds check against the table size.
    2786        3968 :   Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, ift_size);
    2787        3965 :   TrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position);
    2788             : 
    2789             :   // Mask the key to prevent SSCA.
    2790        3969 :   if (untrusted_code_mitigations_) {
    2791             :     // mask = ((key - size) & ~key) >> 31
    2792             :     Node* neg_key =
    2793           0 :         graph()->NewNode(machine->Word32Xor(), key, Int32Constant(-1));
    2794             :     Node* masked_diff = graph()->NewNode(
    2795             :         machine->Word32And(),
    2796           0 :         graph()->NewNode(machine->Int32Sub(), key, ift_size), neg_key);
    2797             :     Node* mask =
    2798           0 :         graph()->NewNode(machine->Word32Sar(), masked_diff, Int32Constant(31));
    2799           0 :     key = graph()->NewNode(machine->Word32And(), key, mask);
    2800             :   }
    2801             : 
    2802             :   // Load signature from the table and check.
    2803             :   Node* ift_sig_ids =
    2804        7934 :       LOAD_INSTANCE_FIELD(IndirectFunctionTableSigIds, MachineType::Pointer());
    2805             : 
    2806        7938 :   int32_t expected_sig_id = env_->module->signature_ids[sig_index];
    2807             :   Node* int32_scaled_key = Uint32ToUintptr(
    2808        7934 :       graph()->NewNode(machine->Word32Shl(), key, Int32Constant(2)));
    2809             : 
    2810             :   Node* loaded_sig = SetEffect(
    2811             :       graph()->NewNode(machine->Load(MachineType::Int32()), ift_sig_ids,
    2812        3969 :                        int32_scaled_key, Effect(), Control()));
    2813             :   Node* sig_match = graph()->NewNode(machine->WordEqual(), loaded_sig,
    2814        3969 :                                      Int32Constant(expected_sig_id));
    2815             : 
    2816        3969 :   TrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position);
    2817             : 
    2818             :   Node* ift_targets =
    2819        7938 :       LOAD_INSTANCE_FIELD(IndirectFunctionTableTargets, MachineType::Pointer());
    2820        7934 :   Node* ift_instances = LOAD_INSTANCE_FIELD(IndirectFunctionTableRefs,
    2821             :                                             MachineType::TaggedPointer());
    2822             : 
    2823             :   Node* intptr_scaled_key = graph()->NewNode(
    2824        3969 :       machine->Word32Shl(), key, Int32Constant(kSystemPointerSizeLog2));
    2825             : 
    2826             :   Node* target = SetEffect(
    2827             :       graph()->NewNode(machine->Load(MachineType::Pointer()), ift_targets,
    2828        3969 :                        intptr_scaled_key, Effect(), Control()));
    2829             : 
    2830             :   STATIC_ASSERT(kTaggedSize == kSystemPointerSize);
    2831             :   Node* tagged_scaled_key = intptr_scaled_key;
    2832             : 
    2833             :   Node* target_instance = SetEffect(graph()->NewNode(
    2834             :       machine->Load(MachineType::TaggedPointer()),
    2835             :       graph()->NewNode(machine->IntAdd(), ift_instances, tagged_scaled_key),
    2836             :       Int32Constant(wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(0)),
    2837        7938 :       Effect(), Control()));
    2838             : 
    2839        3969 :   args[0] = target;
    2840             : 
    2841             :   return BuildWasmCall(sig, args, rets, position, target_instance,
    2842        3969 :                        untrusted_code_mitigations_ ? kRetpoline : kNoRetpoline);
    2843             : }
    2844             : 
    2845       67328 : Node* WasmGraphBuilder::BuildI32Rol(Node* left, Node* right) {
    2846             :   // Implement Rol by Ror since TurboFan does not have Rol opcode.
    2847             :   // TODO(weiliang): support Word32Rol opcode in TurboFan.
    2848             :   Int32Matcher m(right);
    2849       33664 :   if (m.HasValue()) {
    2850             :     return Binop(wasm::kExprI32Ror, left,
    2851       67280 :                  mcgraph()->Int32Constant(32 - (m.Value() & 0x1F)));
    2852             :   } else {
    2853             :     return Binop(wasm::kExprI32Ror, left,
    2854          24 :                  Binop(wasm::kExprI32Sub, mcgraph()->Int32Constant(32), right));
    2855             :   }
    2856             : }
    2857             : 
    2858         196 : Node* WasmGraphBuilder::BuildI64Rol(Node* left, Node* right) {
    2859             :   // Implement Rol by Ror since TurboFan does not have Rol opcode.
    2860             :   // TODO(weiliang): support Word64Rol opcode in TurboFan.
    2861             :   Int64Matcher m(right);
    2862          98 :   if (m.HasValue()) {
    2863             :     return Binop(wasm::kExprI64Ror, left,
    2864          60 :                  mcgraph()->Int64Constant(64 - (m.Value() & 0x3F)));
    2865             :   } else {
    2866             :     return Binop(wasm::kExprI64Ror, left,
    2867          68 :                  Binop(wasm::kExprI64Sub, mcgraph()->Int64Constant(64), right));
    2868             :   }
    2869             : }
    2870             : 
    2871       76873 : Node* WasmGraphBuilder::Invert(Node* node) {
    2872       76873 :   return Unop(wasm::kExprI32Eqz, node);
    2873             : }
    2874             : 
    2875           0 : bool CanCover(Node* value, IrOpcode::Value opcode) {
    2876           0 :   if (value->opcode() != opcode) return false;
    2877             :   bool first = true;
    2878           0 :   for (Edge const edge : value->use_edges()) {
    2879           0 :     if (NodeProperties::IsControlEdge(edge)) continue;
    2880           0 :     if (NodeProperties::IsEffectEdge(edge)) continue;
    2881             :     DCHECK(NodeProperties::IsValueEdge(edge));
    2882           0 :     if (!first) return false;
    2883             :     first = false;
    2884             :   }
    2885           0 :   return true;
    2886             : }
    2887             : 
    2888       73434 : Node* WasmGraphBuilder::BuildChangeInt32ToIntPtr(Node* value) {
    2889      146868 :   if (mcgraph()->machine()->Is64()) {
    2890       73436 :     value = graph()->NewNode(mcgraph()->machine()->ChangeInt32ToInt64(), value);
    2891             :   }
    2892       73434 :   return value;
    2893             : }
    2894             : 
    2895      146872 : Node* WasmGraphBuilder::BuildChangeInt32ToSmi(Node* value) {
    2896       73432 :   value = BuildChangeInt32ToIntPtr(value);
    2897             :   return graph()->NewNode(mcgraph()->machine()->WordShl(), value,
    2898      146879 :                           BuildSmiShiftBitsConstant());
    2899             : }
    2900             : 
    2901        2967 : Node* WasmGraphBuilder::BuildChangeUint31ToSmi(Node* value) {
    2902             :   return graph()->NewNode(mcgraph()->machine()->WordShl(),
    2903        4451 :                           Uint32ToUintptr(value), BuildSmiShiftBitsConstant());
    2904             : }
    2905             : 
    2906      326641 : Node* WasmGraphBuilder::BuildSmiShiftBitsConstant() {
    2907      326641 :   return mcgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize);
    2908             : }
    2909             : 
    2910      755182 : Node* WasmGraphBuilder::BuildChangeSmiToInt32(Node* value) {
    2911             :   value = graph()->NewNode(mcgraph()->machine()->WordSar(), value,
    2912      251730 :                            BuildSmiShiftBitsConstant());
    2913      503462 :   if (mcgraph()->machine()->Is64()) {
    2914             :     value =
    2915      251726 :         graph()->NewNode(mcgraph()->machine()->TruncateInt64ToInt32(), value);
    2916             :   }
    2917      251733 :   return value;
    2918             : }
    2919             : 
    2920         243 : Node* WasmGraphBuilder::BuildConvertUint32ToSmiWithSaturation(Node* value,
    2921         972 :                                                               uint32_t maxval) {
    2922             :   DCHECK(Smi::IsValid(maxval));
    2923             :   Node* max = Uint32Constant(maxval);
    2924             :   Node* check = graph()->NewNode(mcgraph()->machine()->Uint32LessThanOrEqual(),
    2925         243 :                                  value, max);
    2926         243 :   Node* valsmi = BuildChangeUint31ToSmi(value);
    2927         486 :   Node* maxsmi = graph()->NewNode(mcgraph()->common()->NumberConstant(maxval));
    2928         486 :   Diamond d(graph(), mcgraph()->common(), check, BranchHint::kTrue);
    2929         243 :   d.Chain(Control());
    2930         243 :   return d.Phi(MachineRepresentation::kTagged, valsmi, maxsmi);
    2931             : }
    2932             : 
    2933     1108239 : void WasmGraphBuilder::InitInstanceCache(
    2934    11083156 :     WasmInstanceCacheNodes* instance_cache) {
    2935             :   DCHECK_NOT_NULL(instance_node_);
    2936             : 
    2937             :   // Load the memory start.
    2938             :   instance_cache->mem_start = SetEffect(graph()->NewNode(
    2939             :       mcgraph()->machine()->Load(MachineType::UintPtr()), instance_node_.get(),
    2940             :       mcgraph()->Int32Constant(WASM_INSTANCE_OBJECT_OFFSET(MemoryStart)),
    2941     3324849 :       Effect(), Control()));
    2942             : 
    2943             :   // Load the memory size.
    2944             :   instance_cache->mem_size = SetEffect(graph()->NewNode(
    2945             :       mcgraph()->machine()->Load(MachineType::UintPtr()), instance_node_.get(),
    2946             :       mcgraph()->Int32Constant(WASM_INSTANCE_OBJECT_OFFSET(MemorySize)),
    2947     3325055 :       Effect(), Control()));
    2948             : 
    2949     1108297 :   if (untrusted_code_mitigations_) {
    2950             :     // Load the memory mask.
    2951             :     instance_cache->mem_mask =
    2952           0 :         LOAD_INSTANCE_FIELD(MemoryMask, MachineType::UintPtr());
    2953             :   } else {
    2954             :     // Explicitly set to nullptr to ensure a SEGV when we try to use it.
    2955     1108297 :     instance_cache->mem_mask = nullptr;
    2956             :   }
    2957     1108297 : }
    2958             : 
    2959        4911 : void WasmGraphBuilder::PrepareInstanceCacheForLoop(
    2960        9822 :     WasmInstanceCacheNodes* instance_cache, Node* control) {
    2961             : #define INTRODUCE_PHI(field, rep)                                            \
    2962             :   instance_cache->field = graph()->NewNode(mcgraph()->common()->Phi(rep, 1), \
    2963             :                                            instance_cache->field, control);
    2964             : 
    2965       14733 :   INTRODUCE_PHI(mem_start, MachineType::PointerRepresentation());
    2966       14733 :   INTRODUCE_PHI(mem_size, MachineType::PointerRepresentation());
    2967        4911 :   if (untrusted_code_mitigations_) {
    2968           0 :     INTRODUCE_PHI(mem_mask, MachineType::PointerRepresentation());
    2969             :   }
    2970             : 
    2971             : #undef INTRODUCE_PHI
    2972        4911 : }
    2973             : 
    2974       46261 : void WasmGraphBuilder::NewInstanceCacheMerge(WasmInstanceCacheNodes* to,
    2975             :                                              WasmInstanceCacheNodes* from,
    2976       29869 :                                              Node* merge) {
    2977             : #define INTRODUCE_PHI(field, rep)                                            \
    2978             :   if (to->field != from->field) {                                            \
    2979             :     Node* vals[] = {to->field, from->field, merge};                          \
    2980             :     to->field = graph()->NewNode(mcgraph()->common()->Phi(rep, 2), 3, vals); \
    2981             :   }
    2982             : 
    2983       76130 :   INTRODUCE_PHI(mem_start, MachineType::PointerRepresentation());
    2984       76132 :   INTRODUCE_PHI(mem_size, MachineRepresentation::kWord32);
    2985       46262 :   if (untrusted_code_mitigations_) {
    2986           0 :     INTRODUCE_PHI(mem_mask, MachineRepresentation::kWord32);
    2987             :   }
    2988             : 
    2989             : #undef INTRODUCE_PHI
    2990       46262 : }
    2991             : 
    2992      242282 : void WasmGraphBuilder::MergeInstanceCacheInto(WasmInstanceCacheNodes* to,
    2993             :                                               WasmInstanceCacheNodes* from,
    2994             :                                               Node* merge) {
    2995             :   to->mem_size = CreateOrMergeIntoPhi(MachineType::PointerRepresentation(),
    2996      242282 :                                       merge, to->mem_size, from->mem_size);
    2997             :   to->mem_start = CreateOrMergeIntoPhi(MachineType::PointerRepresentation(),
    2998      242282 :                                        merge, to->mem_start, from->mem_start);
    2999      242283 :   if (untrusted_code_mitigations_) {
    3000             :     to->mem_mask = CreateOrMergeIntoPhi(MachineType::PointerRepresentation(),
    3001           0 :                                         merge, to->mem_mask, from->mem_mask);
    3002             :   }
    3003      242283 : }
    3004             : 
    3005     1138698 : Node* WasmGraphBuilder::CreateOrMergeIntoPhi(MachineRepresentation rep,
    3006             :                                              Node* merge, Node* tnode,
    3007       15608 :                                              Node* fnode) {
    3008     1138698 :   if (IsPhiWithMerge(tnode, merge)) {
    3009      110804 :     AppendToPhi(tnode, fnode);
    3010     1027905 :   } else if (tnode != fnode) {
    3011       15607 :     uint32_t count = merge->InputCount();
    3012             :     // + 1 for the merge node.
    3013       15607 :     Node** vals = Buffer(count + 1);
    3014       15608 :     for (uint32_t j = 0; j < count - 1; j++) vals[j] = tnode;
    3015       15608 :     vals[count - 1] = fnode;
    3016       15608 :     vals[count] = merge;
    3017             :     return graph()->NewNode(mcgraph()->common()->Phi(rep, count), count + 1,
    3018       46823 :                             vals);
    3019             :   }
    3020     1123104 :   return tnode;
    3021             : }
    3022             : 
    3023      242279 : Node* WasmGraphBuilder::CreateOrMergeIntoEffectPhi(Node* merge, Node* tnode,
    3024             :                                                    Node* fnode) {
    3025      242279 :   if (IsPhiWithMerge(tnode, merge)) {
    3026       15757 :     AppendToPhi(tnode, fnode);
    3027      226524 :   } else if (tnode != fnode) {
    3028         146 :     uint32_t count = merge->InputCount();
    3029         146 :     Node** effects = Buffer(count);
    3030         568 :     for (uint32_t j = 0; j < count - 1; j++) {
    3031         422 :       effects[j] = tnode;
    3032             :     }
    3033         146 :     effects[count - 1] = fnode;
    3034         146 :     tnode = EffectPhi(count, effects, merge);
    3035             :   }
    3036      242281 :   return tnode;
    3037             : }
    3038             : 
    3039         538 : Node* WasmGraphBuilder::GetImportedMutableGlobals() {
    3040         278 :   if (imported_mutable_globals_ == nullptr) {
    3041             :     // Load imported_mutable_globals_ from the instance object at runtime.
    3042         520 :     imported_mutable_globals_ = graph()->NewNode(
    3043             :         mcgraph()->machine()->Load(MachineType::UintPtr()),
    3044             :         instance_node_.get(),
    3045             :         mcgraph()->Int32Constant(
    3046             :             WASM_INSTANCE_OBJECT_OFFSET(ImportedMutableGlobals)),
    3047             :         graph()->start(), graph()->start());
    3048             :   }
    3049         279 :   return imported_mutable_globals_.get();
    3050             : }
    3051             : 
    3052       86022 : void WasmGraphBuilder::GetGlobalBaseAndOffset(MachineType mem_type,
    3053             :                                               const wasm::WasmGlobal& global,
    3054             :                                               Node** base_node,
    3055      148975 :                                               Node** offset_node) {
    3056             :   DCHECK_NOT_NULL(instance_node_);
    3057       86022 :   if (global.mutability && global.imported) {
    3058             :     *base_node = SetEffect(graph()->NewNode(
    3059             :         mcgraph()->machine()->Load(MachineType::UintPtr()),
    3060             :         GetImportedMutableGlobals(),
    3061             :         mcgraph()->Int32Constant(global.index * sizeof(Address)), Effect(),
    3062         612 :         Control()));
    3063         153 :     *offset_node = mcgraph()->Int32Constant(0);
    3064             :   } else {
    3065       85869 :     if (globals_start_ == nullptr) {
    3066             :       // Load globals_start from the instance object at runtime.
    3067             :       // TODO(wasm): we currently generate only one load of the {globals_start}
    3068             :       // start per graph, which means it can be placed anywhere by the
    3069             :       // scheduler. This is legal because the globals_start should never change.
    3070             :       // However, in some cases (e.g. if the instance object is already in a
    3071             :       // register), it is slightly more efficient to reload this value from the
    3072             :       // instance object. Since this depends on register allocation, it is not
    3073             :       // possible to express in the graph, and would essentially constitute a
    3074             :       // "mem2reg" optimization in TurboFan.
    3075       32651 :       globals_start_ = graph()->NewNode(
    3076             :           mcgraph()->machine()->Load(MachineType::UintPtr()),
    3077             :           instance_node_.get(),
    3078             :           mcgraph()->Int32Constant(WASM_INSTANCE_OBJECT_OFFSET(GlobalsStart)),
    3079             :           graph()->start(), graph()->start());
    3080             :     }
    3081       85871 :     *base_node = globals_start_.get();
    3082      171742 :     *offset_node = mcgraph()->Int32Constant(global.offset);
    3083             : 
    3084       85872 :     if (mem_type == MachineType::Simd128() && global.offset != 0) {
    3085             :       // TODO(titzer,bbudge): code generation for SIMD memory offsets is broken.
    3086             :       *base_node = graph()->NewNode(mcgraph()->machine()->IntAdd(), *base_node,
    3087       68790 :                                     *offset_node);
    3088       22930 :       *offset_node = mcgraph()->Int32Constant(0);
    3089             :     }
    3090             :   }
    3091       86025 : }
    3092             : 
    3093         126 : void WasmGraphBuilder::GetBaseAndOffsetForImportedMutableAnyRefGlobal(
    3094        2394 :     const wasm::WasmGlobal& global, Node** base, Node** offset) {
    3095             :   // Load the base from the ImportedMutableGlobalsBuffer of the instance.
    3096         252 :   Node* buffers = LOAD_INSTANCE_FIELD(ImportedMutableGlobalsBuffers,
    3097             :                                       MachineType::TaggedPointer());
    3098         504 :   *base = LOAD_FIXED_ARRAY_SLOT_ANY(buffers, global.index);
    3099             : 
    3100             :   // For the offset we need the index of the global in the buffer, and then
    3101             :   // calculate the actual offset from the index. Load the index from the
    3102             :   // ImportedMutableGlobals array of the instance.
    3103             :   Node* index = SetEffect(
    3104             :       graph()->NewNode(mcgraph()->machine()->Load(MachineType::UintPtr()),
    3105             :                        GetImportedMutableGlobals(),
    3106             :                        mcgraph()->Int32Constant(global.index * sizeof(Address)),
    3107         378 :                        Effect(), Control()));
    3108             : 
    3109             :   // From the index, calculate the actual offset in the FixeArray. This
    3110             :   // is kHeaderSize + (index * kTaggedSize). kHeaderSize can be acquired with
    3111             :   // wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(0).
    3112             :   Node* index_times_tagged_size =
    3113             :       graph()->NewNode(mcgraph()->machine()->IntMul(), Uint32ToUintptr(index),
    3114         252 :                        mcgraph()->Int32Constant(kTaggedSize));
    3115             :   *offset = graph()->NewNode(
    3116             :       mcgraph()->machine()->IntAdd(), index_times_tagged_size,
    3117             :       mcgraph()->IntPtrConstant(
    3118         378 :           wasm::ObjectAccess::ElementOffsetInTaggedFixedArray(0)));
    3119         126 : }
    3120             : 
    3121      594748 : Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
    3122             :   DCHECK_NOT_NULL(instance_cache_);
    3123      494451 :   Node* mem_start = instance_cache_->mem_start;
    3124             :   DCHECK_NOT_NULL(mem_start);
    3125      494451 :   if (offset == 0) return mem_start;
    3126             :   return graph()->NewNode(mcgraph()->machine()->IntAdd(), mem_start,
    3127      200596 :                           mcgraph()->IntPtrConstant(offset));
    3128             : }
    3129             : 
    3130        1656 : Node* WasmGraphBuilder::CurrentMemoryPages() {
    3131             :   // CurrentMemoryPages can not be called from asm.js.
    3132             :   DCHECK_EQ(wasm::kWasmOrigin, env_->module->origin);
    3133             :   DCHECK_NOT_NULL(instance_cache_);
    3134         414 :   Node* mem_size = instance_cache_->mem_size;
    3135             :   DCHECK_NOT_NULL(mem_size);
    3136             :   Node* result =
    3137             :       graph()->NewNode(mcgraph()->machine()->WordShr(), mem_size,
    3138         828 :                        mcgraph()->Int32Constant(wasm::kWasmPageSizeLog2));
    3139         828 :   if (mcgraph()->machine()->Is64()) {
    3140             :     result =
    3141         414 :         graph()->NewNode(mcgraph()->machine()->TruncateInt64ToInt32(), result);
    3142             :   }
    3143         414 :   return result;
    3144             : }
    3145             : 
    3146        5410 : Node* WasmGraphBuilder::BuildLoadBuiltinFromInstance(int builtin_index) {
    3147             :   DCHECK(Builtins::IsBuiltinId(builtin_index));
    3148        1082 :   Node* isolate_root = LOAD_INSTANCE_FIELD(IsolateRoot, MachineType::Pointer());
    3149        1623 :   return LOAD_TAGGED_POINTER(isolate_root,
    3150             :                              IsolateData::builtin_slot_offset(builtin_index));
    3151             : }
    3152             : 
    3153             : // Only call this function for code which is not reused across instantiations,
    3154             : // as we do not patch the embedded js_context.
    3155        4219 : Node* WasmGraphBuilder::BuildCallToRuntimeWithContext(
    3156             :     Runtime::FunctionId f, Node* js_context, Node** parameters,
    3157       42228 :     int parameter_count, Node** effect, Node* control) {
    3158        4219 :   const Runtime::Function* fun = Runtime::FunctionForId(f);
    3159             :   auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
    3160             :       mcgraph()->zone(), f, fun->nargs, Operator::kNoProperties,
    3161        8438 :       CallDescriptor::kNoFlags);
    3162             :   // The CEntryStub is loaded from the instance_node so that generated code is
    3163             :   // Isolate independent. At the moment this is only done for CEntryStub(1).
    3164             :   DCHECK_EQ(1, fun->result_size);
    3165             :   Node* centry_stub =
    3166        8447 :       LOAD_INSTANCE_FIELD(CEntryStub, MachineType::TaggedPointer());
    3167             :   // TODO(titzer): allow arbitrary number of runtime arguments
    3168             :   // At the moment we only allow 5 parameters. If more parameters are needed,
    3169             :   // increase this constant accordingly.
    3170             :   static const int kMaxParams = 5;
    3171             :   DCHECK_GE(kMaxParams, parameter_count);
    3172             :   Node* inputs[kMaxParams + 6];
    3173             :   int count = 0;
    3174        4225 :   inputs[count++] = centry_stub;
    3175        9537 :   for (int i = 0; i < parameter_count; i++) {
    3176        5312 :     inputs[count++] = parameters[i];
    3177             :   }
    3178        4225 :   inputs[count++] =
    3179        8448 :       mcgraph()->ExternalConstant(ExternalReference::Create(f));  // ref
    3180        8444 :   inputs[count++] = mcgraph()->Int32Constant(fun->nargs);         // arity
    3181        4223 :   inputs[count++] = js_context;                                   // js_context
    3182        4223 :   inputs[count++] = *effect;
    3183        4223 :   inputs[count++] = control;
    3184             : 
    3185             :   Node* call = mcgraph()->graph()->NewNode(
    3186        8446 :       mcgraph()->common()->Call(call_descriptor), count, inputs);
    3187        4225 :   *effect = call;
    3188        4225 :   return call;
    3189             : }
    3190             : 
    3191        3267 : Node* WasmGraphBuilder::BuildCallToRuntime(Runtime::FunctionId f,
    3192             :                                            Node** parameters,
    3193        3267 :                                            int parameter_count) {
    3194             :   return BuildCallToRuntimeWithContext(f, NoContextConstant(), parameters,
    3195        6534 :                                        parameter_count, effect_, Control());
    3196             : }
    3197             : 
    3198      319234 : Node* WasmGraphBuilder::GetGlobal(uint32_t index) {
    3199      127114 :   const wasm::WasmGlobal& global = env_->module->globals[index];
    3200       63674 :   if (global.type == wasm::ValueType::kWasmAnyRef) {
    3201         234 :     if (global.mutability && global.imported) {
    3202          90 :       Node* base = nullptr;
    3203          90 :       Node* offset = nullptr;
    3204          90 :       GetBaseAndOffsetForImportedMutableAnyRefGlobal(global, &base, &offset);
    3205             :       return SetEffect(
    3206             :           graph()->NewNode(mcgraph()->machine()->Load(MachineType::AnyTagged()),
    3207         180 :                            base, offset, Effect(), Control()));
    3208             :     }
    3209             :     Node* globals_buffer =
    3210         288 :         LOAD_INSTANCE_FIELD(TaggedGlobalsBuffer, MachineType::TaggedPointer());
    3211         576 :     return LOAD_FIXED_ARRAY_SLOT_ANY(globals_buffer, global.offset);
    3212             :   }
    3213             : 
    3214             :   MachineType mem_type =
    3215       63440 :       wasm::ValueTypes::MachineTypeFor(env_->module->globals[index].type);
    3216       63440 :   Node* base = nullptr;
    3217       63440 :   Node* offset = nullptr;
    3218       63440 :   GetGlobalBaseAndOffset(mem_type, env_->module->globals[index], &base,
    3219       63440 :                          &offset);
    3220             :   Node* result = SetEffect(graph()->NewNode(
    3221      126880 :       mcgraph()->machine()->Load(mem_type), base, offset, Effect(), Control()));
    3222             : #if defined(V8_TARGET_BIG_ENDIAN)
    3223             :   result = BuildChangeEndiannessLoad(result, mem_type,
    3224             :                                      env_->module->globals[index].type);
    3225             : #endif
    3226       63440 :   return result;
    3227             : }
    3228             : 
    3229      114194 : Node* WasmGraphBuilder::SetGlobal(uint32_t index, Node* val) {
    3230       45404 :   const wasm::WasmGlobal& global = env_->module->globals[index];
    3231       22720 :   if (global.type == wasm::ValueType::kWasmAnyRef) {
    3232         135 :     if (global.mutability && global.imported) {
    3233          36 :       Node* base = nullptr;
    3234          36 :       Node* offset = nullptr;
    3235          36 :       GetBaseAndOffsetForImportedMutableAnyRefGlobal(global, &base, &offset);
    3236             : 
    3237             :       return SetEffect(graph()->NewNode(
    3238             :           mcgraph()->machine()->Store(StoreRepresentation(
    3239             :               MachineRepresentation::kTagged, kFullWriteBarrier)),
    3240         108 :           base, offset, val, Effect(), Control()));
    3241             :     }
    3242             :     Node* globals_buffer =
    3243         198 :         LOAD_INSTANCE_FIELD(TaggedGlobalsBuffer, MachineType::TaggedPointer());
    3244         495 :     return STORE_FIXED_ARRAY_SLOT_ANY(globals_buffer,
    3245             :                                       env_->module->globals[index].offset, val);
    3246             :   }
    3247             : 
    3248             :   MachineType mem_type =
    3249       22585 :       wasm::ValueTypes::MachineTypeFor(env_->module->globals[index].type);
    3250       22585 :   Node* base = nullptr;
    3251       22585 :   Node* offset = nullptr;
    3252       22585 :   GetGlobalBaseAndOffset(mem_type, env_->module->globals[index], &base,
    3253       22585 :                          &offset);
    3254             :   const Operator* op = mcgraph()->machine()->Store(
    3255       45170 :       StoreRepresentation(mem_type.representation(), kNoWriteBarrier));
    3256             : #if defined(V8_TARGET_BIG_ENDIAN)
    3257             :   val = BuildChangeEndiannessStore(val, mem_type.representation(),
    3258             :                                    env_->module->globals[index].type);
    3259             : #endif
    3260             :   return SetEffect(
    3261       45170 :       graph()->NewNode(op, base, offset, val, Effect(), Control()));
    3262             : }
    3263             : 
    3264       33518 : Node* WasmGraphBuilder::CheckBoundsAndAlignment(
    3265             :     uint8_t access_size, Node* index, uint32_t offset,
    3266       20756 :     wasm::WasmCodePosition position) {
    3267             :   // Atomic operations need bounds checks until the backend can emit protected
    3268             :   // loads.
    3269             :   index =
    3270       33518 :       BoundsCheckMem(access_size, index, offset, position, kNeedsBoundsCheck);
    3271             : 
    3272       33554 :   const uintptr_t align_mask = access_size - 1;
    3273             : 
    3274             :   // Don't emit an alignment check if the index is a constant.
    3275             :   // TODO(wasm): a constant match is also done above in {BoundsCheckMem}.
    3276             :   UintPtrMatcher match(index);
    3277       33554 :   if (match.HasValue()) {
    3278       28379 :     uintptr_t effective_offset = match.Value() + offset;
    3279       28379 :     if ((effective_offset & align_mask) != 0) {
    3280             :       // statically known to be unaligned; trap.
    3281           0 :       TrapIfEq32(wasm::kTrapUnalignedAccess, Int32Constant(0), 0, position);
    3282             :     }
    3283             :     return index;
    3284             :   }
    3285             : 
    3286             :   // Unlike regular memory accesses, atomic memory accesses should trap if
    3287             :   // the effective offset is misaligned.
    3288             :   // TODO(wasm): this addition is redundant with one inserted by {MemBuffer}.
    3289             :   Node* effective_offset = graph()->NewNode(mcgraph()->machine()->IntAdd(),
    3290       10368 :                                             MemBuffer(offset), index);
    3291             : 
    3292             :   Node* cond = graph()->NewNode(mcgraph()->machine()->WordAnd(),
    3293       10400 :                                 effective_offset, IntPtrConstant(align_mask));
    3294             :   TrapIfFalse(wasm::kTrapUnalignedAccess,
    3295             :               graph()->NewNode(mcgraph()->machine()->Word32Equal(), cond,
    3296             :                                mcgraph()->Int32Constant(0)),
    3297       15541 :               position);
    3298        5179 :   return index;
    3299             : }
    3300             : 
    3301             : // Insert code to bounds check a memory access if necessary. Return the
    3302             : // bounds-checked index, which is guaranteed to have (the equivalent of)
    3303             : // {uintptr_t} representation.
    3304      489919 : Node* WasmGraphBuilder::BoundsCheckMem(uint8_t access_size, Node* index,
    3305             :                                        uint32_t offset,
    3306             :                                        wasm::WasmCodePosition position,
    3307      523448 :                                        EnforceBoundsCheck enforce_check) {
    3308             :   DCHECK_LE(1, access_size);
    3309      489919 :   index = Uint32ToUintptr(index);
    3310      489890 :   if (FLAG_wasm_no_bounds_checks) return index;
    3311             : 
    3312      489912 :   if (use_trap_handler() && enforce_check == kCanOmitBoundsCheck) {
    3313             :     return index;
    3314             :   }
    3315             : 
    3316       67050 :   if (!IsInBounds(offset, access_size, env_->max_memory_size)) {
    3317             :     // The access will be out of bounds, even for the largest memory.
    3318          18 :     TrapIfEq32(wasm::kTrapMemOutOfBounds, Int32Constant(0), 0, position);
    3319          18 :     return mcgraph()->IntPtrConstant(0);
    3320             :   }
    3321       33507 :   uint64_t end_offset = uint64_t{offset} + access_size - 1u;
    3322       33507 :   Node* end_offset_node = IntPtrConstant(end_offset);
    3323             : 
    3324             :   // The accessed memory is [index + offset, index + end_offset].
    3325             :   // Check that the last read byte (at {index + end_offset}) is in bounds.
    3326             :   // 1) Check that {end_offset < mem_size}. This also ensures that we can safely
    3327             :   //    compute {effective_size} as {mem_size - end_offset)}.
    3328             :   //    {effective_size} is >= 1 if condition 1) holds.
    3329             :   // 2) Check that {index + end_offset < mem_size} by
    3330             :   //    - computing {effective_size} as {mem_size - end_offset} and
    3331             :   //    - checking that {index < effective_size}.
    3332             : 
    3333       33518 :   auto m = mcgraph()->machine();
    3334       33518 :   Node* mem_size = instance_cache_->mem_size;
    3335       33518 :   if (end_offset >= env_->min_memory_size) {
    3336             :     // The end offset is larger than the smallest memory.
    3337             :     // Dynamically check the end offset against the dynamic memory size.
    3338        6502 :     Node* cond = graph()->NewNode(m->UintLessThan(), end_offset_node, mem_size);
    3339        6513 :     TrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position);
    3340             :   } else {
    3341             :     // The end offset is smaller than the smallest memory, so only one check is
    3342             :     // required. Check to see if the index is also a constant.
    3343             :     UintPtrMatcher match(index);
    3344       27016 :     if (match.HasValue()) {
    3345             :       uintptr_t index_val = match.Value();
    3346       26997 :       if (index_val < env_->min_memory_size - end_offset) {
    3347             :         // The input index is a constant and everything is statically within
    3348             :         // bounds of the smallest possible memory.
    3349             :         return index;
    3350             :       }
    3351             :     }
    3352             :   }
    3353             : 
    3354             :   // This produces a positive number, since {end_offset < min_size <= mem_size}.
    3355             :   Node* effective_size =
    3356        6537 :       graph()->NewNode(m->IntSub(), mem_size, end_offset_node);
    3357             : 
    3358             :   // Introduce the actual bounds check.
    3359        6537 :   Node* cond = graph()->NewNode(m->UintLessThan(), index, effective_size);
    3360        6536 :   TrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position);
    3361             : 
    3362        6555 :   if (untrusted_code_mitigations_) {
    3363             :     // In the fallthrough case, condition the index with the memory mask.
    3364           0 :     Node* mem_mask = instance_cache_->mem_mask;
    3365             :     DCHECK_NOT_NULL(mem_mask);
    3366           0 :     index = graph()->NewNode(m->WordAnd(), index, mem_mask);
    3367             :   }
    3368        6555 :   return index;
    3369             : }
    3370             : 
    3371             : // Check that the range [start, start + size) is in the range [0, max).
    3372         171 : void WasmGraphBuilder::BoundsCheckRange(Node* start, Node* size, Node* max,
    3373         171 :                                         wasm::WasmCodePosition position) {
    3374             :   // The accessed memory is [start, end), where {end} is {start + size}. We
    3375             :   // want to check that {start + size <= max}, making sure that {start + size}
    3376             :   // doesn't overflow. This can be expressed as {start <= max - size} as long
    3377             :   // as {max - size} isn't negative, which is true if {size <= max}.
    3378         171 :   auto m = mcgraph()->machine();
    3379         171 :   Node* cond = graph()->NewNode(m->Uint32LessThanOrEqual(), size, max);
    3380         171 :   TrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position);
    3381             : 
    3382             :   // This produces a positive number, since {size <= max}.
    3383         171 :   Node* effective_size = graph()->NewNode(m->Int32Sub(), max, size);
    3384             : 
    3385             :   // Introduce the actual bounds check.
    3386             :   Node* check =
    3387         171 :       graph()->NewNode(m->Uint32LessThanOrEqual(), start, effective_size);
    3388         171 :   TrapIfFalse(wasm::kTrapMemOutOfBounds, check, position);
    3389             : 
    3390             :   // TODO(binji): Does this need addtional untrusted_code_mitigations_ mask
    3391             :   // like BoundsCheckMem above?
    3392         171 : }
    3393             : 
    3394         126 : Node* WasmGraphBuilder::BoundsCheckMemRange(Node* start, Node* size,
    3395         126 :                                             wasm::WasmCodePosition position) {
    3396             :   // TODO(binji): Support trap handler.
    3397         126 :   if (!FLAG_wasm_no_bounds_checks) {
    3398         126 :     BoundsCheckRange(start, size, instance_cache_->mem_size, position);
    3399             :   }
    3400             :   return graph()->NewNode(mcgraph()->machine()->IntAdd(), MemBuffer(0),
    3401         378 :                           Uint32ToUintptr(start));
    3402             : }
    3403             : 
    3404         806 : const Operator* WasmGraphBuilder::GetSafeLoadOperator(int offset,
    3405         811 :                                                       wasm::ValueType type) {
    3406         806 :   int alignment = offset % (wasm::ValueTypes::ElementSizeInBytes(type));
    3407         806 :   MachineType mach_type = wasm::ValueTypes::MachineTypeFor(type);
    3408         811 :   if (alignment == 0 || mcgraph()->machine()->UnalignedLoadSupported(
    3409          10 :                             wasm::ValueTypes::MachineRepresentationFor(type))) {
    3410         806 :     return mcgraph()->machine()->Load(mach_type);
    3411             :   }
    3412           0 :   return mcgraph()->machine()->UnalignedLoad(mach_type);
    3413             : }
    3414             : 
    3415        1002 : const Operator* WasmGraphBuilder::GetSafeStoreOperator(int offset,
    3416        1016 :                                                        wasm::ValueType type) {
    3417        1002 :   int alignment = offset % (wasm::ValueTypes::ElementSizeInBytes(type));
    3418        1002 :   MachineRepresentation rep = wasm::ValueTypes::MachineRepresentationFor(type);
    3419        1030 :   if (alignment == 0 || mcgraph()->machine()->UnalignedStoreSupported(rep)) {
    3420             :     StoreRepresentation store_rep(rep, WriteBarrierKind::kNoWriteBarrier);
    3421        1002 :     return mcgraph()->machine()->Store(store_rep);
    3422             :   }
    3423             :   UnalignedStoreRepresentation store_rep(rep);
    3424           0 :   return mcgraph()->machine()->UnalignedStore(store_rep);
    3425             : }
    3426             : 
    3427          48 : Node* WasmGraphBuilder::TraceMemoryOperation(bool is_store,
    3428             :                                              MachineRepresentation rep,
    3429             :                                              Node* index, uint32_t offset,
    3430         197 :                                              wasm::WasmCodePosition position) {
    3431             :   int kAlign = 4;  // Ensure that the LSB is 0, such that this looks like a Smi.
    3432             :   Node* info = graph()->NewNode(
    3433          96 :       mcgraph()->machine()->StackSlot(sizeof(wasm::MemoryTracingInfo), kAlign));
    3434             : 
    3435             :   Node* address = graph()->NewNode(mcgraph()->machine()->Int32Add(),
    3436          97 :                                    Int32Constant(offset), index);
    3437         146 :   auto store = [&](int offset, MachineRepresentation rep, Node* data) {
    3438             :     SetEffect(graph()->NewNode(
    3439             :         mcgraph()->machine()->Store(StoreRepresentation(rep, kNoWriteBarrier)),
    3440         884 :         info, mcgraph()->Int32Constant(offset), data, Effect(), Control()));
    3441         200 :   };
    3442             :   // Store address, is_store, and mem_rep.
    3443             :   store(offsetof(wasm::MemoryTracingInfo, address),
    3444          50 :         MachineRepresentation::kWord32, address);
    3445             :   store(offsetof(wasm::MemoryTracingInfo, is_store),
    3446             :         MachineRepresentation::kWord8,
    3447         100 :         mcgraph()->Int32Constant(is_store ? 1 : 0));
    3448             :   store(offsetof(wasm::MemoryTracingInfo, mem_rep),
    3449             :         MachineRepresentation::kWord8,
    3450         100 :         mcgraph()->Int32Constant(static_cast<int>(rep)));
    3451             : 
    3452          50 :   Node* call = BuildCallToRuntime(Runtime::kWasmTraceMemory, &info, 1);
    3453          50 :   SetSourcePosition(call, position);
    3454          50 :   return call;
    3455             : }
    3456             : 
    3457      198560 : Node* WasmGraphBuilder::LoadMem(wasm::ValueType type, MachineType memtype,
    3458             :                                 Node* index, uint32_t offset,
    3459             :                                 uint32_t alignment,
    3460     1190800 :                                 wasm::WasmCodePosition position) {
    3461             :   Node* load;
    3462             : 
    3463             :   // Wasm semantics throw on OOB. Introduce explicit bounds check and
    3464             :   // conditioning when not using the trap handler.
    3465             :   index = BoundsCheckMem(wasm::ValueTypes::MemSize(memtype), index, offset,
    3466      198562 :                          position, kCanOmitBoundsCheck);
    3467             : 
    3468      395743 :   if (memtype.representation() == MachineRepresentation::kWord8 ||
    3469      197179 :       mcgraph()->machine()->UnalignedLoadSupported(memtype.representation())) {
    3470      198564 :     if (use_trap_handler()) {
    3471             :       load = graph()->NewNode(mcgraph()->machine()->ProtectedLoad(memtype),
    3472      397123 :                               MemBuffer(offset), index, Effect(), Control());
    3473      198563 :       SetSourcePosition(load, position);
    3474             :     } else {
    3475             :       load = graph()->NewNode(mcgraph()->machine()->Load(memtype),
    3476           2 :                               MemBuffer(offset), index, Effect(), Control());
    3477             :     }
    3478             :   } else {
    3479             :     // TODO(eholk): Support unaligned loads with trap handlers.
    3480             :     DCHECK(!use_trap_handler());
    3481             :     load = graph()->NewNode(mcgraph()->machine()->UnalignedLoad(memtype),
    3482           0 :                             MemBuffer(offset), index, Effect(), Control());
    3483             :   }
    3484             : 
    3485             :   SetEffect(load);
    3486             : 
    3487             : #if defined(V8_TARGET_BIG_ENDIAN)
    3488             :   load = BuildChangeEndiannessLoad(load, memtype, type);
    3489             : #endif
    3490             : 
    3491      288957 :   if (type == wasm::kWasmI64 &&
    3492             :       ElementSizeInBytes(memtype.representation()) < 8) {
    3493             :     // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes.
    3494         807 :     if (memtype.IsSigned()) {
    3495             :       // sign extend
    3496         429 :       load = graph()->NewNode(mcgraph()->machine()->ChangeInt32ToInt64(), load);
    3497             :     } else {
    3498             :       // zero extend
    3499             :       load =
    3500         378 :           graph()->NewNode(mcgraph()->machine()->ChangeUint32ToUint64(), load);
    3501             :     }
    3502             :   }
    3503             : 
    3504      198561 :   if (FLAG_trace_wasm_memory) {
    3505             :     TraceMemoryOperation(false, memtype.representation(), index, offset,
    3506          30 :                          position);
    3507             :   }
    3508             : 
    3509      198561 :   return load;
    3510             : }
    3511             : 
    3512      257925 : Node* WasmGraphBuilder::StoreMem(MachineRepresentation mem_rep, Node* index,
    3513             :                                  uint32_t offset, uint32_t alignment, Node* val,
    3514             :                                  wasm::WasmCodePosition position,
    3515     1546405 :                                  wasm::ValueType type) {
    3516             :   Node* store;
    3517             : 
    3518             :   index = BoundsCheckMem(i::ElementSizeInBytes(mem_rep), index, offset,
    3519      257930 :                          position, kCanOmitBoundsCheck);
    3520             : 
    3521             : #if defined(V8_TARGET_BIG_ENDIAN)
    3522             :   val = BuildChangeEndiannessStore(val, mem_rep, type);
    3523             : #endif
    3524             : 
    3525      514689 :   if (mem_rep == MachineRepresentation::kWord8 ||
    3526      256767 :       mcgraph()->machine()->UnalignedStoreSupported(mem_rep)) {
    3527      257922 :     if (use_trap_handler()) {
    3528             :       store =
    3529             :           graph()->NewNode(mcgraph()->machine()->ProtectedStore(mem_rep),
    3530      515837 :                            MemBuffer(offset), index, val, Effect(), Control());
    3531      257958 :       SetSourcePosition(store, position);
    3532             :     } else {
    3533             :       StoreRepresentation rep(mem_rep, kNoWriteBarrier);
    3534             :       store =
    3535             :           graph()->NewNode(mcgraph()->machine()->Store(rep), MemBuffer(offset),
    3536           0 :                            index, val, Effect(), Control());
    3537             :     }
    3538             :   } else {
    3539             :     // TODO(eholk): Support unaligned stores with trap handlers.
    3540             :     DCHECK(!use_trap_handler());
    3541             :     UnalignedStoreRepresentation rep(mem_rep);
    3542             :     store =
    3543             :         graph()->NewNode(mcgraph()->machine()->UnalignedStore(rep),
    3544           0 :                          MemBuffer(offset), index, val, Effect(), Control());
    3545             :   }
    3546             : 
    3547             :   SetEffect(store);
    3548             : 
    3549      257957 :   if (FLAG_trace_wasm_memory) {
    3550          20 :     TraceMemoryOperation(true, mem_rep, index, offset, position);
    3551             :   }
    3552             : 
    3553      257957 :   return store;
    3554             : }
    3555             : 
    3556             : namespace {
    3557       66141 : Node* GetAsmJsOOBValue(MachineRepresentation rep, MachineGraph* mcgraph) {
    3558       66141 :   switch (rep) {
    3559             :     case MachineRepresentation::kWord8:
    3560             :     case MachineRepresentation::kWord16:
    3561             :     case MachineRepresentation::kWord32:
    3562       58742 :       return mcgraph->Int32Constant(0);
    3563             :     case MachineRepresentation::kWord64:
    3564           0 :       return mcgraph->Int64Constant(0);
    3565             :     case MachineRepresentation::kFloat32:
    3566        6482 :       return mcgraph->Float32Constant(std::numeric_limits<float>::quiet_NaN());
    3567             :     case MachineRepresentation::kFloat64:
    3568         917 :       return mcgraph->Float64Constant(std::numeric_limits<double>::quiet_NaN());
    3569             :     default:
    3570           0 :       UNREACHABLE();
    3571             :   }
    3572             : }
    3573             : }  // namespace
    3574             : 
    3575      661410 : Node* WasmGraphBuilder::BuildAsmjsLoadMem(MachineType type, Node* index) {
    3576             :   DCHECK_NOT_NULL(instance_cache_);
    3577       66141 :   Node* mem_start = instance_cache_->mem_start;
    3578       66141 :   Node* mem_size = instance_cache_->mem_size;
    3579             :   DCHECK_NOT_NULL(mem_start);
    3580             :   DCHECK_NOT_NULL(mem_size);
    3581             : 
    3582             :   // Asm.js semantics are defined in terms of typed arrays, hence OOB
    3583             :   // reads return {undefined} coerced to the result type (0 for integers, NaN
    3584             :   // for float and double).
    3585             :   // Note that we check against the memory size ignoring the size of the
    3586             :   // stored value, which is conservative if misaligned. Technically, asm.js
    3587             :   // should never have misaligned accesses.
    3588       66141 :   index = Uint32ToUintptr(index);
    3589             :   Diamond bounds_check(
    3590             :       graph(), mcgraph()->common(),
    3591             :       graph()->NewNode(mcgraph()->machine()->UintLessThan(), index, mem_size),
    3592      198423 :       BranchHint::kTrue);
    3593       66141 :   bounds_check.Chain(Control());
    3594             : 
    3595       66141 :   if (untrusted_code_mitigations_) {
    3596             :     // Condition the index with the memory mask.
    3597           0 :     Node* mem_mask = instance_cache_->mem_mask;
    3598             :     DCHECK_NOT_NULL(mem_mask);
    3599           0 :     index = graph()->NewNode(mcgraph()->machine()->WordAnd(), index, mem_mask);
    3600             :   }
    3601             : 
    3602             :   Node* load = graph()->NewNode(mcgraph()->machine()->Load(type), mem_start,
    3603      132282 :                                 index, Effect(), bounds_check.if_true);
    3604       66141 :   SetEffect(bounds_check.EffectPhi(load, Effect()));
    3605       66141 :   SetControl(bounds_check.merge);
    3606             :   return bounds_check.Phi(type.representation(), load,
    3607       66141 :                           GetAsmJsOOBValue(type.representation(), mcgraph()));
    3608             : }
    3609             : 
    3610      609428 : Node* WasmGraphBuilder::Uint32ToUintptr(Node* node) {
    3611     1218856 :   if (mcgraph()->machine()->Is32()) return node;
    3612             :   // Fold instances of ChangeUint32ToUint64(IntConstant) directly.
    3613             :   Uint32Matcher matcher(node);
    3614      609443 :   if (matcher.HasValue()) {
    3615      476724 :     uintptr_t value = matcher.Value();
    3616      476724 :     return mcgraph()->IntPtrConstant(bit_cast<intptr_t>(value));
    3617             :   }
    3618      265409 :   return graph()->NewNode(mcgraph()->machine()->ChangeUint32ToUint64(), node);
    3619             : }
    3620             : 
    3621       47018 : Node* WasmGraphBuilder::BuildAsmjsStoreMem(MachineType type, Node* index,
    3622      376144 :                                            Node* val) {
    3623             :   DCHECK_NOT_NULL(instance_cache_);
    3624       47018 :   Node* mem_start = instance_cache_->mem_start;
    3625       47018 :   Node* mem_size = instance_cache_->mem_size;
    3626             :   DCHECK_NOT_NULL(mem_start);
    3627             :   DCHECK_NOT_NULL(mem_size);
    3628             : 
    3629             :   // Asm.js semantics are to ignore OOB writes.
    3630             :   // Note that we check against the memory size ignoring the size of the
    3631             :   // stored value, which is conservative if misaligned. Technically, asm.js
    3632             :   // should never have misaligned accesses.
    3633             :   Diamond bounds_check(
    3634             :       graph(), mcgraph()->common(),
    3635             :       graph()->NewNode(mcgraph()->machine()->Uint32LessThan(), index, mem_size),
    3636      141054 :       BranchHint::kTrue);
    3637       47018 :   bounds_check.Chain(Control());
    3638             : 
    3639       47018 :   if (untrusted_code_mitigations_) {
    3640             :     // Condition the index with the memory mask.
    3641           0 :     Node* mem_mask = instance_cache_->mem_mask;
    3642             :     DCHECK_NOT_NULL(mem_mask);
    3643             :     index =
    3644           0 :         graph()->NewNode(mcgraph()->machine()->Word32And(), index, mem_mask);
    3645             :   }
    3646             : 
    3647       47018 :   index = Uint32ToUintptr(index);
    3648             :   const Operator* store_op = mcgraph()->machine()->Store(StoreRepresentation(
    3649       94036 :       type.representation(), WriteBarrierKind::kNoWriteBarrier));
    3650             :   Node* store = graph()->NewNode(store_op, mem_start, index, val, Effect(),
    3651       47018 :                                  bounds_check.if_true);
    3652       47018 :   SetEffect(bounds_check.EffectPhi(store, Effect()));
    3653       47018 :   SetControl(bounds_check.merge);
    3654       47018 :   return val;
    3655             : }
    3656             : 
    3657           0 : void WasmGraphBuilder::PrintDebugName(Node* node) {
    3658           0 :   PrintF("#%d:%s", node->id(), node->op()->mnemonic());
    3659           0 : }
    3660             : 
    3661    18118483 : Graph* WasmGraphBuilder::graph() { return mcgraph()->graph(); }
    3662             : 
    3663             : namespace {
    3664        5085 : Signature<MachineRepresentation>* CreateMachineSignature(
    3665       10170 :     Zone* zone, wasm::FunctionSig* sig) {
    3666             :   Signature<MachineRepresentation>::Builder builder(zone, sig->return_count(),
    3667             :                                                     sig->parameter_count());
    3668       10170 :   for (auto ret : sig->returns()) {
    3669        5085 :     builder.AddReturn(wasm::ValueTypes::MachineRepresentationFor(ret));
    3670             :   }
    3671             : 
    3672        8080 :   for (auto param : sig->parameters()) {
    3673        2995 :     builder.AddParam(wasm::ValueTypes::MachineRepresentationFor(param));
    3674             :   }
    3675        5085 :   return builder.Build();
    3676             : }
    3677             : }  // namespace
    3678             : 
    3679     1060818 : void WasmGraphBuilder::LowerInt64() {
    3680     3182454 :   if (mcgraph()->machine()->Is64()) return;
    3681             :   Int64Lowering r(mcgraph()->graph(), mcgraph()->machine(), mcgraph()->common(),
    3682             :                   mcgraph()->zone(),
    3683           0 :                   CreateMachineSignature(mcgraph()->zone(), sig_));
    3684           0 :   r.LowerGraph();
    3685             : }
    3686             : 
    3687           0 : void WasmGraphBuilder::SimdScalarLoweringForTesting() {
    3688             :   SimdScalarLowering(mcgraph(), CreateMachineSignature(mcgraph()->zone(), sig_))
    3689           0 :       .LowerGraph();
    3690           0 : }
    3691             : 
    3692      667912 : void WasmGraphBuilder::SetSourcePosition(Node* node,
    3693             :                                          wasm::WasmCodePosition position) {
    3694             :   DCHECK_NE(position, wasm::kNoCodePosition);
    3695      667912 :   if (source_position_table_)
    3696      566761 :     source_position_table_->SetSourcePosition(node, SourcePosition(position));
    3697      667957 : }
    3698             : 
    3699        7986 : Node* WasmGraphBuilder::S128Zero() {
    3700        3993 :   has_simd_ = true;
    3701        7986 :   return graph()->NewNode(mcgraph()->machine()->S128Zero());
    3702             : }
    3703             : 
    3704       15370 : Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) {
    3705        7685 :   has_simd_ = true;
    3706        7685 :   switch (opcode) {
    3707             :     case wasm::kExprF32x4Splat:
    3708        1575 :       return graph()->NewNode(mcgraph()->machine()->F32x4Splat(), inputs[0]);
    3709             :     case wasm::kExprF32x4SConvertI32x4:
    3710             :       return graph()->NewNode(mcgraph()->machine()->F32x4SConvertI32x4(),
    3711          30 :                               inputs[0]);
    3712             :     case wasm::kExprF32x4UConvertI32x4:
    3713             :       return graph()->NewNode(mcgraph()->machine()->F32x4UConvertI32x4(),
    3714          30 :                               inputs[0]);
    3715             :     case wasm::kExprF32x4Abs:
    3716          45 :       return graph()->NewNode(mcgraph()->machine()->F32x4Abs(), inputs[0]);
    3717             :     case wasm::kExprF32x4Neg:
    3718          45 :       return graph()->NewNode(mcgraph()->machine()->F32x4Neg(), inputs[0]);
    3719             :     case wasm::kExprF32x4RecipApprox:
    3720             :       return graph()->NewNode(mcgraph()->machine()->F32x4RecipApprox(),
    3721          45 :                               inputs[0]);
    3722             :     case wasm::kExprF32x4RecipSqrtApprox:
    3723             :       return graph()->NewNode(mcgraph()->machine()->F32x4RecipSqrtApprox(),
    3724          45 :                               inputs[0]);
    3725             :     case wasm::kExprF32x4Add:
    3726             :       return graph()->NewNode(mcgraph()->machine()->F32x4Add(), inputs[0],
    3727         135 :                               inputs[1]);
    3728             :     case wasm::kExprF32x4AddHoriz:
    3729             :       return graph()->NewNode(mcgraph()->machine()->F32x4AddHoriz(), inputs[0],
    3730          45 :                               inputs[1]);
    3731             :     case wasm::kExprF32x4Sub:
    3732             :       return graph()->NewNode(mcgraph()->machine()->F32x4Sub(), inputs[0],
    3733          45 :                               inputs[1]);
    3734             :     case wasm::kExprF32x4Mul:
    3735             :       return graph()->NewNode(mcgraph()->machine()->F32x4Mul(), inputs[0],
    3736          45 :                               inputs[1]);
    3737             :     case wasm::kExprF32x4Min:
    3738             :       return graph()->NewNode(mcgraph()->machine()->F32x4Min(), inputs[0],
    3739          45 :                               inputs[1]);
    3740             :     case wasm::kExprF32x4Max:
    3741             :       return graph()->NewNode(mcgraph()->machine()->F32x4Max(), inputs[0],
    3742          45 :                               inputs[1]);
    3743             :     case wasm::kExprF32x4Eq:
    3744             :       return graph()->NewNode(mcgraph()->machine()->F32x4Eq(), inputs[0],
    3745          45 :                               inputs[1]);
    3746             :     case wasm::kExprF32x4Ne:
    3747             :       return graph()->NewNode(mcgraph()->machine()->F32x4Ne(), inputs[0],
    3748          45 :                               inputs[1]);
    3749             :     case wasm::kExprF32x4Lt:
    3750             :       return graph()->NewNode(mcgraph()->machine()->F32x4Lt(), inputs[0],
    3751          45 :                               inputs[1]);
    3752             :     case wasm::kExprF32x4Le:
    3753             :       return graph()->NewNode(mcgraph()->machine()->F32x4Le(), inputs[0],
    3754          45 :                               inputs[1]);
    3755             :     case wasm::kExprF32x4Gt:
    3756             :       return graph()->NewNode(mcgraph()->machine()->F32x4Lt(), inputs[1],
    3757          45 :                               inputs[0]);
    3758             :     case wasm::kExprF32x4Ge:
    3759             :       return graph()->NewNode(mcgraph()->machine()->F32x4Le(), inputs[1],
    3760          45 :                               inputs[0]);
    3761             :     case wasm::kExprI32x4Splat:
    3762        6900 :       return graph()->NewNode(mcgraph()->machine()->I32x4Splat(), inputs[0]);
    3763             :     case wasm::kExprI32x4SConvertF32x4:
    3764             :       return graph()->NewNode(mcgraph()->machine()->I32x4SConvertF32x4(),
    3765          45 :                               inputs[0]);
    3766             :     case wasm::kExprI32x4UConvertF32x4:
    3767             :       return graph()->NewNode(mcgraph()->machine()->I32x4UConvertF32x4(),
    3768          45 :                               inputs[0]);
    3769             :     case wasm::kExprI32x4SConvertI16x8Low:
    3770             :       return graph()->NewNode(mcgraph()->machine()->I32x4SConvertI16x8Low(),
    3771          45 :                               inputs[0]);
    3772             :     case wasm::kExprI32x4SConvertI16x8High:
    3773             :       return graph()->NewNode(mcgraph()->machine()->I32x4SConvertI16x8High(),
    3774          45 :                               inputs[0]);
    3775             :     case wasm::kExprI32x4Neg:
    3776          45 :       return graph()->NewNode(mcgraph()->machine()->I32x4Neg(), inputs[0]);
    3777             :     case wasm::kExprI32x4Add:
    3778             :       return graph()->NewNode(mcgraph()->machine()->I32x4Add(), inputs[0],
    3779         135 :                               inputs[1]);
    3780             :     case wasm::kExprI32x4AddHoriz:
    3781             :       return graph()->NewNode(mcgraph()->machine()->I32x4AddHoriz(), inputs[0],
    3782          45 :                               inputs[1]);
    3783             :     case wasm::kExprI32x4Sub:
    3784             :       return graph()->NewNode(mcgraph()->machine()->I32x4Sub(), inputs[0],
    3785          45 :                               inputs[1]);
    3786             :     case wasm::kExprI32x4Mul:
    3787             :       return graph()->NewNode(mcgraph()->machine()->I32x4Mul(), inputs[0],
    3788          45 :                               inputs[1]);
    3789             :     case wasm::kExprI32x4MinS:
    3790             :       return graph()->NewNode(mcgraph()->machine()->I32x4MinS(), inputs[0],
    3791          45 :                               inputs[1]);
    3792             :     case wasm::kExprI32x4MaxS:
    3793             :       return graph()->NewNode(mcgraph()->machine()->I32x4MaxS(), inputs[0],
    3794          45 :                               inputs[1]);
    3795             :     case wasm::kExprI32x4Eq:
    3796             :       return graph()->NewNode(mcgraph()->machine()->I32x4Eq(), inputs[0],
    3797         225 :                               inputs[1]);
    3798             :     case wasm::kExprI32x4Ne:
    3799             :       return graph()->NewNode(mcgraph()->machine()->I32x4Ne(), inputs[0],
    3800         240 :                               inputs[1]);
    3801             :     case wasm::kExprI32x4LtS:
    3802             :       return graph()->NewNode(mcgraph()->machine()->I32x4GtS(), inputs[1],
    3803          45 :                               inputs[0]);
    3804             :     case wasm::kExprI32x4LeS:
    3805             :       return graph()->NewNode(mcgraph()->machine()->I32x4GeS(), inputs[1],
    3806          45 :                               inputs[0]);
    3807             :     case wasm::kExprI32x4GtS:
    3808             :       return graph()->NewNode(mcgraph()->machine()->I32x4GtS(), inputs[0],
    3809          45 :                               inputs[1]);
    3810             :     case wasm::kExprI32x4GeS:
    3811             :       return graph()->NewNode(mcgraph()->machine()->I32x4GeS(), inputs[0],
    3812          45 :                               inputs[1]);
    3813             :     case wasm::kExprI32x4UConvertI16x8Low:
    3814             :       return graph()->NewNode(mcgraph()->machine()->I32x4UConvertI16x8Low(),
    3815          45 :                               inputs[0]);
    3816             :     case wasm::kExprI32x4UConvertI16x8High:
    3817             :       return graph()->NewNode(mcgraph()->machine()->I32x4UConvertI16x8High(),
    3818          45 :                               inputs[0]);
    3819             :     case wasm::kExprI32x4MinU:
    3820             :       return graph()->NewNode(mcgraph()->machine()->I32x4MinU(), inputs[0],
    3821          45 :                               inputs[1]);
    3822             :     case wasm::kExprI32x4MaxU:
    3823             :       return graph()->NewNode(mcgraph()->machine()->I32x4MaxU(), inputs[0],
    3824          45 :                               inputs[1]);
    3825             :     case wasm::kExprI32x4LtU:
    3826             :       return graph()->NewNode(mcgraph()->machine()->I32x4GtU(), inputs[1],
    3827          45 :                               inputs[0]);
    3828             :     case wasm::kExprI32x4LeU:
    3829             :       return graph()->NewNode(mcgraph()->machine()->I32x4GeU(), inputs[1],
    3830          45 :                               inputs[0]);
    3831             :     case wasm::kExprI32x4GtU:
    3832             :       return graph()->NewNode(mcgraph()->machine()->I32x4GtU(), inputs[0],
    3833          45 :                               inputs[1]);
    3834             :     case wasm::kExprI32x4GeU:
    3835             :       return graph()->NewNode(mcgraph()->machine()->I32x4GeU(), inputs[0],
    3836          45 :                               inputs[1]);
    3837             :     case wasm::kExprI16x8Splat:
    3838        4350 :       return graph()->NewNode(mcgraph()->machine()->I16x8Splat(), inputs[0]);
    3839             :     case wasm::kExprI16x8SConvertI8x16Low:
    3840             :       return graph()->NewNode(mcgraph()->machine()->I16x8SConvertI8x16Low(),
    3841          45 :                               inputs[0]);
    3842             :     case wasm::kExprI16x8SConvertI8x16High:
    3843             :       return graph()->NewNode(mcgraph()->machine()->I16x8SConvertI8x16High(),
    3844          45 :                               inputs[0]);
    3845             :     case wasm::kExprI16x8Neg:
    3846          45 :       return graph()->NewNode(mcgraph()->machine()->I16x8Neg(), inputs[0]);
    3847             :     case wasm::kExprI16x8SConvertI32x4:
    3848             :       return graph()->NewNode(mcgraph()->machine()->I16x8SConvertI32x4(),
    3849          45 :                               inputs[0], inputs[1]);
    3850             :     case wasm::kExprI16x8Add:
    3851             :       return graph()->NewNode(mcgraph()->machine()->I16x8Add(), inputs[0],
    3852          45 :                               inputs[1]);
    3853             :     case wasm::kExprI16x8AddSaturateS:
    3854             :       return graph()->NewNode(mcgraph()->machine()->I16x8AddSaturateS(),
    3855          45 :                               inputs[0], inputs[1]);
    3856             :     case wasm::kExprI16x8AddHoriz:
    3857             :       return graph()->NewNode(mcgraph()->machine()->I16x8AddHoriz(), inputs[0],
    3858          45 :                               inputs[1]);
    3859             :     case wasm::kExprI16x8Sub:
    3860             :       return graph()->NewNode(mcgraph()->machine()->I16x8Sub(), inputs[0],
    3861          45 :                               inputs[1]);
    3862             :     case wasm::kExprI16x8SubSaturateS:
    3863             :       return graph()->NewNode(mcgraph()->machine()->I16x8SubSaturateS(),
    3864          45 :                               inputs[0], inputs[1]);
    3865             :     case wasm::kExprI16x8Mul:
    3866             :       return graph()->NewNode(mcgraph()->machine()->I16x8Mul(), inputs[0],
    3867          45 :                               inputs[1]);
    3868             :     case wasm::kExprI16x8MinS:
    3869             :       return graph()->NewNode(mcgraph()->machine()->I16x8MinS(), inputs[0],
    3870          45 :                               inputs[1]);
    3871             :     case wasm::kExprI16x8MaxS:
    3872             :       return graph()->NewNode(mcgraph()->machine()->I16x8MaxS(), inputs[0],
    3873          45 :                               inputs[1]);
    3874             :     case wasm::kExprI16x8Eq:
    3875             :       return graph()->NewNode(mcgraph()->machine()->I16x8Eq(), inputs[0],
    3876         225 :                               inputs[1]);
    3877             :     case wasm::kExprI16x8Ne:
    3878             :       return graph()->NewNode(mcgraph()->machine()->I16x8Ne(), inputs[0],
    3879         240 :                               inputs[1]);
    3880             :     case wasm::kExprI16x8LtS:
    3881             :       return graph()->NewNode(mcgraph()->machine()->I16x8GtS(), inputs[1],
    3882          45 :                               inputs[0]);
    3883             :     case wasm::kExprI16x8LeS:
    3884             :       return graph()->NewNode(mcgraph()->machine()->I16x8GeS(), inputs[1],
    3885          45 :                               inputs[0]);
    3886             :     case wasm::kExprI16x8GtS:
    3887             :       return graph()->NewNode(mcgraph()->machine()->I16x8GtS(), inputs[0],
    3888          45 :                               inputs[1]);
    3889             :     case wasm::kExprI16x8GeS:
    3890             :       return graph()->NewNode(mcgraph()->machine()->I16x8GeS(), inputs[0],
    3891          45 :                               inputs[1]);
    3892             :     case wasm::kExprI16x8UConvertI8x16Low:
    3893             :       return graph()->NewNode(mcgraph()->machine()->I16x8UConvertI8x16Low(),
    3894          45 :                               inputs[0]);
    3895             :     case wasm::kExprI16x8UConvertI8x16High:
    3896             :       return graph()->NewNode(mcgraph()->machine()->I16x8UConvertI8x16High(),
    3897          45 :                               inputs[0]);
    3898             :     case wasm::kExprI16x8UConvertI32x4:
    3899             :       return graph()->NewNode(mcgraph()->machine()->I16x8UConvertI32x4(),
    3900          45 :                               inputs[0], inputs[1]);
    3901             :     case wasm::kExprI16x8AddSaturateU:
    3902             :       return graph()->NewNode(mcgraph()->machine()->I16x8AddSaturateU(),
    3903          45 :                               inputs[0], inputs[1]);
    3904             :     case wasm::kExprI16x8SubSaturateU:
    3905             :       return graph()->NewNode(mcgraph()->machine()->I16x8SubSaturateU(),
    3906          45 :                               inputs[0], inputs[1]);
    3907             :     case wasm::kExprI16x8MinU:
    3908             :       return graph()->NewNode(mcgraph()->machine()->I16x8MinU(), inputs[0],
    3909          45 :                               inputs[1]);
    3910             :     case wasm::kExprI16x8MaxU:
    3911             :       return graph()->NewNode(mcgraph()->machine()->I16x8MaxU(), inputs[0],
    3912          45 :                               inputs[1]);
    3913             :     case wasm::kExprI16x8LtU:
    3914             :       return graph()->NewNode(mcgraph()->machine()->I16x8GtU(), inputs[1],
    3915          45 :                               inputs[0]);
    3916             :     case wasm::kExprI16x8LeU:
    3917             :       return graph()->NewNode(mcgraph()->machine()->I16x8GeU(), inputs[1],
    3918          45 :                               inputs[0]);
    3919             :     case wasm::kExprI16x8GtU:
    3920             :       return graph()->NewNode(mcgraph()->machine()->I16x8GtU(), inputs[0],
    3921          45 :                               inputs[1]);
    3922             :     case wasm::kExprI16x8GeU:
    3923             :       return graph()->NewNode(mcgraph()->machine()->I16x8GeU(), inputs[0],
    3924          45 :                               inputs[1]);
    3925             :     case wasm::kExprI8x16Splat:
    3926        3180 :       return graph()->NewNode(mcgraph()->machine()->I8x16Splat(), inputs[0]);
    3927             :     case wasm::kExprI8x16Neg:
    3928          45 :       return graph()->NewNode(mcgraph()->machine()->I8x16Neg(), inputs[0]);
    3929             :     case wasm::kExprI8x16SConvertI16x8:
    3930             :       return graph()->NewNode(mcgraph()->machine()->I8x16SConvertI16x8(),
    3931          45 :                               inputs[0], inputs[1]);
    3932             :     case wasm::kExprI8x16Add:
    3933             :       return graph()->NewNode(mcgraph()->machine()->I8x16Add(), inputs[0],
    3934          45 :                               inputs[1]);
    3935             :     case wasm::kExprI8x16AddSaturateS:
    3936             :       return graph()->NewNode(mcgraph()->machine()->I8x16AddSaturateS(),
    3937          45 :                               inputs[0], inputs[1]);
    3938             :     case wasm::kExprI8x16Sub:
    3939             :       return graph()->NewNode(mcgraph()->machine()->I8x16Sub(), inputs[0],
    3940          45 :                               inputs[1]);
    3941             :     case wasm::kExprI8x16SubSaturateS:
    3942             :       return graph()->NewNode(mcgraph()->machine()->I8x16SubSaturateS(),
    3943          45 :                               inputs[0], inputs[1]);
    3944             :     case wasm::kExprI8x16Mul:
    3945             :       return graph()->NewNode(mcgraph()->machine()->I8x16Mul(), inputs[0],
    3946          45 :                               inputs[1]);
    3947             :     case wasm::kExprI8x16MinS:
    3948             :       return graph()->NewNode(mcgraph()->machine()->I8x16MinS(), inputs[0],
    3949          45 :                               inputs[1]);
    3950             :     case wasm::kExprI8x16MaxS:
    3951             :       return graph()->NewNode(mcgraph()->machine()->I8x16MaxS(), inputs[0],
    3952          45 :                               inputs[1]);
    3953             :     case wasm::kExprI8x16Eq:
    3954             :       return graph()->NewNode(mcgraph()->machine()->I8x16Eq(), inputs[0],
    3955         225 :                               inputs[1]);
    3956             :     case wasm::kExprI8x16Ne:
    3957             :       return graph()->NewNode(mcgraph()->machine()->I8x16Ne(), inputs[0],
    3958         240 :                               inputs[1]);
    3959             :     case wasm::kExprI8x16LtS:
    3960             :       return graph()->NewNode(mcgraph()->machine()->I8x16GtS(), inputs[1],
    3961          45 :                               inputs[0]);
    3962             :     case wasm::kExprI8x16LeS:
    3963             :       return graph()->NewNode(mcgraph()->machine()->I8x16GeS(), inputs[1],
    3964          45 :                               inputs[0]);
    3965             :     case wasm::kExprI8x16GtS:
    3966             :       return graph()->NewNode(mcgraph()->machine()->I8x16GtS(), inputs[0],
    3967          45 :                               inputs[1]);
    3968             :     case wasm::kExprI8x16GeS:
    3969             :       return graph()->NewNode(mcgraph()->machine()->I8x16GeS(), inputs[0],
    3970          45 :                               inputs[1]);
    3971             :     case wasm::kExprI8x16UConvertI16x8:
    3972             :       return graph()->NewNode(mcgraph()->machine()->I8x16UConvertI16x8(),
    3973          45 :                               inputs[0], inputs[1]);
    3974             :     case wasm::kExprI8x16AddSaturateU:
    3975             :       return graph()->NewNode(mcgraph()->machine()->I8x16AddSaturateU(),
    3976          45 :                               inputs[0], inputs[1]);
    3977             :     case wasm::kExprI8x16SubSaturateU:
    3978             :       return graph()->NewNode(mcgraph()->machine()->I8x16SubSaturateU(),
    3979          45 :                               inputs[0], inputs[1]);
    3980             :     case wasm::kExprI8x16MinU:
    3981             :       return graph()->NewNode(mcgraph()->machine()->I8x16MinU(), inputs[0],
    3982          45 :                               inputs[1]);
    3983             :     case wasm::kExprI8x16MaxU:
    3984             :       return graph()->NewNode(mcgraph()->machine()->I8x16MaxU(), inputs[0],
    3985          45 :                               inputs[1]);
    3986             :     case wasm::kExprI8x16LtU:
    3987             :       return graph()->NewNode(mcgraph()->machine()->I8x16GtU(), inputs[1],
    3988          45 :                               inputs[0]);
    3989             :     case wasm::kExprI8x16LeU:
    3990             :       return graph()->NewNode(mcgraph()->machine()->I8x16GeU(), inputs[1],
    3991          45 :                               inputs[0]);
    3992             :     case wasm::kExprI8x16GtU:
    3993             :       return graph()->NewNode(mcgraph()->machine()->I8x16GtU(), inputs[0],
    3994          45 :                               inputs[1]);
    3995             :     case wasm::kExprI8x16GeU:
    3996             :       return graph()->NewNode(mcgraph()->machine()->I8x16GeU(), inputs[0],
    3997          45 :                               inputs[1]);
    3998             :     case wasm::kExprS128And:
    3999             :       return graph()->NewNode(mcgraph()->machine()->S128And(), inputs[0],
    4000          45 :                               inputs[1]);
    4001             :     case wasm::kExprS128Or:
    4002             :       return graph()->NewNode(mcgraph()->machine()->S128Or(), inputs[0],
    4003          45 :                               inputs[1]);
    4004             :     case wasm::kExprS128Xor:
    4005             :       return graph()->NewNode(mcgraph()->machine()->S128Xor(), inputs[0],
    4006          45 :                               inputs[1]);
    4007             :     case wasm::kExprS128Not:
    4008          45 :       return graph()->NewNode(mcgraph()->machine()->S128Not(), inputs[0]);
    4009             :     case wasm::kExprS128Select:
    4010             :       return graph()->NewNode(mcgraph()->machine()->S128Select(), inputs[2],
    4011         105 :                               inputs[0], inputs[1]);
    4012             :     case wasm::kExprS1x4AnyTrue:
    4013         195 :       return graph()->NewNode(mcgraph()->machine()->S1x4AnyTrue(), inputs[0]);
    4014             :     case wasm::kExprS1x4AllTrue:
    4015         195 :       return graph()->NewNode(mcgraph()->machine()->S1x4AllTrue(), inputs[0]);
    4016             :     case wasm::kExprS1x8AnyTrue:
    4017         195 :       return graph()->NewNode(mcgraph()->machine()->S1x8AnyTrue(), inputs[0]);
    4018             :     case wasm::kExprS1x8AllTrue:
    4019         195 :       return graph()->NewNode(mcgraph()->machine()->S1x8AllTrue(), inputs[0]);
    4020             :     case wasm::kExprS1x16AnyTrue:
    4021         195 :       return graph()->NewNode(mcgraph()->machine()->S1x16AnyTrue(), inputs[0]);
    4022             :     case wasm::kExprS1x16AllTrue:
    4023         195 :       return graph()->NewNode(mcgraph()->machine()->S1x16AllTrue(), inputs[0]);
    4024             :     default:
    4025           0 :       FATAL_UNSUPPORTED_OPCODE(opcode);
    4026             :   }
    4027             : }
    4028             : 
    4029       34880 : Node* WasmGraphBuilder::SimdLaneOp(wasm::WasmOpcode opcode, uint8_t lane,
    4030       34880 :                                    Node* const* inputs) {
    4031       34880 :   has_simd_ = true;
    4032       34880 :   switch (opcode) {
    4033             :     case wasm::kExprF32x4ExtractLane:
    4034             :       return graph()->NewNode(mcgraph()->machine()->F32x4ExtractLane(lane),
    4035        3840 :                               inputs[0]);
    4036             :     case wasm::kExprF32x4ReplaceLane:
    4037             :       return graph()->NewNode(mcgraph()->machine()->F32x4ReplaceLane(lane),
    4038         360 :                               inputs[0], inputs[1]);
    4039             :     case wasm::kExprI32x4ExtractLane:
    4040             :       return graph()->NewNode(mcgraph()->machine()->I32x4ExtractLane(lane),
    4041       24510 :                               inputs[0]);
    4042             :     case wasm::kExprI32x4ReplaceLane:
    4043             :       return graph()->NewNode(mcgraph()->machine()->I32x4ReplaceLane(lane),
    4044         510 :                               inputs[0], inputs[1]);
    4045             :     case wasm::kExprI16x8ExtractLane:
    4046             :       return graph()->NewNode(mcgraph()->machine()->I16x8ExtractLane(lane),
    4047       29640 :                               inputs[0]);
    4048             :     case wasm::kExprI16x8ReplaceLane:
    4049             :       return graph()->NewNode(mcgraph()->machine()->I16x8ReplaceLane(lane),
    4050         510 :                               inputs[0], inputs[1]);
    4051             :     case wasm::kExprI8x16ExtractLane:
    4052             :       return graph()->NewNode(mcgraph()->machine()->I8x16ExtractLane(lane),
    4053       44400 :                               inputs[0]);
    4054             :     case wasm::kExprI8x16ReplaceLane:
    4055             :       return graph()->NewNode(mcgraph()->machine()->I8x16ReplaceLane(lane),
    4056         870 :                               inputs[0], inputs[1]);
    4057             :     default:
    4058           0 :       FATAL_UNSUPPORTED_OPCODE(opcode);
    4059             :   }
    4060             : }
    4061             : 
    4062        2385 : Node* WasmGraphBuilder::SimdShiftOp(wasm::WasmOpcode opcode, uint8_t shift,
    4063        2385 :                                     Node* const* inputs) {
    4064        2385 :   has_simd_ = true;
    4065        2385 :   switch (opcode) {
    4066             :     case wasm::kExprI32x4Shl:
    4067        1395 :       return graph()->NewNode(mcgraph()->machine()->I32x4Shl(shift), inputs[0]);
    4068             :     case wasm::kExprI32x4ShrS:
    4069             :       return graph()->NewNode(mcgraph()->machine()->I32x4ShrS(shift),
    4070        1395 :                               inputs[0]);
    4071             :     case wasm::kExprI32x4ShrU:
    4072             :       return graph()->NewNode(mcgraph()->machine()->I32x4ShrU(shift),
    4073        1395 :                               inputs[0]);
    4074             :     case wasm::kExprI16x8Shl:
    4075         675 :       return graph()->NewNode(mcgraph()->machine()->I16x8Shl(shift), inputs[0]);
    4076             :     case wasm::kExprI16x8ShrS:
    4077             :       return graph()->NewNode(mcgraph()->machine()->I16x8ShrS(shift),
    4078         675 :                               inputs[0]);
    4079             :     case wasm::kExprI16x8ShrU:
    4080             :       return graph()->NewNode(mcgraph()->machine()->I16x8ShrU(shift),
    4081         675 :                               inputs[0]);
    4082             :     case wasm::kExprI8x16Shl:
    4083         315 :       return graph()->NewNode(mcgraph()->machine()->I8x16Shl(shift), inputs[0]);
    4084             :     case wasm::kExprI8x16ShrS:
    4085             :       return graph()->NewNode(mcgraph()->machine()->I8x16ShrS(shift),
    4086         315 :                               inputs[0]);
    4087             :     case wasm::kExprI8x16ShrU:
    4088             :       return graph()->NewNode(mcgraph()->machine()->I8x16ShrU(shift),
    4089         315 :                               inputs[0]);
    4090             :     default:
    4091           0 :       FATAL_UNSUPPORTED_OPCODE(opcode);
    4092             :   }
    4093             : }
    4094             : 
    4095       33780 : Node* WasmGraphBuilder::Simd8x16ShuffleOp(const uint8_t shuffle[16],
    4096       33780 :                                           Node* const* inputs) {
    4097       33780 :   has_simd_ = true;
    4098             :   return graph()->NewNode(mcgraph()->machine()->S8x16Shuffle(shuffle),
    4099      101340 :                           inputs[0], inputs[1]);
    4100             : }
    4101             : 
    4102             : #define ATOMIC_BINOP_LIST(V)                        \
    4103             :   V(I32AtomicAdd, Add, Uint32, Word32)              \
    4104             :   V(I64AtomicAdd, Add, Uint64, Word64)              \
    4105             :   V(I32AtomicAdd8U, Add, Uint8, Word32)             \
    4106             :   V(I32AtomicAdd16U, Add, Uint16, Word32)           \
    4107             :   V(I64AtomicAdd8U, Add, Uint8, Word64)             \
    4108             :   V(I64AtomicAdd16U, Add, Uint16, Word64)           \
    4109             :   V(I64AtomicAdd32U, Add, Uint32, Word64)           \
    4110             :   V(I32AtomicSub, Sub, Uint32, Word32)              \
    4111             :   V(I64AtomicSub, Sub, Uint64, Word64)              \
    4112             :   V(I32AtomicSub8U, Sub, Uint8, Word32)             \
    4113             :   V(I32AtomicSub16U, Sub, Uint16, Word32)           \
    4114             :   V(I64AtomicSub8U, Sub, Uint8, Word64)             \
    4115             :   V(I64AtomicSub16U, Sub, Uint16, Word64)           \
    4116             :   V(I64AtomicSub32U, Sub, Uint32, Word64)           \
    4117             :   V(I32AtomicAnd, And, Uint32, Word32)              \
    4118             :   V(I64AtomicAnd, And, Uint64, Word64)              \
    4119             :   V(I32AtomicAnd8U, And, Uint8, Word32)             \
    4120             :   V(I64AtomicAnd16U, And, Uint16, Word64)           \
    4121             :   V(I32AtomicAnd16U, And, Uint16, Word32)           \
    4122             :   V(I64AtomicAnd8U, And, Uint8, Word64)             \
    4123             :   V(I64AtomicAnd32U, And, Uint32, Word64)           \
    4124             :   V(I32AtomicOr, Or, Uint32, Word32)                \
    4125             :   V(I64AtomicOr, Or, Uint64, Word64)                \
    4126             :   V(I32AtomicOr8U, Or, Uint8, Word32)               \
    4127             :   V(I32AtomicOr16U, Or, Uint16, Word32)             \
    4128             :   V(I64AtomicOr8U, Or, Uint8, Word64)               \
    4129             :   V(I64AtomicOr16U, Or, Uint16, Word64)             \
    4130             :   V(I64AtomicOr32U, Or, Uint32, Word64)             \
    4131             :   V(I32AtomicXor, Xor, Uint32, Word32)              \
    4132             :   V(I64AtomicXor, Xor, Uint64, Word64)              \
    4133             :   V(I32AtomicXor8U, Xor, Uint8, Word32)             \
    4134             :   V(I32AtomicXor16U, Xor, Uint16, Word32)           \
    4135             :   V(I64AtomicXor8U, Xor, Uint8, Word64)             \
    4136             :   V(I64AtomicXor16U, Xor, Uint16, Word64)           \
    4137             :   V(I64AtomicXor32U, Xor, Uint32, Word64)           \
    4138             :   V(I32AtomicExchange, Exchange, Uint32, Word32)    \
    4139             :   V(I64AtomicExchange, Exchange, Uint64, Word64)    \
    4140             :   V(I32AtomicExchange8U, Exchange, Uint8, Word32)   \
    4141             :   V(I32AtomicExchange16U, Exchange, Uint16, Word32) \
    4142             :   V(I64AtomicExchange8U, Exchange, Uint8, Word64)   \
    4143             :   V(I64AtomicExchange16U, Exchange, Uint16, Word64) \
    4144             :   V(I64AtomicExchange32U, Exchange, Uint32, Word64)
    4145             : 
    4146             : #define ATOMIC_CMP_EXCHG_LIST(V)                 \
    4147             :   V(I32AtomicCompareExchange, Uint32, Word32)    \
    4148             :   V(I64AtomicCompareExchange, Uint64, Word64)    \
    4149             :   V(I32AtomicCompareExchange8U, Uint8, Word32)   \
    4150             :   V(I32AtomicCompareExchange16U, Uint16, Word32) \
    4151             :   V(I64AtomicCompareExchange8U, Uint8, Word64)   \
    4152             :   V(I64AtomicCompareExchange16U, Uint16, Word64) \
    4153             :   V(I64AtomicCompareExchange32U, Uint32, Word64)
    4154             : 
    4155             : #define ATOMIC_LOAD_LIST(V)           \
    4156             :   V(I32AtomicLoad, Uint32, Word32)    \
    4157             :   V(I64AtomicLoad, Uint64, Word64)    \
    4158             :   V(I32AtomicLoad8U, Uint8, Word32)   \
    4159             :   V(I32AtomicLoad16U, Uint16, Word32) \
    4160             :   V(I64AtomicLoad8U, Uint8, Word64)   \
    4161             :   V(I64AtomicLoad16U, Uint16, Word64) \
    4162             :   V(I64AtomicLoad32U, Uint32, Word64)
    4163             : 
    4164             : #define ATOMIC_STORE_LIST(V)                    \
    4165             :   V(I32AtomicStore, Uint32, kWord32, Word32)    \
    4166             :   V(I64AtomicStore, Uint64, kWord64, Word64)    \
    4167             :   V(I32AtomicStore8U, Uint8, kWord8, Word32)    \
    4168             :   V(I32AtomicStore16U, Uint16, kWord16, Word32) \
    4169             :   V(I64AtomicStore8U, Uint8, kWord8, Word64)    \
    4170             :   V(I64AtomicStore16U, Uint16, kWord16, Word64) \
    4171             :   V(I64AtomicStore32U, Uint32, kWord32, Word64)
    4172             : 
    4173       33583 : Node* WasmGraphBuilder::AtomicOp(wasm::WasmOpcode opcode, Node* const* inputs,
    4174             :                                  uint32_t alignment, uint32_t offset,
    4175      138106 :                                  wasm::WasmCodePosition position) {
    4176             :   Node* node;
    4177       33583 :   switch (opcode) {
    4178             : #define BUILD_ATOMIC_BINOP(Name, Operation, Type, Prefix)                     \
    4179             :   case wasm::kExpr##Name: {                                                   \
    4180             :     Node* index = CheckBoundsAndAlignment(                                    \
    4181             :         wasm::ValueTypes::MemSize(MachineType::Type()), inputs[0], offset,    \
    4182             :         position);                                                            \
    4183             :     node = graph()->NewNode(                                                  \
    4184             :         mcgraph()->machine()->Prefix##Atomic##Operation(MachineType::Type()), \
    4185             :         MemBuffer(offset), index, inputs[1], Effect(), Control());            \
    4186             :     break;                                                                    \
    4187             :   }
    4188       96144 :     ATOMIC_BINOP_LIST(BUILD_ATOMIC_BINOP)
    4189             : #undef BUILD_ATOMIC_BINOP
    4190             : 
    4191             : #define BUILD_ATOMIC_CMP_EXCHG(Name, Type, Prefix)                            \
    4192             :   case wasm::kExpr##Name: {                                                   \
    4193             :     Node* index = CheckBoundsAndAlignment(                                    \
    4194             :         wasm::ValueTypes::MemSize(MachineType::Type()), inputs[0], offset,    \
    4195             :         position);                                                            \
    4196             :     node = graph()->NewNode(                                                  \
    4197             :         mcgraph()->machine()->Prefix##AtomicCompareExchange(                  \
    4198             :             MachineType::Type()),                                             \
    4199             :         MemBuffer(offset), index, inputs[1], inputs[2], Effect(), Control()); \
    4200             :     break;                                                                    \
    4201             :   }
    4202         890 :     ATOMIC_CMP_EXCHG_LIST(BUILD_ATOMIC_CMP_EXCHG)
    4203             : #undef BUILD_ATOMIC_CMP_EXCHG
    4204             : 
    4205             : #define BUILD_ATOMIC_LOAD_OP(Name, Type, Prefix)                           \
    4206             :   case wasm::kExpr##Name: {                                                \
    4207             :     Node* index = CheckBoundsAndAlignment(                                 \
    4208             :         wasm::ValueTypes::MemSize(MachineType::Type()), inputs[0], offset, \
    4209             :         position);                                                         \
    4210             :     node = graph()->NewNode(                                               \
    4211             :         mcgraph()->machine()->Prefix##AtomicLoad(MachineType::Type()),     \
    4212             :         MemBuffer(offset), index, Effect(), Control());                    \
    4213             :     break;                                                                 \
    4214             :   }
    4215       18080 :     ATOMIC_LOAD_LIST(BUILD_ATOMIC_LOAD_OP)
    4216             : #undef BUILD_ATOMIC_LOAD_OP
    4217             : 
    4218             : #define BUILD_ATOMIC_STORE_OP(Name, Type, Rep, Prefix)                         \
    4219             :   case wasm::kExpr##Name: {                                                    \
    4220             :     Node* index = CheckBoundsAndAlignment(                                     \
    4221             :         wasm::ValueTypes::MemSize(MachineType::Type()), inputs[0], offset,     \
    4222             :         position);                                                             \
    4223             :     node = graph()->NewNode(                                                   \
    4224             :         mcgraph()->machine()->Prefix##AtomicStore(MachineRepresentation::Rep), \
    4225             :         MemBuffer(offset), index, inputs[1], Effect(), Control());             \
    4226             :     break;                                                                     \
    4227             :   }
    4228       17771 :     ATOMIC_STORE_LIST(BUILD_ATOMIC_STORE_OP)
    4229             : #undef BUILD_ATOMIC_STORE_OP
    4230             :     case wasm::kExprAtomicWake: {
    4231             :       Node* index = CheckBoundsAndAlignment(
    4232             :           wasm::ValueTypes::MemSize(MachineType::Uint32()), inputs[0], offset,
    4233         360 :           position);
    4234             :       // Now that we've bounds-checked, compute the effective address.
    4235             :       Node* address = graph()->NewNode(mcgraph()->machine()->Int32Add(),
    4236         180 :                                        Uint32Constant(offset), index);
    4237             :       WasmAtomicWakeDescriptor interface_descriptor;
    4238             :       auto call_descriptor = Linkage::GetStubCallDescriptor(
    4239             :           mcgraph()->zone(), interface_descriptor,
    4240             :           interface_descriptor.GetStackParameterCount(),
    4241             :           CallDescriptor::kNoFlags, Operator::kNoProperties,
    4242         180 :           StubCallMode::kCallWasmRuntimeStub);
    4243             :       Node* call_target = mcgraph()->RelocatableIntPtrConstant(
    4244         180 :           wasm::WasmCode::kWasmAtomicWake, RelocInfo::WASM_STUB_CALL);
    4245             :       node = graph()->NewNode(mcgraph()->common()->Call(call_descriptor),
    4246             :                               call_target, address, inputs[1], Effect(),
    4247         360 :                               Control());
    4248             :       break;
    4249             :     }
    4250             : 
    4251             :     case wasm::kExprI32AtomicWait: {
    4252             :       Node* index = CheckBoundsAndAlignment(
    4253             :           wasm::ValueTypes::MemSize(MachineType::Uint32()), inputs[0], offset,
    4254         563 :           position);
    4255             :       // Now that we've bounds-checked, compute the effective address.
    4256             :       Node* address = graph()->NewNode(mcgraph()->machine()->Int32Add(),
    4257         288 :                                        Uint32Constant(offset), index);
    4258             :       Node* timeout;
    4259         574 :       if (mcgraph()->machine()->Is32()) {
    4260           0 :         timeout = BuildF64SConvertI64(inputs[2]);
    4261             :       } else {
    4262             :         timeout = graph()->NewNode(mcgraph()->machine()->RoundInt64ToFloat64(),
    4263         287 :                                    inputs[2]);
    4264             :       }
    4265             :       WasmI32AtomicWaitDescriptor interface_descriptor;
    4266             :       auto call_descriptor = Linkage::GetStubCallDescriptor(
    4267             :           mcgraph()->zone(), interface_descriptor,
    4268             :           interface_descriptor.GetStackParameterCount(),
    4269             :           CallDescriptor::kNoFlags, Operator::kNoProperties,
    4270         288 :           StubCallMode::kCallWasmRuntimeStub);
    4271             :       Node* call_target = mcgraph()->RelocatableIntPtrConstant(
    4272         286 :           wasm::WasmCode::kWasmI32AtomicWait, RelocInfo::WASM_STUB_CALL);
    4273             :       node = graph()->NewNode(mcgraph()->common()->Call(call_descriptor),
    4274             :                               call_target, address, inputs[1], timeout,
    4275         576 :                               Effect(), Control());
    4276             :       break;
    4277             :     }
    4278             : 
    4279             :     case wasm::kExprI64AtomicWait: {
    4280             :       Node* index = CheckBoundsAndAlignment(
    4281             :           wasm::ValueTypes::MemSize(MachineType::Uint32()), inputs[0], offset,
    4282         561 :           position);
    4283             :       // Now that we've bounds-checked, compute the effective address.
    4284             :       Node* address = graph()->NewNode(mcgraph()->machine()->Int32Add(),
    4285         288 :                                        Uint32Constant(offset), index);
    4286             :       Node* timeout;
    4287         576 :       if (mcgraph()->machine()->Is32()) {
    4288           0 :         timeout = BuildF64SConvertI64(inputs[2]);
    4289             :       } else {
    4290             :         timeout = graph()->NewNode(mcgraph()->machine()->RoundInt64ToFloat64(),
    4291         288 :                                    inputs[2]);
    4292             :       }
    4293             :       Node* expected_value_low = graph()->NewNode(
    4294         570 :           mcgraph()->machine()->TruncateInt64ToInt32(), inputs[1]);
    4295             :       Node* tmp = graph()->NewNode(mcgraph()->machine()->Word64Shr(), inputs[1],
    4296         574 :                                    Int64Constant(32));
    4297             :       Node* expected_value_high =
    4298         288 :           graph()->NewNode(mcgraph()->machine()->TruncateInt64ToInt32(), tmp);
    4299             :       WasmI64AtomicWaitDescriptor interface_descriptor;
    4300             :       auto call_descriptor = Linkage::GetStubCallDescriptor(
    4301             :           mcgraph()->zone(), interface_descriptor,
    4302             :           interface_descriptor.GetStackParameterCount(),
    4303             :           CallDescriptor::kNoFlags, Operator::kNoProperties,
    4304         288 :           StubCallMode::kCallWasmRuntimeStub);
    4305             :       Node* call_target = mcgraph()->RelocatableIntPtrConstant(
    4306         285 :           wasm::WasmCode::kWasmI64AtomicWait, RelocInfo::WASM_STUB_CALL);
    4307             :       node = graph()->NewNode(mcgraph()->common()->Call(call_descriptor),
    4308             :                               call_target, address, expected_value_high,
    4309         288 :                               expected_value_low, timeout, Effect(), Control());
    4310             :       break;
    4311             :     }
    4312             : 
    4313             :     default:
    4314           0 :       FATAL_UNSUPPORTED_OPCODE(opcode);
    4315             :   }
    4316       33602 :   return SetEffect(node);
    4317             : }
    4318             : 
    4319             : #undef ATOMIC_BINOP_LIST
    4320             : #undef ATOMIC_CMP_EXCHG_LIST
    4321             : #undef ATOMIC_LOAD_LIST
    4322             : #undef ATOMIC_STORE_LIST
    4323             : 
    4324          72 : Node* WasmGraphBuilder::CheckDataSegmentIsPassiveAndNotDropped(
    4325         720 :     uint32_t data_segment_index, wasm::WasmCodePosition position) {
    4326             :   // The data segment index must be in bounds since it is required by
    4327             :   // validation.
    4328             :   DCHECK_LT(data_segment_index, env_->module->num_declared_data_segments);
    4329             : 
    4330             :   Node* dropped_data_segments =
    4331         144 :       LOAD_INSTANCE_FIELD(DroppedDataSegments, MachineType::Pointer());
    4332             :   Node* is_segment_dropped = SetEffect(graph()->NewNode(
    4333             :       mcgraph()->machine()->Load(MachineType::Uint8()), dropped_data_segments,
    4334         216 :       mcgraph()->IntPtrConstant(data_segment_index), Effect(), Control()));
    4335          72 :   TrapIfTrue(wasm::kTrapDataSegmentDropped, is_segment_dropped, position);
    4336          72 :   return dropped_data_segments;
    4337             : }
    4338             : 
    4339          45 : Node* WasmGraphBuilder::MemoryInit(uint32_t data_segment_index, Node* dst,
    4340             :                                    Node* src, Node* size,
    4341         810 :                                    wasm::WasmCodePosition position) {
    4342          45 :   CheckDataSegmentIsPassiveAndNotDropped(data_segment_index, position);
    4343          45 :   dst = BoundsCheckMemRange(dst, size, position);
    4344          45 :   MachineOperatorBuilder* m = mcgraph()->machine();
    4345             : 
    4346             :   Node* seg_index = Uint32Constant(data_segment_index);
    4347             : 
    4348             :   {
    4349             :     // Load segment size from WasmInstanceObject::data_segment_sizes.
    4350             :     Node* seg_size_array =
    4351          90 :         LOAD_INSTANCE_FIELD(DataSegmentSizes, MachineType::Pointer());
    4352             :     STATIC_ASSERT(wasm::kV8MaxWasmDataSegments <= kMaxUInt32 >> 2);
    4353             :     Node* scaled_index = Uint32ToUintptr(
    4354          90 :         graph()->NewNode(m->Word32Shl(), seg_index, Int32Constant(2)));
    4355             :     Node* seg_size = SetEffect(graph()->NewNode(m->Load(MachineType::Uint32()),
    4356             :                                                 seg_size_array, scaled_index,
    4357          45 :                                                 Effect(), Control()));
    4358             : 
    4359             :     // Bounds check the src index against the segment size.
    4360          45 :     BoundsCheckRange(src, size, seg_size, position);
    4361             :   }
    4362             : 
    4363             :   {
    4364             :     // Load segment's base pointer from WasmInstanceObject::data_segment_starts.
    4365             :     Node* seg_start_array =
    4366          90 :         LOAD_INSTANCE_FIELD(DataSegmentStarts, MachineType::Pointer());
    4367             :     STATIC_ASSERT(wasm::kV8MaxWasmDataSegments <= kMaxUInt32 >>
    4368             :                   kPointerSizeLog2);
    4369             :     Node* scaled_index = Uint32ToUintptr(graph()->NewNode(
    4370          90 :         m->Word32Shl(), seg_index, Int32Constant(kPointerSizeLog2)));
    4371             :     Node* seg_start = SetEffect(
    4372             :         graph()->NewNode(m->Load(MachineType::Pointer()), seg_start_array,
    4373          45 :                          scaled_index, Effect(), Control()));
    4374             : 
    4375             :     // Convert src index to pointer.
    4376          45 :     src = graph()->NewNode(m->IntAdd(), seg_start, Uint32ToUintptr(src));
    4377             :   }
    4378             : 
    4379             :   Node* function = graph()->NewNode(mcgraph()->common()->ExternalConstant(
    4380         135 :       ExternalReference::wasm_memory_copy()));
    4381             :   MachineType sig_types[] = {MachineType::Pointer(), MachineType::Pointer(),
    4382          45 :                              MachineType::Uint32()};
    4383             :   MachineSignature sig(0, 3, sig_types);
    4384          45 :   return BuildCCall(&sig, function, dst, src, size);
    4385             : }
    4386             : 
    4387          27 : Node* WasmGraphBuilder::MemoryDrop(uint32_t data_segment_index,
    4388         162 :                                    wasm::WasmCodePosition position) {
    4389             :   Node* dropped_data_segments =
    4390          27 :       CheckDataSegmentIsPassiveAndNotDropped(data_segment_index, position);
    4391             :   const Operator* store_op = mcgraph()->machine()->Store(
    4392          27 :       StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier));
    4393             :   return SetEffect(
    4394             :       graph()->NewNode(store_op, dropped_data_segments,
    4395             :                        mcgraph()->IntPtrConstant(data_segment_index),
    4396          81 :                        mcgraph()->Int32Constant(1), Effect(), Control()));
    4397             : }
    4398             : 
    4399          27 : Node* WasmGraphBuilder::MemoryCopy(Node* dst, Node* src, Node* size,
    4400          27 :                                    wasm::WasmCodePosition position) {
    4401          27 :   dst = BoundsCheckMemRange(dst, size, position);
    4402          27 :   src = BoundsCheckMemRange(src, size, position);
    4403             :   Node* function = graph()->NewNode(mcgraph()->common()->ExternalConstant(
    4404          81 :       ExternalReference::wasm_memory_copy()));
    4405             :   MachineType sig_types[] = {MachineType::Pointer(), MachineType::Pointer(),
    4406          27 :                              MachineType::Uint32()};
    4407             :   MachineSignature sig(0, 3, sig_types);
    4408          27 :   return BuildCCall(&sig, function, dst, src, size);
    4409             : }
    4410             : 
    4411          27 : Node* WasmGraphBuilder::MemoryFill(Node* dst, Node* value, Node* size,
    4412          27 :                                    wasm::WasmCodePosition position) {
    4413          27 :   dst = BoundsCheckMemRange(dst, size, position);
    4414             :   Node* function = graph()->NewNode(mcgraph()->common()->ExternalConstant(
    4415          81 :       ExternalReference::wasm_memory_fill()));
    4416             :   MachineType sig_types[] = {MachineType::Pointer(), MachineType::Uint32(),
    4417          27 :                              MachineType::Uint32()};
    4418             :   MachineSignature sig(0, 3, sig_types);
    4419          27 :   return BuildCCall(&sig, function, dst, value, size);
    4420             : }
    4421             : 
    4422          18 : Node* WasmGraphBuilder::CheckElemSegmentIsPassiveAndNotDropped(
    4423         180 :     uint32_t elem_segment_index, wasm::WasmCodePosition position) {
    4424             :   // The elem segment index must be in bounds since it is required by
    4425             :   // validation.
    4426             :   DCHECK_LT(elem_segment_index, env_->module->elem_segments.size());
    4427             : 
    4428             :   Node* dropped_elem_segments =
    4429          36 :       LOAD_INSTANCE_FIELD(DroppedElemSegments, MachineType::Pointer());
    4430             :   Node* is_segment_dropped = SetEffect(graph()->NewNode(
    4431             :       mcgraph()->machine()->Load(MachineType::Uint8()), dropped_elem_segments,
    4432          54 :       mcgraph()->IntPtrConstant(elem_segment_index), Effect(), Control()));
    4433          18 :   TrapIfTrue(wasm::kTrapElemSegmentDropped, is_segment_dropped, position);
    4434          18 :   return dropped_elem_segments;
    4435             : }
    4436             : 
    4437           9 : Node* WasmGraphBuilder::TableInit(uint32_t table_index,
    4438             :                                   uint32_t elem_segment_index, Node* dst,
    4439             :                                   Node* src, Node* size,
    4440          18 :                                   wasm::WasmCodePosition position) {
    4441             :   Node* args[] = {
    4442          18 :       graph()->NewNode(mcgraph()->common()->NumberConstant(table_index)),
    4443          18 :       graph()->NewNode(mcgraph()->common()->NumberConstant(elem_segment_index)),
    4444           9 :       BuildConvertUint32ToSmiWithSaturation(dst, wasm::kV8MaxWasmTableSize),
    4445           9 :       BuildConvertUint32ToSmiWithSaturation(src, wasm::kV8MaxWasmTableSize),
    4446          36 :       BuildConvertUint32ToSmiWithSaturation(size, wasm::kV8MaxWasmTableSize)};
    4447             :   Node* result =
    4448           9 :       BuildCallToRuntime(Runtime::kWasmTableInit, args, arraysize(args));
    4449             : 
    4450           9 :   return result;
    4451             : }
    4452             : 
    4453          18 : Node* WasmGraphBuilder::TableDrop(uint32_t elem_segment_index,
    4454         108 :                                   wasm::WasmCodePosition position) {
    4455             :   Node* dropped_elem_segments =
    4456          18 :       CheckElemSegmentIsPassiveAndNotDropped(elem_segment_index, position);
    4457             :   const Operator* store_op = mcgraph()->machine()->Store(
    4458          18 :       StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier));
    4459             :   return SetEffect(
    4460             :       graph()->NewNode(store_op, dropped_elem_segments,
    4461             :                        mcgraph()->IntPtrConstant(elem_segment_index),
    4462          54 :                        mcgraph()->Int32Constant(1), Effect(), Control()));
    4463             : }
    4464             : 
    4465          72 : Node* WasmGraphBuilder::TableCopy(uint32_t table_index, Node* dst, Node* src,
    4466          72 :                                   Node* size, wasm::WasmCodePosition position) {
    4467             :   Node* args[] = {
    4468         144 :       graph()->NewNode(mcgraph()->common()->NumberConstant(table_index)),
    4469          72 :       BuildConvertUint32ToSmiWithSaturation(dst, wasm::kV8MaxWasmTableSize),
    4470          72 :       BuildConvertUint32ToSmiWithSaturation(src, wasm::kV8MaxWasmTableSize),
    4471         216 :       BuildConvertUint32ToSmiWithSaturation(size, wasm::kV8MaxWasmTableSize)};
    4472             :   Node* result =
    4473          72 :       BuildCallToRuntime(Runtime::kWasmTableCopy, args, arraysize(args));
    4474             : 
    4475          72 :   return result;
    4476             : }
    4477             : 
    4478           0 : class WasmDecorator final : public GraphDecorator {
    4479             :  public:
    4480             :   explicit WasmDecorator(NodeOriginTable* origins, wasm::Decoder* decoder)
    4481           0 :       : origins_(origins), decoder_(decoder) {}
    4482             : 
    4483           0 :   void Decorate(Node* node) final {
    4484             :     origins_->SetNodeOrigin(
    4485             :         node, NodeOrigin("wasm graph creation", "n/a",
    4486           0 :                          NodeOrigin::kWasmBytecode, decoder_->position()));
    4487           0 :   }
    4488             : 
    4489             :  private:
    4490             :   compiler::NodeOriginTable* origins_;
    4491             :   wasm::Decoder* decoder_;
    4492             : };
    4493             : 
    4494           0 : void WasmGraphBuilder::AddBytecodePositionDecorator(
    4495             :     NodeOriginTable* node_origins, wasm::Decoder* decoder) {
    4496             :   DCHECK_NULL(decorator_);
    4497           0 :   decorator_ = new (graph()->zone()) WasmDecorator(node_origins, decoder);
    4498           0 :   graph()->AddDecorator(decorator_);
    4499           0 : }
    4500             : 
    4501           0 : void WasmGraphBuilder::RemoveBytecodePositionDecorator() {
    4502             :   DCHECK_NOT_NULL(decorator_);
    4503           0 :   graph()->RemoveDecorator(decorator_);
    4504           0 :   decorator_ = nullptr;
    4505           0 : }
    4506             : 
    4507             : namespace {
    4508      313944 : bool must_record_function_compilation(Isolate* isolate) {
    4509      313944 :   return isolate->logger()->is_listening_to_code_events() ||
    4510             :          isolate->is_profiling();
    4511             : }
    4512             : 
    4513             : PRINTF_FORMAT(4, 5)
    4514           0 : void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
    4515             :                                Isolate* isolate, Handle<Code> code,
    4516             :                                const char* format, ...) {
    4517             :   DCHECK(must_record_function_compilation(isolate));
    4518             : 
    4519             :   ScopedVector<char> buffer(128);
    4520             :   va_list arguments;
    4521           0 :   va_start(arguments, format);
    4522           0 :   int len = VSNPrintF(buffer, format, arguments);
    4523           0 :   CHECK_LT(0, len);
    4524           0 :   va_end(arguments);
    4525             :   Handle<String> name_str =
    4526           0 :       isolate->factory()->NewStringFromAsciiChecked(buffer.start());
    4527           0 :   PROFILE(isolate, CodeCreateEvent(tag, AbstractCode::cast(*code), *name_str));
    4528           0 : }
    4529             : 
    4530             : class WasmWrapperGraphBuilder : public WasmGraphBuilder {
    4531             :  public:
    4532      166068 :   WasmWrapperGraphBuilder(Zone* zone, JSGraph* jsgraph, wasm::FunctionSig* sig,
    4533             :                           compiler::SourcePositionTable* spt,
    4534             :                           StubCallMode stub_mode, wasm::WasmFeatures features)
    4535             :       : WasmGraphBuilder(nullptr, zone, jsgraph, sig, spt),
    4536             :         isolate_(jsgraph->isolate()),
    4537             :         jsgraph_(jsgraph),
    4538             :         stub_mode_(stub_mode),
    4539      332136 :         enabled_features_(features) {}
    4540             : 
    4541       55446 :   Node* BuildAllocateHeapNumberWithValue(Node* value, Node* control) {
    4542      152474 :     MachineOperatorBuilder* machine = mcgraph()->machine();
    4543       46422 :     CommonOperatorBuilder* common = mcgraph()->common();
    4544       46422 :     Node* target = (stub_mode_ == StubCallMode::kCallWasmRuntimeStub)
    4545             :                        ? mcgraph()->RelocatableIntPtrConstant(
    4546             :                              wasm::WasmCode::kWasmAllocateHeapNumber,
    4547             :                              RelocInfo::WASM_STUB_CALL)
    4548             :                        : jsgraph()->HeapConstant(
    4549       55446 :                              BUILTIN_CODE(isolate_, AllocateHeapNumber));
    4550       46422 :     if (!allocate_heap_number_operator_.is_set()) {
    4551             :       auto call_descriptor = Linkage::GetStubCallDescriptor(
    4552             :           mcgraph()->zone(), AllocateHeapNumberDescriptor(), 0,
    4553       39624 :           CallDescriptor::kNoFlags, Operator::kNoThrow, stub_mode_);
    4554       13208 :       allocate_heap_number_operator_.set(common->Call(call_descriptor));
    4555             :     }
    4556             :     Node* heap_number = graph()->NewNode(allocate_heap_number_operator_.get(),
    4557             :                                          target, Effect(), control);
    4558             :     SetEffect(
    4559             :         graph()->NewNode(machine->Store(StoreRepresentation(
    4560             :                              MachineRepresentation::kFloat64, kNoWriteBarrier)),
    4561             :                          heap_number, BuildHeapNumberValueIndexConstant(),
    4562       92844 :                          value, heap_number, control));
    4563       46422 :     return heap_number;
    4564             :   }
    4565             : 
    4566       94942 :   Node* BuildChangeSmiToFloat64(Node* value) {
    4567             :     return graph()->NewNode(mcgraph()->machine()->ChangeInt32ToFloat64(),
    4568      189886 :                             BuildChangeSmiToInt32(value));
    4569             :   }
    4570             : 
    4571       94944 :   Node* BuildTestHeapObject(Node* value) {
    4572             :     return graph()->NewNode(mcgraph()->machine()->WordAnd(), value,
    4573      189893 :                             mcgraph()->IntPtrConstant(kHeapObjectTag));
    4574             :   }
    4575             : 
    4576       94947 :   Node* BuildLoadHeapNumberValue(Node* value) {
    4577             :     return SetEffect(graph()->NewNode(
    4578             :         mcgraph()->machine()->Load(MachineType::Float64()), value,
    4579      474737 :         BuildHeapNumberValueIndexConstant(), Effect(), Control()));
    4580             :   }
    4581             : 
    4582             :   Node* BuildHeapNumberValueIndexConstant() {
    4583      141369 :     return mcgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag);
    4584             :   }
    4585             : 
    4586             :   Node* BuildChangeInt32ToTagged(Node* value) {
    4587             :     MachineOperatorBuilder* machine = mcgraph()->machine();
    4588             :     CommonOperatorBuilder* common = mcgraph()->common();
    4589             : 
    4590             :     if (SmiValuesAre32Bits()) {
    4591       27012 :       return BuildChangeInt32ToSmi(value);
    4592             :     }
    4593             :     DCHECK(SmiValuesAre31Bits());
    4594             : 
    4595             :     Node* effect = Effect();
    4596             :     Node* control = Control();
    4597             :     Node* add = graph()->NewNode(machine->Int32AddWithOverflow(), value, value,
    4598             :                                  graph()->start());
    4599             : 
    4600             :     Node* ovf = graph()->NewNode(common->Projection(1), add, graph()->start());
    4601             :     Node* branch =
    4602             :         graph()->NewNode(common->Branch(BranchHint::kFalse), ovf, control);
    4603             : 
    4604             :     Node* if_true = graph()->NewNode(common->IfTrue(), branch);
    4605             :     Node* vtrue = BuildAllocateHeapNumberWithValue(
    4606             :         graph()->NewNode(machine->ChangeInt32ToFloat64(), value), if_true);
    4607             :     Node* etrue = Effect();
    4608             : 
    4609             :     Node* if_false = graph()->NewNode(common->IfFalse(), branch);
    4610             :     Node* vfalse = graph()->NewNode(common->Projection(0), add, if_false);
    4611             :     vfalse = BuildChangeInt32ToIntPtr(vfalse);
    4612             : 
    4613             :     Node* merge =
    4614             :         SetControl(graph()->NewNode(common->Merge(2), if_true, if_false));
    4615             :     SetEffect(graph()->NewNode(common->EffectPhi(2), etrue, effect, merge));
    4616             :     return graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2),
    4617             :                             vtrue, vfalse, merge);
    4618             :   }
    4619             : 
    4620       46422 :   Node* BuildChangeFloat64ToTagged(Node* value) {
    4621      371376 :     MachineOperatorBuilder* machine = mcgraph()->machine();
    4622       46422 :     CommonOperatorBuilder* common = mcgraph()->common();
    4623             : 
    4624             :     // Check several conditions:
    4625             :     //  i32?
    4626             :     //  ├─ true: zero?
    4627             :     //  │        ├─ true: negative?
    4628             :     //  │        │        ├─ true: box
    4629             :     //  │        │        └─ false: potentially Smi
    4630             :     //  │        └─ false: potentially Smi
    4631             :     //  └─ false: box
    4632             :     // For potential Smi values, depending on whether Smis are 31 or 32 bit, we
    4633             :     // still need to check whether the value fits in a Smi.
    4634             : 
    4635             :     Node* effect = Effect();
    4636             :     Node* control = Control();
    4637       46422 :     Node* value32 = graph()->NewNode(machine->RoundFloat64ToInt32(), value);
    4638             :     Node* check_i32 = graph()->NewNode(
    4639             :         machine->Float64Equal(), value,
    4640       92844 :         graph()->NewNode(machine->ChangeInt32ToFloat64(), value32));
    4641       46422 :     Node* branch_i32 = graph()->NewNode(common->Branch(), check_i32, control);
    4642             : 
    4643       46422 :     Node* if_i32 = graph()->NewNode(common->IfTrue(), branch_i32);
    4644       46422 :     Node* if_not_i32 = graph()->NewNode(common->IfFalse(), branch_i32);
    4645             : 
    4646             :     // We only need to check for -0 if the {value} can potentially contain -0.
    4647             :     Node* check_zero = graph()->NewNode(machine->Word32Equal(), value32,
    4648       46422 :                                         mcgraph()->Int32Constant(0));
    4649             :     Node* branch_zero = graph()->NewNode(common->Branch(BranchHint::kFalse),
    4650       46422 :                                          check_zero, if_i32);
    4651             : 
    4652       46422 :     Node* if_zero = graph()->NewNode(common->IfTrue(), branch_zero);
    4653       46422 :     Node* if_not_zero = graph()->NewNode(common->IfFalse(), branch_zero);
    4654             : 
    4655             :     // In case of 0, we need to check the high bits for the IEEE -0 pattern.
    4656             :     Node* check_negative = graph()->NewNode(
    4657             :         machine->Int32LessThan(),
    4658             :         graph()->NewNode(machine->Float64ExtractHighWord32(), value),
    4659       92844 :         mcgraph()->Int32Constant(0));
    4660             :     Node* branch_negative = graph()->NewNode(common->Branch(BranchHint::kFalse),
    4661       46422 :                                              check_negative, if_zero);
    4662             : 
    4663       46422 :     Node* if_negative = graph()->NewNode(common->IfTrue(), branch_negative);
    4664             :     Node* if_not_negative =
    4665       46422 :         graph()->NewNode(common->IfFalse(), branch_negative);
    4666             : 
    4667             :     // We need to create a box for negative 0.
    4668             :     Node* if_smi =
    4669       46422 :         graph()->NewNode(common->Merge(2), if_not_zero, if_not_negative);
    4670       46422 :     Node* if_box = graph()->NewNode(common->Merge(2), if_not_i32, if_negative);
    4671             : 
    4672             :     // On 64-bit machines we can just wrap the 32-bit integer in a smi, for
    4673             :     // 32-bit machines we need to deal with potential overflow and fallback to
    4674             :     // boxing.
    4675             :     Node* vsmi;
    4676             :     if (SmiValuesAre32Bits()) {
    4677       46422 :       vsmi = BuildChangeInt32ToSmi(value32);
    4678             :     } else {
    4679             :       DCHECK(SmiValuesAre31Bits());
    4680             :       Node* smi_tag = graph()->NewNode(machine->Int32AddWithOverflow(), value32,
    4681             :                                        value32, if_smi);
    4682             : 
    4683             :       Node* check_ovf =
    4684             :           graph()->NewNode(common->Projection(1), smi_tag, if_smi);
    4685             :       Node* branch_ovf = graph()->NewNode(common->Branch(BranchHint::kFalse),
    4686             :                                           check_ovf, if_smi);
    4687             : 
    4688             :       Node* if_ovf = graph()->NewNode(common->IfTrue(), branch_ovf);
    4689             :       if_box = graph()->NewNode(common->Merge(2), if_ovf, if_box);
    4690             : 
    4691             :       if_smi = graph()->NewNode(common->IfFalse(), branch_ovf);
    4692             :       vsmi = graph()->NewNode(common->Projection(0), smi_tag, if_smi);
    4693             :       vsmi = BuildChangeInt32ToIntPtr(vsmi);
    4694             :     }
    4695             : 
    4696             :     // Allocate the box for the {value}.
    4697       46422 :     Node* vbox = BuildAllocateHeapNumberWithValue(value, if_box);
    4698             :     Node* ebox = Effect();
    4699             : 
    4700             :     Node* merge =
    4701       46422 :         SetControl(graph()->NewNode(common->Merge(2), if_smi, if_box));
    4702       46422 :     SetEffect(graph()->NewNode(common->EffectPhi(2), effect, ebox, merge));
    4703             :     return graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2),
    4704       92844 :                             vsmi, vbox, merge);
    4705             :   }
    4706             : 
    4707        7015 :   int AddArgumentNodes(Node** args, int pos, int param_count,
    4708       49721 :                        wasm::FunctionSig* sig) {
    4709             :     // Convert wasm numbers to JS values.
    4710       63751 :     for (int i = 0; i < param_count; ++i) {
    4711             :       Node* param =
    4712       49721 :           Param(i + 1);  // Start from index 1 to drop the instance_node.
    4713       99442 :       args[pos++] = ToJS(param, sig->GetParam(i));
    4714             :     }
    4715        7015 :     return pos;
    4716             :   }
    4717             : 
    4718      185860 :   Node* BuildJavaScriptToNumber(Node* node, Node* js_context) {
    4719             :     auto call_descriptor = Linkage::GetStubCallDescriptor(
    4720             :         mcgraph()->zone(), TypeConversionDescriptor{}, 0,
    4721      763602 :         CallDescriptor::kNoFlags, Operator::kNoProperties, stub_mode_);
    4722             :     Node* stub_code =
    4723       94947 :         (stub_mode_ == StubCallMode::kCallWasmRuntimeStub)
    4724             :             ? mcgraph()->RelocatableIntPtrConstant(
    4725             :                   wasm::WasmCode::kWasmToNumber, RelocInfo::WASM_STUB_CALL)
    4726      189895 :             : jsgraph()->HeapConstant(BUILTIN_CODE(isolate_, ToNumber));
    4727             : 
    4728             :     Node* result = SetEffect(
    4729             :         graph()->NewNode(mcgraph()->common()->Call(call_descriptor), stub_code,
    4730       94947 :                          node, js_context, Effect(), Control()));
    4731             : 
    4732       94946 :     SetSourcePosition(result, 1);
    4733             : 
    4734       94947 :     return result;
    4735             :   }
    4736             : 
    4737       94945 :   Node* BuildChangeTaggedToFloat64(Node* value) {
    4738     1424172 :     MachineOperatorBuilder* machine = mcgraph()->machine();
    4739       94945 :     CommonOperatorBuilder* common = mcgraph()->common();
    4740             : 
    4741             :     // Implement the following decision tree:
    4742             :     //  heap object?
    4743             :     //  ├─ true: undefined?
    4744             :     //  │        ├─ true: f64 const
    4745             :     //  │        └─ false: load heap number value
    4746             :     //  └─ false: smi to float64
    4747             : 
    4748       94945 :     Node* check_heap_object = BuildTestHeapObject(value);
    4749             :     Diamond is_heap_object(graph(), common, check_heap_object,
    4750       94949 :                            BranchHint::kFalse);
    4751       94942 :     is_heap_object.Chain(Control());
    4752             : 
    4753       94944 :     SetControl(is_heap_object.if_true);
    4754             :     Node* orig_effect = Effect();
    4755             : 
    4756             :     Node* undefined_node =
    4757      189893 :         LOAD_INSTANCE_FIELD(UndefinedValue, MachineType::TaggedPointer());
    4758             :     Node* check_undefined =
    4759       94949 :         graph()->NewNode(machine->WordEqual(), value, undefined_node);
    4760             :     Node* effect_tagged = Effect();
    4761             : 
    4762       94941 :     Diamond is_undefined(graph(), common, check_undefined, BranchHint::kFalse);
    4763       94948 :     is_undefined.Nest(is_heap_object, true);
    4764             : 
    4765       94947 :     SetControl(is_undefined.if_false);
    4766       94947 :     Node* vheap_number = BuildLoadHeapNumberValue(value);
    4767             :     Node* effect_undefined = Effect();
    4768             : 
    4769       94946 :     SetControl(is_undefined.merge);
    4770             :     Node* vundefined =
    4771       94946 :         mcgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
    4772             :     Node* vtagged = is_undefined.Phi(MachineRepresentation::kFloat64,
    4773       94949 :                                      vundefined, vheap_number);
    4774             : 
    4775       94944 :     effect_tagged = is_undefined.EffectPhi(effect_tagged, effect_undefined);
    4776             : 
    4777             :     // If input is Smi: just convert to float64.
    4778       94946 :     Node* vfrom_smi = BuildChangeSmiToFloat64(value);
    4779             : 
    4780       94944 :     SetControl(is_heap_object.merge);
    4781       94944 :     SetEffect(is_heap_object.EffectPhi(effect_tagged, orig_effect));
    4782             :     return is_heap_object.Phi(MachineRepresentation::kFloat64, vtagged,
    4783       94941 :                               vfrom_smi);
    4784             :   }
    4785             : 
    4786       73752 :   Node* ToJS(Node* node, wasm::ValueType type) {
    4787       73752 :     switch (type) {
    4788             :       case wasm::kWasmI32:
    4789       27009 :         return BuildChangeInt32ToTagged(node);
    4790             :       case wasm::kWasmS128:
    4791           0 :         UNREACHABLE();
    4792             :       case wasm::kWasmI64: {
    4793             :         DCHECK(enabled_features_.bigint);
    4794          36 :         return BuildChangeInt64ToBigInt(node);
    4795             :       }
    4796             :       case wasm::kWasmF32:
    4797             :         node = graph()->NewNode(mcgraph()->machine()->ChangeFloat32ToFloat64(),
    4798       12419 :                                 node);
    4799       12419 :         return BuildChangeFloat64ToTagged(node);
    4800             :       case wasm::kWasmF64:
    4801       34003 :         return BuildChangeFloat64ToTagged(node);
    4802             :       case wasm::kWasmAnyRef:
    4803             :       case wasm::kWasmAnyFunc:
    4804             :         return node;
    4805             :       default:
    4806           0 :         UNREACHABLE();
    4807             :     }
    4808             :   }
    4809             : 
    4810          63 :   Node* BuildChangeInt64ToBigInt(Node* input) {
    4811             :     BigIntToWasmI64Descriptor interface_descriptor;
    4812             : 
    4813             :     auto call_descriptor = Linkage::GetStubCallDescriptor(
    4814             :         mcgraph()->zone(),                              // zone
    4815             :         interface_descriptor,                           // descriptor
    4816             :         interface_descriptor.GetStackParameterCount(),  // stack parameter count
    4817             :         CallDescriptor::kNoFlags,                       // flags
    4818             :         Operator::kNoProperties,                        // properties
    4819         297 :         stub_mode_);                                    // stub call mode
    4820             : 
    4821             :     Node* target =
    4822          36 :         (stub_mode_ == StubCallMode::kCallWasmRuntimeStub)
    4823             :             ? mcgraph()->RelocatableIntPtrConstant(
    4824             :                   wasm::WasmCode::kBigIntToWasmI64, RelocInfo::WASM_STUB_CALL)
    4825          72 :             : jsgraph()->HeapConstant(BUILTIN_CODE(isolate_, I64ToBigInt));
    4826             : 
    4827             :     return SetEffect(
    4828             :         SetControl(graph()->NewNode(mcgraph()->common()->Call(call_descriptor),
    4829          72 :                                     target, input, Effect(), Control())));
    4830             :   }
    4831             : 
    4832          27 :   Node* BuildChangeBigIntToInt64(Node* input, Node* context) {
    4833             :     BigIntToI64Descriptor interface_descriptor;
    4834             : 
    4835             :     auto call_descriptor = Linkage::GetStubCallDescriptor(
    4836             :         mcgraph()->zone(),                              // zone
    4837             :         interface_descriptor,                           // descriptor
    4838             :         interface_descriptor.GetStackParameterCount(),  // stack parameter count
    4839             :         CallDescriptor::kNoFlags,                       // flags
    4840             :         Operator::kNoProperties,                        // properties
    4841         153 :         stub_mode_);                                    // stub call mode
    4842             : 
    4843             :     Node* target =
    4844          18 :         (stub_mode_ == StubCallMode::kCallWasmRuntimeStub)
    4845             :             ? mcgraph()->RelocatableIntPtrConstant(
    4846             :                   wasm::WasmCode::kWasmBigIntToI64, RelocInfo::WASM_STUB_CALL)
    4847          36 :             : jsgraph()->HeapConstant(BUILTIN_CODE(isolate_, BigIntToI64));
    4848             : 
    4849             :     return SetEffect(SetControl(
    4850             :         graph()->NewNode(mcgraph()->common()->Call(call_descriptor), target,
    4851          36 :                          input, context, Effect(), Control())));
    4852             :   }
    4853             : 
    4854       95161 :   Node* FromJS(Node* node, Node* js_context, wasm::ValueType type) {
    4855             :     DCHECK_NE(wasm::kWasmStmt, type);
    4856             : 
    4857             :     // The parameter is of type AnyRef, we take it as is.
    4858       95161 :     if (type == wasm::kWasmAnyRef) {
    4859         180 :       return node;
    4860             :     }
    4861             : 
    4862       94981 :     if (type == wasm::kWasmAnyFunc) {
    4863             :       Node* check =
    4864             :           BuildChangeSmiToInt32(SetEffect(BuildCallToRuntimeWithContext(
    4865             :               Runtime::kWasmIsValidAnyFuncValue, js_context, &node, 1, effect_,
    4866       45893 :               Control())));
    4867             : 
    4868             :       Diamond type_check(graph(), mcgraph()->common(), check,
    4869          36 :                          BranchHint::kTrue);
    4870          18 :       type_check.Chain(Control());
    4871             : 
    4872          18 :       Node* effect = Effect();
    4873             :       BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError, js_context,
    4874          18 :                                     nullptr, 0, &effect, type_check.if_false);
    4875             : 
    4876          36 :       SetEffect(type_check.EffectPhi(Effect(), effect));
    4877             : 
    4878          18 :       SetControl(type_check.merge);
    4879             : 
    4880          18 :       return node;
    4881             :     }
    4882             :     Node* num = nullptr;
    4883             : 
    4884       94963 :     if (type != wasm::kWasmI64) {
    4885             :       // Do a JavaScript ToNumber.
    4886       94945 :       num = BuildJavaScriptToNumber(node, js_context);
    4887             : 
    4888             :       // Change representation.
    4889       94948 :       num = BuildChangeTaggedToFloat64(num);
    4890             :     }
    4891             : 
    4892       94957 :     switch (type) {
    4893             :       case wasm::kWasmI32: {
    4894             :         num = graph()->NewNode(mcgraph()->machine()->TruncateFloat64ToWord32(),
    4895       32138 :                                num);
    4896       32138 :         break;
    4897             :       }
    4898             :       case wasm::kWasmI64: {
    4899             :         DCHECK(enabled_features_.bigint);
    4900          18 :         num = BuildChangeBigIntToInt64(node, js_context);
    4901          18 :         break;
    4902             :       }
    4903             :       case wasm::kWasmF32:
    4904             :         num = graph()->NewNode(mcgraph()->machine()->TruncateFloat64ToFloat32(),
    4905       13611 :                                num);
    4906       13611 :         break;
    4907             :       case wasm::kWasmF64:
    4908             :         break;
    4909             :       case wasm::kWasmS128:
    4910           0 :         UNREACHABLE();
    4911             :       default:
    4912           0 :         UNREACHABLE();
    4913             :     }
    4914             :     DCHECK_NOT_NULL(num);
    4915             : 
    4916       94957 :     return num;
    4917             :   }
    4918             : 
    4919      326351 :   void BuildModifyThreadInWasmFlag(bool new_value) {
    4920      652666 :     if (!trap_handler::IsTrapHandlerEnabled()) return;
    4921             :     Node* isolate_root =
    4922     5217209 :         LOAD_INSTANCE_FIELD(IsolateRoot, MachineType::Pointer());
    4923             : 
    4924             :     Node* thread_in_wasm_flag_address =
    4925      652122 :         LOAD_RAW(isolate_root, Isolate::thread_in_wasm_flag_address_offset(),
    4926             :                  MachineType::Pointer());
    4927             : 
    4928      326062 :     if (FLAG_debug_code) {
    4929             :       Node* flag_value = SetEffect(
    4930             :           graph()->NewNode(mcgraph()->machine()->Load(MachineType::Pointer()),
    4931             :                            thread_in_wasm_flag_address,
    4932          36 :                            mcgraph()->Int32Constant(0), Effect(), Control()));
    4933             :       Node* check =
    4934             :           graph()->NewNode(mcgraph()->machine()->Word32Equal(), flag_value,
    4935          54 :                            mcgraph()->Int32Constant(new_value ? 0 : 1));
    4936             : 
    4937             :       Diamond flag_check(graph(), mcgraph()->common(), check,
    4938          36 :                          BranchHint::kTrue);
    4939          18 :       flag_check.Chain(Control());
    4940             :       Node* message_id = jsgraph()->SmiConstant(static_cast<int32_t>(
    4941             :           new_value ? AbortReason::kUnexpectedThreadInWasmSet
    4942          36 :                     : AbortReason::kUnexpectedThreadInWasmUnset));
    4943             : 
    4944          18 :       Node* effect = Effect();
    4945             :       BuildCallToRuntimeWithContext(Runtime::kAbort, NoContextConstant(),
    4946             :                                     &message_id, 1, &effect,
    4947          36 :                                     flag_check.if_false);
    4948             : 
    4949          36 :       SetEffect(flag_check.EffectPhi(Effect(), effect));
    4950             : 
    4951          18 :       SetControl(flag_check.merge);
    4952             :     }
    4953             : 
    4954             :     SetEffect(graph()->NewNode(
    4955             :         mcgraph()->machine()->Store(StoreRepresentation(
    4956             :             MachineRepresentation::kWord32, kNoWriteBarrier)),
    4957             :         thread_in_wasm_flag_address, mcgraph()->Int32Constant(0),
    4958     1630307 :         mcgraph()->Int32Constant(new_value ? 1 : 0), Effect(), Control()));
    4959             :   }
    4960             : 
    4961      784904 :   Node* BuildLoadFunctionDataFromExportedFunction(Node* closure) {
    4962             :     Node* shared = SetEffect(graph()->NewNode(
    4963             :         jsgraph()->machine()->Load(MachineType::AnyTagged()), closure,
    4964             :         jsgraph()->Int32Constant(
    4965             :             wasm::ObjectAccess::SharedFunctionInfoOffsetInTaggedJSFunction()),
    4966     1255847 :         Effect(), Control()));
    4967             :     return SetEffect(graph()->NewNode(
    4968             :         jsgraph()->machine()->Load(MachineType::AnyTagged()), shared,
    4969             :         jsgraph()->Int32Constant(SharedFunctionInfo::kFunctionDataOffset -
    4970             :                                  kHeapObjectTag),
    4971      470943 :         Effect(), Control()));
    4972             :   }
    4973             : 
    4974      470943 :   Node* BuildLoadInstanceFromExportedFunctionData(Node* function_data) {
    4975             :     return SetEffect(graph()->NewNode(
    4976             :         jsgraph()->machine()->Load(MachineType::AnyTagged()), function_data,
    4977             :         jsgraph()->Int32Constant(WasmExportedFunctionData::kInstanceOffset -
    4978             :                                  kHeapObjectTag),
    4979      941886 :         Effect(), Control()));
    4980             :   }
    4981             : 
    4982        1566 :   Node* BuildLoadFunctionIndexFromExportedFunctionData(Node* function_data) {
    4983             :     Node* function_index_smi = SetEffect(graph()->NewNode(
    4984             :         jsgraph()->machine()->Load(MachineType::AnyTagged()), function_data,
    4985             :         jsgraph()->Int32Constant(
    4986             :             WasmExportedFunctionData::kFunctionIndexOffset - kHeapObjectTag),
    4987        2610 :         Effect(), Control()));
    4988         522 :     Node* function_index = BuildChangeSmiToInt32(function_index_smi);
    4989         522 :     return function_index;
    4990             :   }
    4991             : 
    4992      466888 :   Node* BuildLoadJumpTableOffsetFromExportedFunctionData(Node* function_data) {
    4993             :     Node* jump_table_offset_smi = SetEffect(graph()->NewNode(
    4994             :         jsgraph()->machine()->Load(MachineType::AnyTagged()), function_data,
    4995             :         jsgraph()->Int32Constant(
    4996             :             WasmExportedFunctionData::kJumpTableOffsetOffset - kHeapObjectTag),
    4997      778147 :         Effect(), Control()));
    4998      155630 :     Node* jump_table_offset = BuildChangeSmiToInt32(jump_table_offset_smi);
    4999      155630 :     return jump_table_offset;
    5000             :   }
    5001             : 
    5002      446908 :   void BuildJSToWasmWrapper(bool is_import) {
    5003      428282 :     const int wasm_count = static_cast<int>(sig_->parameter_count());
    5004             : 
    5005             :     // Build the start and the JS parameter nodes.
    5006     1248552 :     SetEffect(SetControl(Start(wasm_count + 5)));
    5007             : 
    5008             :     // Create the js_closure and js_context parameters.
    5009             :     Node* js_closure =
    5010             :         graph()->NewNode(jsgraph()->common()->Parameter(
    5011             :                              Linkage::kJSCallClosureParamIndex, "%closure"),
    5012      313962 :                          graph()->start());
    5013             :     Node* js_context = graph()->NewNode(
    5014             :         mcgraph()->common()->Parameter(
    5015             :             Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"),
    5016      313962 :         graph()->start());
    5017             : 
    5018             :     // Create the instance_node node to pass as parameter. It is loaded from
    5019             :     // an actual reference to an instance or a placeholder reference,
    5020             :     // called {WasmExportedFunction} via the {WasmExportedFunctionData}
    5021             :     // structure.
    5022      156981 :     Node* function_data = BuildLoadFunctionDataFromExportedFunction(js_closure);
    5023             :     instance_node_.set(
    5024      156981 :         BuildLoadInstanceFromExportedFunctionData(function_data));
    5025             : 
    5026      156981 :     if (!wasm::IsJSCompatibleSignature(sig_, enabled_features_.bigint)) {
    5027             :       // Throw a TypeError. Use the js_context of the calling javascript
    5028             :       // function (passed as a parameter), such that the generated code is
    5029             :       // js_context independent.
    5030             :       BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError, js_context,
    5031         828 :                                     nullptr, 0, effect_, Control());
    5032             :       Return(jsgraph()->SmiConstant(0));
    5033      157809 :       return;
    5034             :     }
    5035             : 
    5036      156153 :     const int args_count = wasm_count + 1;  // +1 for wasm_code.
    5037      156153 :     Node** args = Buffer(args_count);
    5038             :     Node** rets;
    5039             : 
    5040             :     // Convert JS parameters to wasm numbers.
    5041      403427 :     for (int i = 0; i < wasm_count; ++i) {
    5042       91117 :       Node* param = Param(i + 1);
    5043      182242 :       Node* wasm_param = FromJS(param, js_context, sig_->GetParam(i));
    5044       91113 :       args[i + 1] = wasm_param;
    5045             :     }
    5046             : 
    5047             :     // Set the ThreadInWasm flag before we do the actual call.
    5048      156153 :     BuildModifyThreadInWasmFlag(true);
    5049             : 
    5050      156148 :     if (is_import) {
    5051             :       // Call to an imported function.
    5052             :       // Load function index from {WasmExportedFunctionData}.
    5053             :       Node* function_index =
    5054         522 :           BuildLoadFunctionIndexFromExportedFunctionData(function_data);
    5055         522 :       BuildImportCall(sig_, args, &rets, wasm::kNoCodePosition, function_index);
    5056             :     } else {
    5057             :       // Call to a wasm function defined in this module.
    5058             :       // The call target is the jump table slot for that function.
    5059             :       Node* jump_table_start =
    5060      311250 :           LOAD_INSTANCE_FIELD(JumpTableStart, MachineType::Pointer());
    5061             :       Node* jump_table_offset =
    5062      155630 :           BuildLoadJumpTableOffsetFromExportedFunctionData(function_data);
    5063             :       Node* jump_table_slot = graph()->NewNode(
    5064      155630 :           mcgraph()->machine()->IntAdd(), jump_table_start, jump_table_offset);
    5065      155629 :       args[0] = jump_table_slot;
    5066             : 
    5067             :       BuildWasmCall(sig_, args, &rets, wasm::kNoCodePosition, nullptr,
    5068      155629 :                     kNoRetpoline);
    5069             :     }
    5070             : 
    5071             :     // Clear the ThreadInWasm flag.
    5072      156153 :     BuildModifyThreadInWasmFlag(false);
    5073             : 
    5074      156149 :     Node* jsval = sig_->return_count() == 0 ? jsgraph()->UndefinedConstant()
    5075      312298 :                                             : ToJS(rets[0], sig_->GetReturn());
    5076             :     Return(jsval);
    5077             :   }
    5078             : 
    5079        7087 :   bool BuildWasmImportCallWrapper(WasmImportCallKind kind) {
    5080       18144 :     int wasm_count = static_cast<int>(sig_->parameter_count());
    5081             : 
    5082             :     // Build the start and the parameter nodes.
    5083      181211 :     SetEffect(SetControl(Start(wasm_count + 4)));
    5084             : 
    5085        7087 :     instance_node_.set(Param(wasm::kWasmInstanceParameterIndex));
    5086             : 
    5087             :     Node* native_context =
    5088       14174 :         LOAD_INSTANCE_FIELD(NativeContext, MachineType::TaggedPointer());
    5089             : 
    5090        7087 :     if (kind == WasmImportCallKind::kRuntimeTypeError) {
    5091             :       // =======================================================================
    5092             :       // === Runtime TypeError =================================================
    5093             :       // =======================================================================
    5094             :       BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError,
    5095             :                                     native_context, nullptr, 0, effect_,
    5096          72 :                                     Control());
    5097             :       // We don't need to return a value here, as the runtime call will not
    5098             :       // return anyway (the c entry stub will trigger stack unwinding).
    5099             :       ReturnVoid();
    5100          72 :       return false;
    5101             :     }
    5102             : 
    5103             :     // The callable is passed as the last parameter, after WASM arguments.
    5104        7015 :     Node* callable_node = Param(wasm_count + 1);
    5105             : 
    5106             :     Node* undefined_node =
    5107       14030 :         LOAD_INSTANCE_FIELD(UndefinedValue, MachineType::TaggedPointer());
    5108             : 
    5109             :     Node* call = nullptr;
    5110             :     bool sloppy_receiver = true;
    5111             : 
    5112             :     // Clear the ThreadInWasm flag.
    5113        7015 :     BuildModifyThreadInWasmFlag(false);
    5114             : 
    5115        7015 :     switch (kind) {
    5116             :       // =======================================================================
    5117             :       // === JS Functions with matching arity ==================================
    5118             :       // =======================================================================
    5119             :       case WasmImportCallKind::kJSFunctionArityMatch:
    5120             :         sloppy_receiver = false;
    5121             :         V8_FALLTHROUGH;  // fallthru
    5122             :       case WasmImportCallKind::kJSFunctionArityMatchSloppy: {
    5123        4593 :         Node** args = Buffer(wasm_count + 9);
    5124             :         int pos = 0;
    5125             :         Node* function_context = SetEffect(graph()->NewNode(
    5126             :             mcgraph()->machine()->Load(MachineType::TaggedPointer()),
    5127             :             callable_node,
    5128             :             mcgraph()->Int32Constant(
    5129             :                 wasm::ObjectAccess::ContextOffsetInTaggedJSFunction()),
    5130        9186 :             Effect(), Control()));
    5131        4593 :         args[pos++] = callable_node;  // target callable.
    5132             :         // Receiver.
    5133        4593 :         if (sloppy_receiver) {
    5134        9018 :           Node* global_proxy = LOAD_FIXED_ARRAY_SLOT_PTR(
    5135             :               native_context, Context::GLOBAL_PROXY_INDEX);
    5136        4509 :           args[pos++] = global_proxy;
    5137             :         } else {
    5138          84 :           args[pos++] = undefined_node;
    5139             :         }
    5140             : 
    5141             :         auto call_descriptor = Linkage::GetJSCallDescriptor(
    5142        4593 :             graph()->zone(), false, wasm_count + 1, CallDescriptor::kNoFlags);
    5143             : 
    5144             :         // Convert wasm numbers to JS values.
    5145        4593 :         pos = AddArgumentNodes(args, pos, wasm_count, sig_);
    5146             : 
    5147        4593 :         args[pos++] = undefined_node;                        // new target
    5148        9186 :         args[pos++] = mcgraph()->Int32Constant(wasm_count);  // argument count
    5149        4593 :         args[pos++] = function_context;
    5150        9186 :         args[pos++] = Effect();
    5151        9186 :         args[pos++] = Control();
    5152             : 
    5153             :         call = graph()->NewNode(mcgraph()->common()->Call(call_descriptor), pos,
    5154        9186 :                                 args);
    5155        4593 :         break;
    5156             :       }
    5157             :       // =======================================================================
    5158             :       // === JS Functions with arguments adapter ===============================
    5159             :       // =======================================================================
    5160             :       case WasmImportCallKind::kJSFunctionArityMismatch:
    5161             :         sloppy_receiver = false;
    5162             :         V8_FALLTHROUGH;  // fallthru
    5163             :       case WasmImportCallKind::kJSFunctionArityMismatchSloppy: {
    5164         541 :         Node** args = Buffer(wasm_count + 9);
    5165             :         int pos = 0;
    5166             :         Node* function_context = SetEffect(graph()->NewNode(
    5167             :             mcgraph()->machine()->Load(MachineType::TaggedPointer()),
    5168             :             callable_node,
    5169             :             mcgraph()->Int32Constant(
    5170             :                 wasm::ObjectAccess::ContextOffsetInTaggedJSFunction()),
    5171        1082 :             Effect(), Control()));
    5172             :         args[pos++] =
    5173         541 :             BuildLoadBuiltinFromInstance(Builtins::kArgumentsAdaptorTrampoline);
    5174         541 :         args[pos++] = callable_node;                         // target callable
    5175         541 :         args[pos++] = undefined_node;                        // new target
    5176         541 :         args[pos++] = mcgraph()->Int32Constant(wasm_count);  // argument count
    5177             : 
    5178             :         // Load shared function info, and then the formal parameter count.
    5179             :         Node* shared_function_info = SetEffect(graph()->NewNode(
    5180             :             mcgraph()->machine()->Load(MachineType::TaggedPointer()),
    5181             :             callable_node,
    5182             :             mcgraph()->Int32Constant(
    5183             :                 wasm::ObjectAccess::
    5184             :                     SharedFunctionInfoOffsetInTaggedJSFunction()),
    5185        1082 :             Effect(), Control()));
    5186             :         Node* formal_param_count = SetEffect(graph()->NewNode(
    5187             :             mcgraph()->machine()->Load(MachineType::Uint16()),
    5188             :             shared_function_info,
    5189             :             mcgraph()->Int32Constant(
    5190             :                 wasm::ObjectAccess::
    5191             :                     FormalParameterCountOffsetInSharedFunctionInfo()),
    5192        1082 :             Effect(), Control()));
    5193         541 :         args[pos++] = formal_param_count;
    5194             : 
    5195             :         // Receiver.
    5196         541 :         if (sloppy_receiver) {
    5197         944 :           Node* global_proxy = LOAD_FIXED_ARRAY_SLOT_PTR(
    5198             :               native_context, Context::GLOBAL_PROXY_INDEX);
    5199         472 :           args[pos++] = global_proxy;
    5200             :         } else {
    5201          69 :           args[pos++] = undefined_node;
    5202             :         }
    5203             : 
    5204             : #ifdef V8_TARGET_ARCH_IA32
    5205             :         // TODO(v8:6666): Remove kAllowCallThroughSlot and use a pc-relative
    5206             :         // call instead once builtins are embedded in every build configuration.
    5207             :         CallDescriptor::Flags flags = CallDescriptor::kAllowCallThroughSlot;
    5208             : #else
    5209             :         CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
    5210             : #endif
    5211             :         auto call_descriptor = Linkage::GetStubCallDescriptor(
    5212             :             mcgraph()->zone(), ArgumentsAdaptorDescriptor{}, 1 + wasm_count,
    5213        1082 :             flags, Operator::kNoProperties);
    5214             : 
    5215             :         // Convert wasm numbers to JS values.
    5216         541 :         pos = AddArgumentNodes(args, pos, wasm_count, sig_);
    5217         541 :         args[pos++] = function_context;
    5218        1082 :         args[pos++] = Effect();
    5219        1082 :         args[pos++] = Control();
    5220             :         call = graph()->NewNode(mcgraph()->common()->Call(call_descriptor), pos,
    5221        1082 :                                 args);
    5222             :         break;
    5223             :       }
    5224             :       // =======================================================================
    5225             :       // === General case of unknown callable ==================================
    5226             :       // =======================================================================
    5227             :       case WasmImportCallKind::kUseCallBuiltin: {
    5228        1881 :         Node** args = Buffer(wasm_count + 9);
    5229             :         int pos = 0;
    5230             :         args[pos++] = mcgraph()->RelocatableIntPtrConstant(
    5231        1881 :             wasm::WasmCode::kWasmCallJavaScript, RelocInfo::WASM_STUB_CALL);
    5232        1881 :         args[pos++] = callable_node;
    5233        1881 :         args[pos++] = mcgraph()->Int32Constant(wasm_count);  // argument count
    5234        1881 :         args[pos++] = undefined_node;                        // receiver
    5235             : 
    5236             :         auto call_descriptor = Linkage::GetStubCallDescriptor(
    5237             :             graph()->zone(), CallTrampolineDescriptor{}, wasm_count + 1,
    5238             :             CallDescriptor::kNoFlags, Operator::kNoProperties,
    5239        3762 :             StubCallMode::kCallWasmRuntimeStub);
    5240             : 
    5241             :         // Convert wasm numbers to JS values.
    5242        1881 :         pos = AddArgumentNodes(args, pos, wasm_count, sig_);
    5243             : 
    5244             :         // The native_context is sufficient here, because all kind of callables
    5245             :         // which depend on the context provide their own context. The context
    5246             :         // here is only needed if the target is a constructor to throw a
    5247             :         // TypeError, if the target is a native function, or if the target is a
    5248             :         // callable JSObject, which can only be constructed by the runtime.
    5249        1881 :         args[pos++] = native_context;
    5250        3762 :         args[pos++] = Effect();
    5251        3762 :         args[pos++] = Control();
    5252             : 
    5253             :         call = graph()->NewNode(mcgraph()->common()->Call(call_descriptor), pos,
    5254        3762 :                                 args);
    5255        1881 :         break;
    5256             :       }
    5257             :       default:
    5258           0 :         UNREACHABLE();
    5259             :     }
    5260             :     DCHECK_NOT_NULL(call);
    5261             : 
    5262             :     SetEffect(call);
    5263        7015 :     SetSourcePosition(call, 0);
    5264             : 
    5265             :     // Convert the return value back.
    5266        7015 :     Node* val = sig_->return_count() == 0
    5267             :                     ? mcgraph()->Int32Constant(0)
    5268       14030 :                     : FromJS(call, native_context, sig_->GetReturn());
    5269             : 
    5270             :     // Set the ThreadInWasm flag again.
    5271        7015 :     BuildModifyThreadInWasmFlag(true);
    5272             : 
    5273             :     Return(val);
    5274        7015 :     return true;
    5275             :   }
    5276             : 
    5277        2428 :   void BuildWasmInterpreterEntry(uint32_t func_index) {
    5278        4407 :     int param_count = static_cast<int>(sig_->parameter_count());
    5279             : 
    5280             :     // Build the start and the parameter nodes.
    5281       10556 :     SetEffect(SetControl(Start(param_count + 3)));
    5282             : 
    5283             :     // Create the instance_node from the passed parameter.
    5284        1214 :     instance_node_.set(Param(wasm::kWasmInstanceParameterIndex));
    5285             : 
    5286             :     // Compute size for the argument buffer.
    5287        1214 :     int args_size_bytes = 0;
    5288        3430 :     for (wasm::ValueType type : sig_->parameters()) {
    5289        1002 :       args_size_bytes += wasm::ValueTypes::ElementSizeInBytes(type);
    5290             :     }
    5291             : 
    5292             :     // The return value is also passed via this buffer:
    5293             :     DCHECK_GE(wasm::kV8MaxWasmFunctionReturns, sig_->return_count());
    5294             :     // TODO(wasm): Handle multi-value returns.
    5295             :     DCHECK_EQ(1, wasm::kV8MaxWasmFunctionReturns);
    5296             :     int return_size_bytes =
    5297             :         sig_->return_count() == 0
    5298             :             ? 0
    5299        2191 :             : wasm::ValueTypes::ElementSizeInBytes(sig_->GetReturn());
    5300             : 
    5301             :     // Get a stack slot for the arguments.
    5302             :     Node* arg_buffer =
    5303        1214 :         args_size_bytes == 0 && return_size_bytes == 0
    5304             :             ? mcgraph()->IntPtrConstant(0)
    5305             :             : graph()->NewNode(mcgraph()->machine()->StackSlot(
    5306        3528 :                   std::max(args_size_bytes, return_size_bytes), 8));
    5307             : 
    5308             :     // Now store all our arguments to the buffer.
    5309             :     int offset = 0;
    5310             : 
    5311        3430 :     for (int i = 0; i < param_count; ++i) {
    5312        1002 :       wasm::ValueType type = sig_->GetParam(i);
    5313             :       // Start from the parameter with index 1 to drop the instance_node.
    5314             :       SetEffect(graph()->NewNode(GetSafeStoreOperator(offset, type), arg_buffer,
    5315        1002 :                                  Int32Constant(offset), Param(i + 1), Effect(),
    5316        2004 :                                  Control()));
    5317        1002 :       offset += wasm::ValueTypes::ElementSizeInBytes(type);
    5318             :     }
    5319             :     DCHECK_EQ(args_size_bytes, offset);
    5320             : 
    5321             :     // We are passing the raw arg_buffer here. To the GC and other parts, it
    5322             :     // looks like a Smi (lowest bit not set). In the runtime function however,
    5323             :     // don't call Smi::value on it, but just cast it to a byte pointer.
    5324        2428 :     Node* parameters[] = {jsgraph()->SmiConstant(func_index), arg_buffer};
    5325             :     BuildCallToRuntime(Runtime::kWasmRunInterpreter, parameters,
    5326        1214 :                        arraysize(parameters));
    5327             : 
    5328             :     // Read back the return value.
    5329        2428 :     if (sig_->return_count() == 0) {
    5330             :       Return(Int32Constant(0));
    5331             :     } else {
    5332             :       // TODO(wasm): Implement multi-return.
    5333             :       DCHECK_EQ(1, sig_->return_count());
    5334             :       MachineType load_rep =
    5335         977 :           wasm::ValueTypes::MachineTypeFor(sig_->GetReturn());
    5336             :       Node* val = SetEffect(
    5337             :           graph()->NewNode(mcgraph()->machine()->Load(load_rep), arg_buffer,
    5338         977 :                            Int32Constant(0), Effect(), Control()));
    5339             :       Return(val);
    5340             :     }
    5341             : 
    5342        2428 :     if (ContainsInt64(sig_)) LowerInt64();
    5343        1214 :   }
    5344             : 
    5345        1572 :   void BuildCWasmEntry() {
    5346             :     // Build the start and the JS parameter nodes.
    5347       11634 :     SetEffect(SetControl(Start(CWasmEntryParameters::kNumParameters + 5)));
    5348             : 
    5349             :     // Create parameter nodes (offset by 1 for the receiver parameter).
    5350         786 :     Node* code_entry = Param(CWasmEntryParameters::kCodeEntry + 1);
    5351         786 :     Node* object_ref_node = Param(CWasmEntryParameters::kObjectRef + 1);
    5352         786 :     Node* arg_buffer = Param(CWasmEntryParameters::kArgumentsBuffer + 1);
    5353             : 
    5354        2304 :     int wasm_arg_count = static_cast<int>(sig_->parameter_count());
    5355             :     int arg_count =
    5356         786 :         wasm_arg_count + 4;  // code, object_ref_node, control, effect
    5357         786 :     Node** args = Buffer(arg_count);
    5358             : 
    5359             :     int pos = 0;
    5360         786 :     args[pos++] = code_entry;
    5361         786 :     args[pos++] = object_ref_node;
    5362             : 
    5363             :     int offset = 0;
    5364        2378 :     for (wasm::ValueType type : sig_->parameters()) {
    5365             :       Node* arg_load = SetEffect(
    5366             :           graph()->NewNode(GetSafeLoadOperator(offset, type), arg_buffer,
    5367         806 :                            Int32Constant(offset), Effect(), Control()));
    5368         806 :       args[pos++] = arg_load;
    5369         806 :       offset += wasm::ValueTypes::ElementSizeInBytes(type);
    5370             :     }
    5371             : 
    5372        1572 :     args[pos++] = Effect();
    5373        1572 :     args[pos++] = Control();
    5374             :     DCHECK_EQ(arg_count, pos);
    5375             : 
    5376             :     // Call the wasm code.
    5377        1572 :     auto call_descriptor = GetWasmCallDescriptor(mcgraph()->zone(), sig_);
    5378             : 
    5379             :     Node* call = SetEffect(graph()->NewNode(
    5380        1572 :         mcgraph()->common()->Call(call_descriptor), arg_count, args));
    5381             : 
    5382             :     // Store the return value.
    5383             :     DCHECK_GE(1, sig_->return_count());
    5384        1572 :     if (sig_->return_count() == 1) {
    5385             :       StoreRepresentation store_rep(
    5386             :           wasm::ValueTypes::MachineRepresentationFor(sig_->GetReturn()),
    5387         732 :           kNoWriteBarrier);
    5388             :       SetEffect(graph()->NewNode(mcgraph()->machine()->Store(store_rep),
    5389             :                                  arg_buffer, Int32Constant(0), call, Effect(),
    5390         732 :                                  Control()));
    5391             :     }
    5392             :     Return(jsgraph()->SmiConstant(0));
    5393             : 
    5394        1572 :     if (mcgraph()->machine()->Is32() && ContainsInt64(sig_)) {
    5395             :       MachineRepresentation sig_reps[] = {
    5396             :           MachineRepresentation::kWord32,  // return value
    5397             :           MachineRepresentation::kTagged,  // receiver
    5398             :           MachineRepresentation::kTagged,  // arg0 (code)
    5399             :           MachineRepresentation::kTagged   // arg1 (buffer)
    5400           0 :       };
    5401             :       Signature<MachineRepresentation> c_entry_sig(1, 2, sig_reps);
    5402             :       Int64Lowering r(mcgraph()->graph(), mcgraph()->machine(),
    5403           0 :                       mcgraph()->common(), mcgraph()->zone(), &c_entry_sig);
    5404           0 :       r.LowerGraph();
    5405             :     }
    5406         786 :   }
    5407             : 
    5408             :   JSGraph* jsgraph() { return jsgraph_; }
    5409             : 
    5410             :  private:
    5411             :   Isolate* const isolate_;
    5412             :   JSGraph* jsgraph_;
    5413             :   StubCallMode stub_mode_;
    5414             :   SetOncePointer<const Operator> allocate_heap_number_operator_;
    5415             :   wasm::WasmFeatures enabled_features_;
    5416             : };
    5417             : 
    5418      157767 : void AppendSignature(char* buffer, size_t max_name_len,
    5419      157767 :                      wasm::FunctionSig* sig) {
    5420      157767 :   size_t name_len = strlen(buffer);
    5421             :   auto append_name_char = [&](char c) {
    5422      276264 :     if (name_len + 1 < max_name_len) buffer[name_len++] = c;
    5423             :   };
    5424      250760 :   for (wasm::ValueType t : sig->parameters()) {
    5425             :     append_name_char(wasm::ValueTypes::ShortNameOf(t));
    5426             :   }
    5427             :   append_name_char(':');
    5428      183271 :   for (wasm::ValueType t : sig->returns()) {
    5429             :     append_name_char(wasm::ValueTypes::ShortNameOf(t));
    5430             :   }
    5431      157767 :   buffer[name_len] = '\0';
    5432      157767 : }
    5433             : 
    5434             : }  // namespace
    5435             : 
    5436      313962 : MaybeHandle<Code> CompileJSToWasmWrapper(Isolate* isolate,
    5437      156981 :                                          wasm::FunctionSig* sig,
    5438             :                                          bool is_import) {
    5439      313962 :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"),
    5440             :                "CompileJSToWasmWrapper");
    5441             :   //----------------------------------------------------------------------------
    5442             :   // Create the Graph.
    5443             :   //----------------------------------------------------------------------------
    5444      313959 :   Zone zone(isolate->allocator(), ZONE_NAME);
    5445      156981 :   Graph graph(&zone);
    5446      156981 :   CommonOperatorBuilder common(&zone);
    5447             :   MachineOperatorBuilder machine(
    5448             :       &zone, MachineType::PointerRepresentation(),
    5449             :       InstructionSelector::SupportedMachineOperatorFlags(),
    5450      156981 :       InstructionSelector::AlignmentRequirements());
    5451      156981 :   JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
    5452             : 
    5453      156981 :   Node* control = nullptr;
    5454      156981 :   Node* effect = nullptr;
    5455             : 
    5456             :   WasmWrapperGraphBuilder builder(&zone, &jsgraph, sig, nullptr,
    5457             :                                   StubCallMode::kCallCodeObject,
    5458      156981 :                                   wasm::WasmFeaturesFromIsolate(isolate));
    5459             :   builder.set_control_ptr(&control);
    5460             :   builder.set_effect_ptr(&effect);
    5461      156981 :   builder.BuildJSToWasmWrapper(is_import);
    5462             : 
    5463             :   //----------------------------------------------------------------------------
    5464             :   // Run the compilation pipeline.
    5465             :   //----------------------------------------------------------------------------
    5466             :   static constexpr size_t kMaxNameLen = 128;
    5467      156970 :   char debug_name[kMaxNameLen] = "js_to_wasm:";
    5468      156970 :   AppendSignature(debug_name, kMaxNameLen, sig);
    5469             : 
    5470             :   // Schedule and compile to machine code.
    5471      156981 :   int params = static_cast<int>(sig->parameter_count());
    5472             :   CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
    5473      156981 :       &zone, false, params + 1, CallDescriptor::kNoFlags);
    5474             : 
    5475             :   MaybeHandle<Code> maybe_code = Pipeline::GenerateCodeForWasmHeapStub(
    5476             :       isolate, incoming, &graph, Code::JS_TO_WASM_FUNCTION, debug_name,
    5477      156981 :       WasmAssemblerOptions());
    5478             :   Handle<Code> code;
    5479      156975 :   if (!maybe_code.ToHandle(&code)) {
    5480           0 :     return maybe_code;
    5481             :   }
    5482             : #ifdef ENABLE_DISASSEMBLER
    5483             :   if (FLAG_print_opt_code) {
    5484             :     CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
    5485             :     OFStream os(tracing_scope.file());
    5486             :     code->Disassemble(debug_name, os);
    5487             :   }
    5488             : #endif
    5489             : 
    5490      156979 :   if (must_record_function_compilation(isolate)) {
    5491             :     RecordFunctionCompilation(CodeEventListener::STUB_TAG, isolate, code, "%s",
    5492           0 :                               debug_name);
    5493             :   }
    5494             : 
    5495      313959 :   return code;
    5496             : }
    5497             : 
    5498      134375 : WasmImportCallKind GetWasmImportCallKind(Handle<JSReceiver> target,
    5499       11372 :                                          wasm::FunctionSig* expected_sig,
    5500             :                                          bool has_bigint_feature) {
    5501      134375 :   if (WasmExportedFunction::IsWasmExportedFunction(*target)) {
    5502      120699 :     auto imported_function = WasmExportedFunction::cast(*target);
    5503             :     wasm::FunctionSig* imported_sig =
    5504             :         imported_function->instance()
    5505      241398 :             ->module()
    5506      241398 :             ->functions[imported_function->function_index()]
    5507      120699 :             .sig;
    5508      120699 :     if (*imported_sig != *expected_sig) {
    5509             :       return WasmImportCallKind::kLinkError;
    5510             :     }
    5511      120519 :     return WasmImportCallKind::kWasmToWasm;
    5512             :   }
    5513             :   // Assuming we are calling to JS, check whether this would be a runtime error.
    5514       13676 :   if (!wasm::IsJSCompatibleSignature(expected_sig, has_bigint_feature)) {
    5515             :     return WasmImportCallKind::kRuntimeTypeError;
    5516             :   }
    5517             :   // For JavaScript calls, determine whether the target has an arity match
    5518             :   // and whether it has a sloppy receiver.
    5519       27208 :   if (target->IsJSFunction()) {
    5520       11642 :     Handle<JSFunction> function = Handle<JSFunction>::cast(target);
    5521       11642 :     SharedFunctionInfo shared = function->shared();
    5522             : 
    5523             : // Check for math intrinsics.
    5524             : #define COMPARE_SIG_FOR_BUILTIN(name)                                         \
    5525             :   {                                                                           \
    5526             :     wasm::FunctionSig* sig = wasm::WasmOpcodes::Signature(wasm::kExpr##name); \
    5527             :     if (!sig) sig = wasm::WasmOpcodes::AsmjsSignature(wasm::kExpr##name);     \
    5528             :     DCHECK_NOT_NULL(sig);                                                     \
    5529             :     if (*expected_sig == *sig) return WasmImportCallKind::k##name;            \
    5530             :   }
    5531             : #define COMPARE_SIG_FOR_BUILTIN_F64(name) \
    5532             :   case Builtins::kMath##name:             \
    5533             :     COMPARE_SIG_FOR_BUILTIN(F64##name);   \
    5534             :     break;
    5535             : #define COMPARE_SIG_FOR_BUILTIN_F32_F64(name) \
    5536             :   case Builtins::kMath##name:                 \
    5537             :     COMPARE_SIG_FOR_BUILTIN(F64##name);       \
    5538             :     COMPARE_SIG_FOR_BUILTIN(F32##name);       \
    5539             :     break;
    5540             : 
    5541       11642 :     if (FLAG_wasm_math_intrinsics && shared->HasBuiltinId()) {
    5542         562 :       switch (shared->builtin_id()) {
    5543          20 :         COMPARE_SIG_FOR_BUILTIN_F64(Acos);
    5544          20 :         COMPARE_SIG_FOR_BUILTIN_F64(Asin);
    5545          19 :         COMPARE_SIG_FOR_BUILTIN_F64(Atan);
    5546          30 :         COMPARE_SIG_FOR_BUILTIN_F64(Cos);
    5547          30 :         COMPARE_SIG_FOR_BUILTIN_F64(Sin);
    5548          19 :         COMPARE_SIG_FOR_BUILTIN_F64(Tan);
    5549          19 :         COMPARE_SIG_FOR_BUILTIN_F64(Exp);
    5550          20 :         COMPARE_SIG_FOR_BUILTIN_F64(Log);
    5551          20 :         COMPARE_SIG_FOR_BUILTIN_F64(Atan2);
    5552             :         //===========================================================
    5553             :         // TODO(8505): Math.pow for wasm does not match JS.
    5554             :         //        COMPARE_SIG_FOR_BUILTIN_F64(Pow);
    5555             :         //===========================================================
    5556         118 :         COMPARE_SIG_FOR_BUILTIN_F32_F64(Min);
    5557          27 :         COMPARE_SIG_FOR_BUILTIN_F32_F64(Max);
    5558          38 :         COMPARE_SIG_FOR_BUILTIN_F32_F64(Abs);
    5559          38 :         COMPARE_SIG_FOR_BUILTIN_F32_F64(Ceil);
    5560          48 :         COMPARE_SIG_FOR_BUILTIN_F32_F64(Floor);
    5561          58 :         COMPARE_SIG_FOR_BUILTIN_F32_F64(Sqrt);
    5562             :         case Builtins::kMathFround:
    5563           9 :           COMPARE_SIG_FOR_BUILTIN(F32ConvertF64);
    5564             :           break;
    5565             :         default:
    5566             :           break;
    5567             :       }
    5568             :     }
    5569             : 
    5570             : #undef COMPARE_SIG_FOR_BUILTIN
    5571             : #undef COMPARE_SIG_FOR_BUILTIN_F64
    5572             : #undef COMPARE_SIG_FOR_BUILTIN_F32_F64
    5573             : 
    5574       11390 :     if (IsClassConstructor(shared->kind())) {
    5575             :       // Class constructor will throw anyway.
    5576             :       return WasmImportCallKind::kUseCallBuiltin;
    5577             :     }
    5578       22389 :     bool sloppy = is_sloppy(shared->language_mode()) && !shared->native();
    5579       22744 :     if (shared->internal_formal_parameter_count() ==
    5580             :         expected_sig->parameter_count()) {
    5581             :       return sloppy ? WasmImportCallKind::kJSFunctionArityMatchSloppy
    5582        8676 :                     : WasmImportCallKind::kJSFunctionArityMatch;
    5583             :     }
    5584             :     return sloppy ? WasmImportCallKind::kJSFunctionArityMismatchSloppy
    5585        2696 :                   : WasmImportCallKind::kJSFunctionArityMismatch;
    5586             :   }
    5587             :   // Unknown case. Use the call builtin.
    5588             :   return WasmImportCallKind::kUseCallBuiltin;
    5589             : }
    5590             : 
    5591         252 : wasm::WasmOpcode GetMathIntrinsicOpcode(WasmImportCallKind kind,
    5592             :                                         const char** name_ptr) {
    5593             : #define CASE(name)                          \
    5594             :   case WasmImportCallKind::k##name:         \
    5595             :     *name_ptr = "WasmMathIntrinsic:" #name; \
    5596             :     return wasm::kExpr##name
    5597         252 :   switch (kind) {
    5598           9 :     CASE(F64Acos);
    5599           9 :     CASE(F64Asin);
    5600           9 :     CASE(F64Atan);
    5601           9 :     CASE(F64Cos);
    5602           9 :     CASE(F64Sin);
    5603           9 :     CASE(F64Tan);
    5604           9 :     CASE(F64Exp);
    5605           9 :     CASE(F64Log);
    5606           9 :     CASE(F64Atan2);
    5607           0 :     CASE(F64Pow);
    5608          18 :     CASE(F64Ceil);
    5609          18 :     CASE(F64Floor);
    5610          18 :     CASE(F64Sqrt);
    5611          18 :     CASE(F64Min);
    5612          18 :     CASE(F64Max);
    5613          18 :     CASE(F64Abs);
    5614           9 :     CASE(F32Min);
    5615           9 :     CASE(F32Max);
    5616           9 :     CASE(F32Abs);
    5617           9 :     CASE(F32Ceil);
    5618           9 :     CASE(F32Floor);
    5619           9 :     CASE(F32Sqrt);
    5620           9 :     CASE(F32ConvertF64);
    5621             :     default:
    5622           0 :       UNREACHABLE();
    5623             :       return wasm::kExprUnreachable;
    5624             :   }
    5625             : #undef CASE
    5626             : }
    5627             : 
    5628         252 : wasm::WasmCode* CompileWasmMathIntrinsic(wasm::WasmEngine* wasm_engine,
    5629             :                                          wasm::NativeModule* native_module,
    5630             :                                          WasmImportCallKind kind,
    5631         504 :                                          wasm::FunctionSig* sig) {
    5632             :   DCHECK_EQ(1, sig->return_count());
    5633             : 
    5634         504 :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"),
    5635             :                "CompileWasmMathIntrinsic");
    5636             : 
    5637         504 :   Zone zone(wasm_engine->allocator(), ZONE_NAME);
    5638             : 
    5639             :   // Compile a WASM function with a single bytecode and let TurboFan
    5640             :   // generate either inlined machine code or a call to a helper.
    5641             :   SourcePositionTable* source_positions = nullptr;
    5642         252 :   MachineGraph* mcgraph = new (&zone) MachineGraph(
    5643         504 :       new (&zone) Graph(&zone), new (&zone) CommonOperatorBuilder(&zone),
    5644             :       new (&zone) MachineOperatorBuilder(
    5645             :           &zone, MachineType::PointerRepresentation(),
    5646             :           InstructionSelector::SupportedMachineOperatorFlags(),
    5647         756 :           InstructionSelector::AlignmentRequirements()));
    5648             : 
    5649             :   wasm::CompilationEnv env(
    5650             :       native_module->module(), wasm::UseTrapHandler::kNoTrapHandler,
    5651             :       wasm::RuntimeExceptionSupport::kNoRuntimeExceptionSupport,
    5652             :       wasm::kAllWasmFeatures, wasm::LowerSimd::kNoLowerSimd);
    5653             : 
    5654             :   WasmGraphBuilder builder(&env, mcgraph->zone(), mcgraph, sig,
    5655         252 :                            source_positions);
    5656             : 
    5657             :   // Set up the graph start.
    5658         252 :   Node* start = builder.Start(static_cast<int>(sig->parameter_count() + 1 + 1));
    5659         252 :   Node* effect = start;
    5660         252 :   Node* control = start;
    5661             :   builder.set_effect_ptr(&effect);
    5662             :   builder.set_control_ptr(&control);
    5663         252 :   builder.set_instance_node(builder.Param(wasm::kWasmInstanceParameterIndex));
    5664             : 
    5665             :   // Generate either a unop or a binop.
    5666             :   Node* result = nullptr;
    5667         252 :   const char* debug_name = "WasmMathIntrinsic";
    5668         252 :   auto opcode = GetMathIntrinsicOpcode(kind, &debug_name);
    5669         252 :   switch (sig->parameter_count()) {
    5670             :     case 1:
    5671         189 :       result = builder.Unop(opcode, builder.Param(1));
    5672         189 :       break;
    5673             :     case 2:
    5674          63 :       result = builder.Binop(opcode, builder.Param(1), builder.Param(2));
    5675          63 :       break;
    5676             :     default:
    5677           0 :       UNREACHABLE();
    5678             :       break;
    5679             :   }
    5680             : 
    5681             :   builder.Return(result);
    5682             : 
    5683             :   // Run the compiler pipeline to generate machine code.
    5684         252 :   auto call_descriptor = GetWasmCallDescriptor(&zone, sig);
    5685         252 :   if (mcgraph->machine()->Is32()) {
    5686             :     call_descriptor = GetI32WasmCallDescriptor(&zone, call_descriptor);
    5687             :   }
    5688             : 
    5689             :   wasm::WasmCode* wasm_code = Pipeline::GenerateCodeForWasmNativeStub(
    5690             :       wasm_engine, call_descriptor, mcgraph, Code::WASM_FUNCTION,
    5691             :       wasm::WasmCode::kFunction, debug_name, WasmStubAssemblerOptions(),
    5692         252 :       native_module, source_positions);
    5693         252 :   CHECK_NOT_NULL(wasm_code);
    5694             :   // TODO(titzer): add counters for math intrinsic code size / allocation
    5695             : 
    5696         252 :   return wasm_code;
    5697             : }
    5698             : 
    5699        7339 : wasm::WasmCode* CompileWasmImportCallWrapper(wasm::WasmEngine* wasm_engine,
    5700             :                                              wasm::NativeModule* native_module,
    5701             :                                              WasmImportCallKind kind,
    5702             :                                              wasm::FunctionSig* sig,
    5703             :                                              bool source_positions) {
    5704             :   DCHECK_NE(WasmImportCallKind::kLinkError, kind);
    5705             :   DCHECK_NE(WasmImportCallKind::kWasmToWasm, kind);
    5706             : 
    5707             :   // Check for math intrinsics first.
    5708        7339 :   if (FLAG_wasm_math_intrinsics &&
    5709        7339 :       kind >= WasmImportCallKind::kFirstMathIntrinsic &&
    5710             :       kind <= WasmImportCallKind::kLastMathIntrinsic) {
    5711         252 :     return CompileWasmMathIntrinsic(wasm_engine, native_module, kind, sig);
    5712             :   }
    5713             : 
    5714       14174 :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"),
    5715             :                "CompileWasmImportCallWrapper");
    5716             :   //----------------------------------------------------------------------------
    5717             :   // Create the Graph
    5718             :   //----------------------------------------------------------------------------
    5719       14174 :   Zone zone(wasm_engine->allocator(), ZONE_NAME);
    5720        7087 :   Graph graph(&zone);
    5721        7087 :   CommonOperatorBuilder common(&zone);
    5722             :   MachineOperatorBuilder machine(
    5723             :       &zone, MachineType::PointerRepresentation(),
    5724             :       InstructionSelector::SupportedMachineOperatorFlags(),
    5725        7087 :       InstructionSelector::AlignmentRequirements());
    5726        7087 :   JSGraph jsgraph(nullptr, &graph, &common, nullptr, nullptr, &machine);
    5727             : 
    5728        7087 :   Node* control = nullptr;
    5729        7087 :   Node* effect = nullptr;
    5730             : 
    5731             :   SourcePositionTable* source_position_table =
    5732        7673 :       source_positions ? new (&zone) SourcePositionTable(&graph) : nullptr;
    5733             : 
    5734             :   WasmWrapperGraphBuilder builder(&zone, &jsgraph, sig, source_position_table,
    5735             :                                   StubCallMode::kCallWasmRuntimeStub,
    5736             :                                   native_module->enabled_features());
    5737             :   builder.set_control_ptr(&control);
    5738             :   builder.set_effect_ptr(&effect);
    5739        7087 :   builder.BuildWasmImportCallWrapper(kind);
    5740             : 
    5741             :   const char* func_name = "wasm-to-js";
    5742             : 
    5743             :   // Schedule and compile to machine code.
    5744             :   CallDescriptor* incoming =
    5745             :       GetWasmCallDescriptor(&zone, sig, WasmGraphBuilder::kNoRetpoline,
    5746        7087 :                             WasmGraphBuilder::kExtraCallableParam);
    5747        7087 :   if (machine.Is32()) {
    5748             :     incoming = GetI32WasmCallDescriptor(&zone, incoming);
    5749             :   }
    5750             :   wasm::WasmCode* wasm_code = Pipeline::GenerateCodeForWasmNativeStub(
    5751             :       wasm_engine, incoming, &jsgraph, Code::WASM_TO_JS_FUNCTION,
    5752             :       wasm::WasmCode::kWasmToJsWrapper, func_name, WasmStubAssemblerOptions(),
    5753        7087 :       native_module, source_position_table);
    5754        7087 :   CHECK_NOT_NULL(wasm_code);
    5755             : 
    5756        7087 :   return wasm_code;
    5757             : }
    5758             : 
    5759        1214 : wasm::WasmCode* CompileWasmInterpreterEntry(wasm::WasmEngine* wasm_engine,
    5760             :                                             wasm::NativeModule* native_module,
    5761             :                                             uint32_t func_index,
    5762             :                                             wasm::FunctionSig* sig) {
    5763             :   //----------------------------------------------------------------------------
    5764             :   // Create the Graph
    5765             :   //----------------------------------------------------------------------------
    5766        1214 :   Zone zone(wasm_engine->allocator(), ZONE_NAME);
    5767        1214 :   Graph graph(&zone);
    5768        1214 :   CommonOperatorBuilder common(&zone);
    5769             :   MachineOperatorBuilder machine(
    5770             :       &zone, MachineType::PointerRepresentation(),
    5771             :       InstructionSelector::SupportedMachineOperatorFlags(),
    5772        1214 :       InstructionSelector::AlignmentRequirements());
    5773        1214 :   JSGraph jsgraph(nullptr, &graph, &common, nullptr, nullptr, &machine);
    5774             : 
    5775        1214 :   Node* control = nullptr;
    5776        1214 :   Node* effect = nullptr;
    5777             : 
    5778             :   WasmWrapperGraphBuilder builder(&zone, &jsgraph, sig, nullptr,
    5779             :                                   StubCallMode::kCallWasmRuntimeStub,
    5780             :                                   native_module->enabled_features());
    5781             :   builder.set_control_ptr(&control);
    5782             :   builder.set_effect_ptr(&effect);
    5783        1214 :   builder.BuildWasmInterpreterEntry(func_index);
    5784             : 
    5785             :   // Schedule and compile to machine code.
    5786        1214 :   CallDescriptor* incoming = GetWasmCallDescriptor(&zone, sig);
    5787        1214 :   if (machine.Is32()) {
    5788             :     incoming = GetI32WasmCallDescriptor(&zone, incoming);
    5789             :   }
    5790             : 
    5791             :   EmbeddedVector<char, 32> func_name;
    5792             :   func_name.Truncate(
    5793        1214 :       SNPrintF(func_name, "wasm-interpreter-entry#%d", func_index));
    5794             : 
    5795             :   wasm::WasmCode* wasm_code = Pipeline::GenerateCodeForWasmNativeStub(
    5796             :       wasm_engine, incoming, &jsgraph, Code::WASM_INTERPRETER_ENTRY,
    5797        1214 :       wasm::WasmCode::kInterpreterEntry, func_name.start(),
    5798        1214 :       WasmStubAssemblerOptions(), native_module);
    5799        1214 :   CHECK_NOT_NULL(wasm_code);
    5800             : 
    5801        1214 :   return wasm_code;
    5802             : }
    5803             : 
    5804         786 : MaybeHandle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) {
    5805         786 :   Zone zone(isolate->allocator(), ZONE_NAME);
    5806         786 :   Graph graph(&zone);
    5807         786 :   CommonOperatorBuilder common(&zone);
    5808             :   MachineOperatorBuilder machine(
    5809             :       &zone, MachineType::PointerRepresentation(),
    5810             :       InstructionSelector::SupportedMachineOperatorFlags(),
    5811         786 :       InstructionSelector::AlignmentRequirements());
    5812         786 :   JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
    5813             : 
    5814         786 :   Node* control = nullptr;
    5815         786 :   Node* effect = nullptr;
    5816             : 
    5817             :   WasmWrapperGraphBuilder builder(&zone, &jsgraph, sig, nullptr,
    5818             :                                   StubCallMode::kCallCodeObject,
    5819         786 :                                   wasm::WasmFeaturesFromIsolate(isolate));
    5820             :   builder.set_control_ptr(&control);
    5821             :   builder.set_effect_ptr(&effect);
    5822         786 :   builder.BuildCWasmEntry();
    5823             : 
    5824             :   // Schedule and compile to machine code.
    5825             :   CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
    5826             :       &zone, false, CWasmEntryParameters::kNumParameters + 1,
    5827         786 :       CallDescriptor::kNoFlags);
    5828             : 
    5829             :   // Build a name in the form "c-wasm-entry:<params>:<returns>".
    5830             :   static constexpr size_t kMaxNameLen = 128;
    5831         786 :   char debug_name[kMaxNameLen] = "c-wasm-entry:";
    5832         786 :   AppendSignature(debug_name, kMaxNameLen, sig);
    5833             : 
    5834             :   MaybeHandle<Code> maybe_code = Pipeline::GenerateCodeForWasmHeapStub(
    5835             :       isolate, incoming, &graph, Code::C_WASM_ENTRY, debug_name,
    5836         786 :       AssemblerOptions::Default(isolate));
    5837             :   Handle<Code> code;
    5838         786 :   if (!maybe_code.ToHandle(&code)) {
    5839           0 :     return maybe_code;
    5840             :   }
    5841             : #ifdef ENABLE_DISASSEMBLER
    5842             :   if (FLAG_print_opt_code) {
    5843             :     CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
    5844             :     OFStream os(tracing_scope.file());
    5845             :     code->Disassemble(debug_name, os);
    5846             :   }
    5847             : #endif
    5848             : 
    5849         786 :   return code;
    5850             : }
    5851             : 
    5852     1067642 : TurbofanWasmCompilationUnit::TurbofanWasmCompilationUnit(
    5853             :     wasm::WasmCompilationUnit* wasm_unit)
    5854     1067642 :     : wasm_unit_(wasm_unit) {}
    5855             : 
    5856             : // Clears unique_ptrs, but (part of) the type is forward declared in the header.
    5857             : TurbofanWasmCompilationUnit::~TurbofanWasmCompilationUnit() = default;
    5858             : 
    5859     1066843 : bool TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
    5860             :     wasm::CompilationEnv* env, wasm::NativeModule* native_module,
    5861             :     const wasm::FunctionBody& func_body, wasm::WasmFeatures* detected,
    5862             :     double* decode_ms, MachineGraph* mcgraph, NodeOriginTable* node_origins,
    5863             :     SourcePositionTable* source_positions) {
    5864             :   base::ElapsedTimer decode_timer;
    5865             :   if (FLAG_trace_wasm_decode_time) {
    5866             :     decode_timer.Start();
    5867             :   }
    5868             : 
    5869             :   // Create a TF graph during decoding.
    5870             :   WasmGraphBuilder builder(env, mcgraph->zone(), mcgraph, func_body.sig,
    5871     2133686 :                            source_positions);
    5872             :   wasm::VoidResult graph_construction_result = wasm::BuildTFGraph(
    5873             :       wasm_unit_->wasm_engine_->allocator(), env->enabled_features, env->module,
    5874     2133907 :       &builder, detected, func_body, node_origins);
    5875     1066988 :   if (graph_construction_result.failed()) {
    5876             :     if (FLAG_trace_wasm_compiler) {
    5877             :       StdoutStream{} << "Compilation failed: "
    5878             :                      << graph_construction_result.error().message()
    5879             :                      << std::endl;
    5880             :     }
    5881             :     native_module->compilation_state()->SetError(
    5882       13478 :         wasm_unit_->func_index_, std::move(graph_construction_result).error());
    5883        6739 :     return false;
    5884             :   }
    5885             : 
    5886     1060249 :   builder.LowerInt64();
    5887             : 
    5888     2136200 :   if (builder.has_simd() &&
    5889       15828 :       (!CpuFeatures::SupportsWasmSimd128() || env->lower_simd)) {
    5890             :     SimdScalarLowering(mcgraph,
    5891             :                        CreateMachineSignature(mcgraph->zone(), func_body.sig))
    5892       15255 :         .LowerGraph();
    5893             :   }
    5894             : 
    5895     2120385 :   if (wasm_unit_->func_index_ >= FLAG_trace_wasm_ast_start &&
    5896     1060199 :       wasm_unit_->func_index_ < FLAG_trace_wasm_ast_end) {
    5897             :     PrintRawWasmCode(wasm_unit_->wasm_engine_->allocator(), func_body,
    5898           0 :                      env->module, wasm::kPrintLocals);
    5899             :   }
    5900             :   if (FLAG_trace_wasm_decode_time) {
    5901             :     *decode_ms = decode_timer.Elapsed().InMillisecondsF();
    5902             :   }
    5903             :   return true;
    5904             : }
    5905             : 
    5906             : namespace {
    5907     1066967 : Vector<const char> GetDebugName(Zone* zone, int index) {
    5908             :   // TODO(herhut): Use name from module if available.
    5909             :   constexpr int kBufferLength = 24;
    5910             : 
    5911             :   EmbeddedVector<char, kBufferLength> name_vector;
    5912     1066967 :   int name_len = SNPrintF(name_vector, "wasm-function#%d", index);
    5913             :   DCHECK(name_len > 0 && name_len < name_vector.length());
    5914             : 
    5915     1066979 :   char* index_name = zone->NewArray<char>(name_len);
    5916     1067001 :   memcpy(index_name, name_vector.start(), name_len);
    5917     1067001 :   return Vector<const char>(index_name, name_len);
    5918             : }
    5919             : }  // namespace
    5920             : 
    5921     1067017 : void TurbofanWasmCompilationUnit::ExecuteCompilation(
    5922             :     wasm::CompilationEnv* env, wasm::NativeModule* native_module,
    5923             :     const wasm::FunctionBody& func_body, Counters* counters,
    5924             :     wasm::WasmFeatures* detected) {
    5925     2134034 :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"),
    5926             :                "ExecuteTurbofanCompilation");
    5927     1067017 :   double decode_ms = 0;
    5928             :   size_t node_count = 0;
    5929             : 
    5930     2127315 :   Zone zone(wasm_unit_->wasm_engine_->allocator(), ZONE_NAME);
    5931     3187422 :   MachineGraph* mcgraph = new (&zone) MachineGraph(
    5932     2134047 :       new (&zone) Graph(&zone), new (&zone) CommonOperatorBuilder(&zone),
    5933             :       new (&zone) MachineOperatorBuilder(
    5934             :           &zone, MachineType::PointerRepresentation(),
    5935             :           InstructionSelector::SupportedMachineOperatorFlags(),
    5936     3201028 :           InstructionSelector::AlignmentRequirements()));
    5937             : 
    5938             :   OptimizedCompilationInfo info(GetDebugName(&zone, wasm_unit_->func_index_),
    5939     2127278 :                                 &zone, Code::WASM_FUNCTION);
    5940     1066929 :   if (env->runtime_exception_support) {
    5941             :     info.SetWasmRuntimeExceptionSupport();
    5942             :   }
    5943             : 
    5944     1066929 :   if (info.trace_turbo_json_enabled()) {
    5945           0 :     TurboCfgFile tcf;
    5946           0 :     tcf << AsC1VCompilation(&info);
    5947             :   }
    5948             : 
    5949             :   NodeOriginTable* node_origins = info.trace_turbo_json_enabled()
    5950             :                                       ? new (&zone)
    5951           0 :                                             NodeOriginTable(mcgraph->graph())
    5952     1066929 :                                       : nullptr;
    5953             :   SourcePositionTable* source_positions =
    5954     1066915 :       new (mcgraph->zone()) SourcePositionTable(mcgraph->graph());
    5955     1066955 :   if (!BuildGraphForWasmFunction(env, native_module, func_body, detected,
    5956             :                                  &decode_ms, mcgraph, node_origins,
    5957     1066853 :                                  source_positions)) {
    5958             :     // Compilation failed.
    5959        6739 :     return;
    5960             :   }
    5961             : 
    5962     1060216 :   if (node_origins) {
    5963           0 :     node_origins->AddDecorator();
    5964             :   }
    5965             : 
    5966             :   base::ElapsedTimer pipeline_timer;
    5967             :   if (FLAG_trace_wasm_decode_time) {
    5968             :     node_count = mcgraph->graph()->NodeCount();
    5969             :     pipeline_timer.Start();
    5970             :   }
    5971             : 
    5972             :   // Run the compiler pipeline to generate machine code.
    5973     1060216 :   auto call_descriptor = GetWasmCallDescriptor(&zone, func_body.sig);
    5974     1060194 :   if (mcgraph->machine()->Is32()) {
    5975             :     call_descriptor = GetI32WasmCallDescriptor(&zone, call_descriptor);
    5976             :   }
    5977             : 
    5978     1060223 :   if (wasm::WasmCode* wasm_code = Pipeline::GenerateCodeForWasmFunction(
    5979             :           &info, wasm_unit_->wasm_engine_, mcgraph, call_descriptor,
    5980             :           source_positions, node_origins, func_body, native_module,
    5981     1060194 :           wasm_unit_->func_index_)) {
    5982     1060235 :     wasm_unit_->SetResult(wasm_code, counters);
    5983             :   }
    5984             :   if (FLAG_trace_wasm_decode_time) {
    5985             :     double pipeline_ms = pipeline_timer.Elapsed().InMillisecondsF();
    5986             :     PrintF(
    5987             :         "wasm-compilation phase 1 ok: %u bytes, %0.3f ms decode, %zu nodes, "
    5988             :         "%0.3f ms pipeline\n",
    5989             :         static_cast<unsigned>(func_body.end - func_body.start), decode_ms,
    5990             :         node_count, pipeline_ms);
    5991             :   }
    5992             :   // TODO(bradnelson): Improve histogram handling of size_t.
    5993             :   counters->wasm_compile_function_peak_memory_bytes()->AddSample(
    5994     3180896 :       static_cast<int>(mcgraph->graph()->zone()->allocation_size()));
    5995             : }
    5996             : 
    5997             : namespace {
    5998             : // Helper for allocating either an GP or FP reg, or the next stack slot.
    5999             : class LinkageLocationAllocator {
    6000             :  public:
    6001             :   template <size_t kNumGpRegs, size_t kNumFpRegs>
    6002             :   constexpr LinkageLocationAllocator(const Register (&gp)[kNumGpRegs],
    6003             :                                      const DoubleRegister (&fp)[kNumFpRegs])
    6004             :       : allocator_(wasm::LinkageAllocator(gp, fp)) {}
    6005             : 
    6006     6758443 :   LinkageLocation Next(MachineRepresentation rep) {
    6007     6758443 :     MachineType type = MachineType::TypeForRepresentation(rep);
    6008     6758488 :     if (IsFloatingPoint(rep)) {
    6009    12828862 :       if (allocator_.CanAllocateFP(rep)) {
    6010             :         int reg_code = allocator_.NextFpReg(rep);
    6011             :         return LinkageLocation::ForRegister(reg_code, type);
    6012             :       }
    6013     6152584 :     } else if (allocator_.CanAllocateGP()) {
    6014             :       int reg_code = allocator_.NextGpReg();
    6015             :       return LinkageLocation::ForRegister(reg_code, type);
    6016             :     }
    6017             :     // Cannot use register; use stack slot.
    6018      188432 :     int index = -1 - allocator_.NextStackSlot(rep);
    6019             :     return LinkageLocation::ForCallerFrameSlot(index, type);
    6020             :   }
    6021             : 
    6022             :   void SetStackOffset(int offset) { allocator_.SetStackOffset(offset); }
    6023     6058372 :   int NumStackSlots() const { return allocator_.NumStackSlots(); }
    6024             : 
    6025             :  private:
    6026             :   wasm::LinkageAllocator allocator_;
    6027             : };
    6028             : }  // namespace
    6029             : 
    6030             : // General code uses the above configuration data.
    6031     3029095 : CallDescriptor* GetWasmCallDescriptor(
    6032    13827960 :     Zone* zone, wasm::FunctionSig* fsig,
    6033             :     WasmGraphBuilder::UseRetpoline use_retpoline,
    6034             :     WasmGraphBuilder::ExtraCallableParam extra_callable_param) {
    6035             :   // The extra here is to accomodate the instance object as first parameter
    6036             :   // and, in the case of an import wrapper, the additional callable.
    6037     3029095 :   int extra_params = extra_callable_param ? 2 : 1;
    6038             :   LocationSignature::Builder locations(zone, fsig->return_count(),
    6039     3029095 :                                        fsig->parameter_count() + extra_params);
    6040             : 
    6041             :   // Add register and/or stack parameter(s).
    6042             :   LinkageLocationAllocator params(wasm::kGpParamRegisters,
    6043     3029225 :                                   wasm::kFpParamRegisters);
    6044             : 
    6045             :   // The instance object.
    6046     3029225 :   locations.AddParam(params.Next(MachineRepresentation::kTaggedPointer));
    6047             :   const size_t param_offset = 1;  // Actual params start here.
    6048             : 
    6049             :   // Parameters are separated into two groups (first all untagged, then all
    6050             :   // tagged parameters). This allows for easy iteration of tagged parameters
    6051             :   // during frame iteration.
    6052             :   const size_t parameter_count = fsig->parameter_count();
    6053     4040288 :   for (size_t i = 0; i < parameter_count; i++) {
    6054             :     MachineRepresentation param =
    6055     1011124 :         wasm::ValueTypes::MachineRepresentationFor(fsig->GetParam(i));
    6056             :     // Skip tagged parameters (e.g. any-ref).
    6057     1011998 :     if (IsAnyTagged(param)) continue;
    6058     1010132 :     auto l = params.Next(param);
    6059     1010209 :     locations.AddParamAt(i + param_offset, l);
    6060             :   }
    6061     1011171 :   for (size_t i = 0; i < parameter_count; i++) {
    6062             :     MachineRepresentation param =
    6063     1011149 :         wasm::ValueTypes::MachineRepresentationFor(fsig->GetParam(i));
    6064             :     // Skip untagged parameters.
    6065     2021401 :     if (!IsAnyTagged(param)) continue;
    6066         933 :     auto l = params.Next(param);
    6067         937 :     locations.AddParamAt(i + param_offset, l);
    6068             :   }
    6069             : 
    6070             :   // Import call wrappers have an additional (implicit) parameter, the callable.
    6071             :   // For consistency with JS, we use the JSFunction register.
    6072     3029186 :   if (extra_callable_param) {
    6073             :     locations.AddParam(LinkageLocation::ForRegister(
    6074             :         kJSFunctionRegister.code(), MachineType::TaggedPointer()));
    6075             :   }
    6076             : 
    6077             :   // Add return location(s).
    6078             :   LinkageLocationAllocator rets(wasm::kGpReturnRegisters,
    6079     3029186 :                                 wasm::kFpReturnRegisters);
    6080             : 
    6081             :   int parameter_slots = params.NumStackSlots();
    6082             :   if (kPadArguments) parameter_slots = RoundUp(parameter_slots, 2);
    6083             : 
    6084             :   rets.SetStackOffset(parameter_slots);
    6085             : 
    6086     3029186 :   const int return_count = static_cast<int>(locations.return_count_);
    6087     5747559 :   for (int i = 0; i < return_count; i++) {
    6088             :     MachineRepresentation ret =
    6089     5436702 :         wasm::ValueTypes::MachineRepresentationFor(fsig->GetReturn(i));
    6090     2718366 :     auto l = rets.Next(ret);
    6091     2718373 :     locations.AddReturn(l);
    6092             :   }
    6093             : 
    6094             :   const RegList kCalleeSaveRegisters = 0;
    6095             :   const RegList kCalleeSaveFPRegisters = 0;
    6096             : 
    6097             :   // The target for wasm calls is always a code object.
    6098             :   MachineType target_type = MachineType::Pointer();
    6099             :   LinkageLocation target_loc = LinkageLocation::ForAnyRegister(target_type);
    6100             : 
    6101             :   CallDescriptor::Kind kind = extra_callable_param
    6102             :                                   ? CallDescriptor::kCallWasmImportWrapper
    6103     3029208 :                                   : CallDescriptor::kCallWasmFunction;
    6104             : 
    6105             :   CallDescriptor::Flags flags =
    6106     3029208 :       use_retpoline ? CallDescriptor::kRetpoline : CallDescriptor::kNoFlags;
    6107             :   return new (zone) CallDescriptor(             // --
    6108             :       kind,                                     // kind
    6109             :       target_type,                              // target MachineType
    6110             :       target_loc,                               // target location
    6111             :       locations.Build(),                        // location_sig
    6112             :       parameter_slots,                          // stack_parameter_count
    6113             :       compiler::Operator::kNoProperties,        // properties
    6114             :       kCalleeSaveRegisters,                     // callee-saved registers
    6115             :       kCalleeSaveFPRegisters,                   // callee-saved fp regs
    6116             :       flags,                                    // flags
    6117             :       "wasm-call",                              // debug name
    6118             :       0,                                        // allocatable registers
    6119    12116742 :       rets.NumStackSlots() - parameter_slots);  // stack_return_count
    6120             : }
    6121             : 
    6122             : namespace {
    6123           0 : CallDescriptor* ReplaceTypeInCallDescriptorWith(
    6124           0 :     Zone* zone, CallDescriptor* call_descriptor, size_t num_replacements,
    6125             :     MachineType input_type, MachineRepresentation output_type) {
    6126             :   size_t parameter_count = call_descriptor->ParameterCount();
    6127             :   size_t return_count = call_descriptor->ReturnCount();
    6128           0 :   for (size_t i = 0; i < call_descriptor->ParameterCount(); i++) {
    6129           0 :     if (call_descriptor->GetParameterType(i) == input_type) {
    6130           0 :       parameter_count += num_replacements - 1;
    6131             :     }
    6132             :   }
    6133           0 :   for (size_t i = 0; i < call_descriptor->ReturnCount(); i++) {
    6134           0 :     if (call_descriptor->GetReturnType(i) == input_type) {
    6135           0 :       return_count += num_replacements - 1;
    6136             :     }
    6137             :   }
    6138           0 :   if (parameter_count == call_descriptor->ParameterCount() &&
    6139             :       return_count == call_descriptor->ReturnCount()) {
    6140             :     return call_descriptor;
    6141             :   }
    6142             : 
    6143             :   LocationSignature::Builder locations(zone, return_count, parameter_count);
    6144             : 
    6145             :   LinkageLocationAllocator params(wasm::kGpParamRegisters,
    6146           0 :                                   wasm::kFpParamRegisters);
    6147           0 :   for (size_t i = 0; i < call_descriptor->ParameterCount(); i++) {
    6148           0 :     if (call_descriptor->GetParameterType(i) == input_type) {
    6149           0 :       for (size_t j = 0; j < num_replacements; j++) {
    6150           0 :         locations.AddParam(params.Next(output_type));
    6151             :       }
    6152             :     } else {
    6153             :       locations.AddParam(
    6154           0 :           params.Next(call_descriptor->GetParameterType(i).representation()));
    6155             :     }
    6156             :   }
    6157             : 
    6158             :   LinkageLocationAllocator rets(wasm::kGpReturnRegisters,
    6159           0 :                                 wasm::kFpReturnRegisters);
    6160             :   rets.SetStackOffset(params.NumStackSlots());
    6161           0 :   for (size_t i = 0; i < call_descriptor->ReturnCount(); i++) {
    6162           0 :     if (call_descriptor->GetReturnType(i) == input_type) {
    6163           0 :       for (size_t j = 0; j < num_replacements; j++) {
    6164           0 :         locations.AddReturn(rets.Next(output_type));
    6165             :       }
    6166             :     } else {
    6167             :       locations.AddReturn(
    6168           0 :           rets.Next(call_descriptor->GetReturnType(i).representation()));
    6169             :     }
    6170             :   }
    6171             : 
    6172             :   return new (zone) CallDescriptor(                    // --
    6173             :       call_descriptor->kind(),                         // kind
    6174             :       call_descriptor->GetInputType(0),                // target MachineType
    6175             :       call_descriptor->GetInputLocation(0),            // target location
    6176             :       locations.Build(),                               // location_sig
    6177             :       params.NumStackSlots(),                          // stack_parameter_count
    6178             :       call_descriptor->properties(),                   // properties
    6179             :       call_descriptor->CalleeSavedRegisters(),         // callee-saved registers
    6180             :       call_descriptor->CalleeSavedFPRegisters(),       // callee-saved fp regs
    6181             :       call_descriptor->flags(),                        // flags
    6182             :       call_descriptor->debug_name(),                   // debug name
    6183             :       call_descriptor->AllocatableRegisters(),         // allocatable registers
    6184           0 :       rets.NumStackSlots() - params.NumStackSlots());  // stack_return_count
    6185             : }
    6186             : }  // namespace
    6187             : 
    6188           0 : CallDescriptor* GetI32WasmCallDescriptor(Zone* zone,
    6189             :                                          CallDescriptor* call_descriptor) {
    6190             :   return ReplaceTypeInCallDescriptorWith(zone, call_descriptor, 2,
    6191             :                                          MachineType::Int64(),
    6192           0 :                                          MachineRepresentation::kWord32);
    6193             : }
    6194             : 
    6195           0 : CallDescriptor* GetI32WasmCallDescriptorForSimd(
    6196             :     Zone* zone, CallDescriptor* call_descriptor) {
    6197             :   return ReplaceTypeInCallDescriptorWith(zone, call_descriptor, 4,
    6198             :                                          MachineType::Simd128(),
    6199           0 :                                          MachineRepresentation::kWord32);
    6200             : }
    6201             : 
    6202     1059903 : AssemblerOptions WasmAssemblerOptions() {
    6203     1216884 :   AssemblerOptions options;
    6204             :   // Relocation info required to serialize {WasmCode} for proper functions.
    6205             :   options.record_reloc_info_for_serialization = true;
    6206             :   options.enable_root_array_delta_access = false;
    6207     1059903 :   return options;
    6208             : }
    6209             : 
    6210           0 : AssemblerOptions WasmStubAssemblerOptions() {
    6211        8553 :   AssemblerOptions options;
    6212             :   // Relocation info not necessary because stubs are not serialized.
    6213        8553 :   options.record_reloc_info_for_serialization = false;
    6214             :   options.enable_root_array_delta_access = false;
    6215           0 :   return options;
    6216             : }
    6217             : 
    6218             : #undef WASM_64
    6219             : #undef FATAL_UNSUPPORTED_OPCODE
    6220             : #undef WASM_INSTANCE_OBJECT_SIZE
    6221             : #undef WASM_INSTANCE_OBJECT_OFFSET
    6222             : #undef LOAD_RAW
    6223             : #undef LOAD_INSTANCE_FIELD
    6224             : #undef LOAD_TAGGED_POINTER
    6225             : #undef LOAD_TAGGED_ANY
    6226             : #undef LOAD_FIXED_ARRAY_SLOT
    6227             : #undef LOAD_FIXED_ARRAY_SLOT_SMI
    6228             : #undef LOAD_FIXED_ARRAY_SLOT_PTR
    6229             : #undef LOAD_FIXED_ARRAY_SLOT_ANY
    6230             : #undef STORE_FIXED_ARRAY_SLOT_SMI
    6231             : #undef STORE_FIXED_ARRAY_SLOT_ANY
    6232             : 
    6233             : }  // namespace compiler
    6234             : }  // namespace internal
    6235      183867 : }  // namespace v8

Generated by: LCOV version 1.10