LCOV - code coverage report
Current view: top level - src/compiler - wasm-compiler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1573 1992 79.0 %
Date: 2017-10-20 Functions: 141 187 75.4 %

          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/base/optional.h"
      11             : #include "src/base/platform/elapsed-timer.h"
      12             : #include "src/base/platform/platform.h"
      13             : #include "src/builtins/builtins.h"
      14             : #include "src/code-factory.h"
      15             : #include "src/compiler/access-builder.h"
      16             : #include "src/compiler/common-operator.h"
      17             : #include "src/compiler/compiler-source-position-table.h"
      18             : #include "src/compiler/diamond.h"
      19             : #include "src/compiler/graph-visualizer.h"
      20             : #include "src/compiler/graph.h"
      21             : #include "src/compiler/instruction-selector.h"
      22             : #include "src/compiler/int64-lowering.h"
      23             : #include "src/compiler/js-graph.h"
      24             : #include "src/compiler/js-operator.h"
      25             : #include "src/compiler/linkage.h"
      26             : #include "src/compiler/machine-operator.h"
      27             : #include "src/compiler/node-matchers.h"
      28             : #include "src/compiler/pipeline.h"
      29             : #include "src/compiler/simd-scalar-lowering.h"
      30             : #include "src/compiler/zone-stats.h"
      31             : #include "src/factory.h"
      32             : #include "src/isolate-inl.h"
      33             : #include "src/log-inl.h"
      34             : #include "src/wasm/function-body-decoder.h"
      35             : #include "src/wasm/wasm-limits.h"
      36             : #include "src/wasm/wasm-module.h"
      37             : #include "src/wasm/wasm-objects-inl.h"
      38             : #include "src/wasm/wasm-opcodes.h"
      39             : #include "src/wasm/wasm-text.h"
      40             : 
      41             : namespace v8 {
      42             : namespace internal {
      43             : namespace compiler {
      44             : 
      45             : // TODO(titzer): pull WASM_64 up to a common header.
      46             : #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64
      47             : #define WASM_64 1
      48             : #else
      49             : #define WASM_64 0
      50             : #endif
      51             : 
      52             : #define FATAL_UNSUPPORTED_OPCODE(opcode)                              \
      53             :   V8_Fatal(__FILE__, __LINE__, "Unsupported opcode #%d:%s", (opcode), \
      54             :            wasm::WasmOpcodes::OpcodeName(opcode));
      55             : 
      56             : namespace {
      57             : 
      58             : constexpr uint32_t kBytesPerExceptionValuesArrayElement = 2;
      59             : 
      60     1481654 : void MergeControlToEnd(JSGraph* jsgraph, Node* node) {
      61      740827 :   Graph* g = jsgraph->graph();
      62      740827 :   if (g->end()) {
      63      200525 :     NodeProperties::MergeControlToEnd(g, jsgraph->common(), node);
      64             :   } else {
      65      540302 :     g->SetEnd(g->NewNode(jsgraph->common()->End(1), node));
      66             :   }
      67      740908 : }
      68             : 
      69             : }  // namespace
      70             : 
      71      545199 : WasmGraphBuilder::WasmGraphBuilder(
      72             :     ModuleEnv* env, Zone* zone, JSGraph* jsgraph, Handle<Code> centry_stub,
      73     1913251 :     wasm::FunctionSig* sig,
      74             :     compiler::SourcePositionTable* source_position_table,
      75             :     RuntimeExceptionSupport exception_support)
      76             :     : zone_(zone),
      77             :       jsgraph_(jsgraph),
      78     1090368 :       centry_stub_node_(jsgraph_->HeapConstant(centry_stub)),
      79             :       env_(env),
      80             :       signature_tables_(zone),
      81             :       function_tables_(zone),
      82             :       function_table_sizes_(zone),
      83             :       cur_buffer_(def_buffer_),
      84             :       cur_bufsize_(kDefaultBufferSize),
      85             :       runtime_exception_support_(exception_support),
      86             :       sig_(sig),
      87     2725875 :       source_position_table_(source_position_table) {
      88     1662560 :   for (size_t i = sig->parameter_count(); i > 0 && !has_simd_; --i) {
      89     1144444 :     if (sig->GetParam(i - 1) == wasm::kWasmS128) has_simd_ = true;
      90             :   }
      91     1341029 :   for (size_t i = sig->return_count(); i > 0 && !has_simd_; --i) {
      92      501382 :     if (sig->GetReturn(i - 1) == wasm::kWasmS128) has_simd_ = true;
      93             :   }
      94             :   DCHECK_NOT_NULL(jsgraph_);
      95      545169 : }
      96             : 
      97           0 : Node* WasmGraphBuilder::Error() { return jsgraph()->Dead(); }
      98             : 
      99     1090418 : Node* WasmGraphBuilder::Start(unsigned params) {
     100     1090418 :   Node* start = graph()->NewNode(jsgraph()->common()->Start(params));
     101             :   graph()->SetStart(start);
     102      545223 :   return start;
     103             : }
     104             : 
     105      805567 : Node* WasmGraphBuilder::Param(unsigned index) {
     106             :   return graph()->NewNode(jsgraph()->common()->Parameter(index),
     107     1611120 :                           graph()->start());
     108             : }
     109             : 
     110       11622 : Node* WasmGraphBuilder::Loop(Node* entry) {
     111       23243 :   return graph()->NewNode(jsgraph()->common()->Loop(1), entry);
     112             : }
     113             : 
     114       23248 : Node* WasmGraphBuilder::Terminate(Node* effect, Node* control) {
     115             :   Node* terminate =
     116       11624 :       graph()->NewNode(jsgraph()->common()->Terminate(), effect, control);
     117       11624 :   MergeControlToEnd(jsgraph(), terminate);
     118       11624 :   return terminate;
     119             : }
     120             : 
     121       16797 : unsigned WasmGraphBuilder::InputCount(Node* node) {
     122       16797 :   return static_cast<unsigned>(node->InputCount());
     123             : }
     124             : 
     125     3094031 : bool WasmGraphBuilder::IsPhiWithMerge(Node* phi, Node* merge) {
     126     3380892 :   return phi && IrOpcode::IsPhiOpcode(phi->opcode()) &&
     127     1833875 :          NodeProperties::GetControlInput(phi) == merge;
     128             : }
     129             : 
     130         190 : bool WasmGraphBuilder::ThrowsException(Node* node, Node** if_success,
     131         180 :                                        Node** if_exception) {
     132         190 :   if (node->op()->HasProperty(compiler::Operator::kNoThrow)) {
     133             :     return false;
     134             :   }
     135             : 
     136         180 :   *if_success = graph()->NewNode(jsgraph()->common()->IfSuccess(), node);
     137             :   *if_exception =
     138         180 :       graph()->NewNode(jsgraph()->common()->IfException(), node, node);
     139             : 
     140          90 :   return true;
     141             : }
     142             : 
     143      539119 : void WasmGraphBuilder::AppendToMerge(Node* merge, Node* from) {
     144             :   DCHECK(IrOpcode::IsMergeOpcode(merge->opcode()));
     145      269558 :   merge->AppendInput(jsgraph()->zone(), from);
     146             :   int new_size = merge->InputCount();
     147             :   NodeProperties::ChangeOp(
     148      269561 :       merge, jsgraph()->common()->ResizeMergeOrPhi(merge->op(), new_size));
     149      269558 : }
     150             : 
     151      433069 : void WasmGraphBuilder::AppendToPhi(Node* phi, Node* from) {
     152             :   DCHECK(IrOpcode::IsPhiOpcode(phi->opcode()));
     153             :   int new_size = phi->InputCount();
     154      288712 :   phi->InsertInput(jsgraph()->zone(), phi->InputCount() - 1, from);
     155             :   NodeProperties::ChangeOp(
     156      144357 :       phi, jsgraph()->common()->ResizeMergeOrPhi(phi->op(), new_size));
     157      144357 : }
     158             : 
     159      103194 : Node* WasmGraphBuilder::Merge(unsigned count, Node** controls) {
     160      154796 :   return graph()->NewNode(jsgraph()->common()->Merge(count), count, controls);
     161             : }
     162             : 
     163      191508 : Node* WasmGraphBuilder::Phi(wasm::ValueType type, unsigned count, Node** vals,
     164      191507 :                             Node* control) {
     165             :   DCHECK(IrOpcode::IsMergeOpcode(control->opcode()));
     166      191508 :   Node** buf = Realloc(vals, count, count + 1);
     167      191507 :   buf[count] = control;
     168             :   return graph()->NewNode(jsgraph()->common()->Phi(type, count), count + 1,
     169      574521 :                           buf);
     170             : }
     171             : 
     172       39885 : Node* WasmGraphBuilder::EffectPhi(unsigned count, Node** effects,
     173       39888 :                                   Node* control) {
     174             :   DCHECK(IrOpcode::IsMergeOpcode(control->opcode()));
     175       39885 :   Node** buf = Realloc(effects, count, count + 1);
     176       39888 :   buf[count] = control;
     177             :   return graph()->NewNode(jsgraph()->common()->EffectPhi(count), count + 1,
     178      119660 :                           buf);
     179             : }
     180             : 
     181           0 : Node* WasmGraphBuilder::NumberConstant(int32_t value) {
     182           0 :   return jsgraph()->Constant(value);
     183             : }
     184             : 
     185        3760 : Node* WasmGraphBuilder::Uint32Constant(uint32_t value) {
     186           0 :   return jsgraph()->Uint32Constant(value);
     187             : }
     188             : 
     189     1116270 : Node* WasmGraphBuilder::Int32Constant(int32_t value) {
     190     1116410 :   return jsgraph()->Int32Constant(value);
     191             : }
     192             : 
     193       46831 : Node* WasmGraphBuilder::Int64Constant(int64_t value) {
     194       46831 :   return jsgraph()->Int64Constant(value);
     195             : }
     196             : 
     197           0 : Node* WasmGraphBuilder::IntPtrConstant(intptr_t value) {
     198           0 :   return jsgraph()->IntPtrConstant(value);
     199             : }
     200             : 
     201      162469 : void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position,
     202     2029011 :                                   Node** effect, Node** control) {
     203             :   // TODO(mtrofin): "!env_" happens when we generate a wrapper.
     204             :   // We should factor wrappers separately from wasm codegen.
     205      162469 :   if (FLAG_wasm_no_stack_checks || !env_ || !runtime_exception_support_) {
     206        6396 :     return;
     207             :   }
     208      156073 :   if (effect == nullptr) effect = effect_;
     209      156073 :   if (control == nullptr) control = control_;
     210             : 
     211             :   Node* limit = graph()->NewNode(
     212             :       jsgraph()->machine()->Load(MachineType::Pointer()),
     213             :       jsgraph()->ExternalConstant(
     214             :           ExternalReference::address_of_stack_limit(jsgraph()->isolate())),
     215      780357 :       jsgraph()->IntPtrConstant(0), *effect, *control);
     216      156091 :   *effect = limit;
     217      156091 :   Node* pointer = graph()->NewNode(jsgraph()->machine()->LoadStackPointer());
     218             : 
     219             :   Node* check =
     220      156088 :       graph()->NewNode(jsgraph()->machine()->UintLessThan(), limit, pointer);
     221             : 
     222      312160 :   Diamond stack_check(graph(), jsgraph()->common(), check, BranchHint::kTrue);
     223      156079 :   stack_check.Chain(*control);
     224             : 
     225      156075 :   Handle<Code> code = BUILTIN_CODE(jsgraph()->isolate(), WasmStackGuard);
     226             :   CallInterfaceDescriptor idesc =
     227      312148 :       WasmRuntimeCallDescriptor(jsgraph()->isolate());
     228             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
     229             :       jsgraph()->isolate(), jsgraph()->zone(), idesc, 0,
     230             :       CallDescriptor::kNoFlags, Operator::kNoProperties,
     231      156086 :       MachineType::AnyTagged(), 1, Linkage::kNoContext);
     232      156065 :   Node* stub_code = jsgraph()->HeapConstant(code);
     233             : 
     234             :   Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), stub_code,
     235      312174 :                                 *effect, stack_check.if_false);
     236             : 
     237      156087 :   SetSourcePosition(call, position);
     238             : 
     239             :   Node* ephi = graph()->NewNode(jsgraph()->common()->EffectPhi(2), *effect,
     240      312186 :                                 call, stack_check.merge);
     241             : 
     242      156089 :   *control = stack_check.merge;
     243      156089 :   *effect = ephi;
     244             : }
     245             : 
     246      228445 : void WasmGraphBuilder::PatchInStackCheckIfNeeded() {
     247      312063 :   if (!needs_stack_check_) return;
     248             : 
     249      150796 :   Node* start = graph()->start();
     250             :   // Place a stack check which uses a dummy node as control and effect.
     251      150796 :   Node* dummy = graph()->NewNode(jsgraph()->common()->Dead());
     252      150857 :   Node* control = dummy;
     253      150857 :   Node* effect = dummy;
     254             :   // The function-prologue stack check is associated with position 0, which
     255             :   // is never a position of any instruction in the function.
     256      150857 :   StackCheck(0, &effect, &control);
     257             : 
     258             :   // In testing, no steck checks were emitted. Nothing to rewire then.
     259      150861 :   if (effect == dummy) return;
     260             : 
     261             :   // Now patch all control uses of {start} to use {control} and all effect uses
     262             :   // to use {effect} instead. Then rewire the dummy node to use start instead.
     263      144892 :   NodeProperties::ReplaceUses(start, start, effect, control);
     264      144891 :   NodeProperties::ReplaceUses(dummy, nullptr, start, start);
     265             : }
     266             : 
     267      992565 : Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
     268      992565 :                               wasm::WasmCodePosition position) {
     269             :   const Operator* op;
     270      992565 :   MachineOperatorBuilder* m = jsgraph()->machine();
     271      992565 :   switch (opcode) {
     272             :     case wasm::kExprI32Add:
     273      446462 :       op = m->Int32Add();
     274      446462 :       break;
     275             :     case wasm::kExprI32Sub:
     276       17054 :       op = m->Int32Sub();
     277       17051 :       break;
     278             :     case wasm::kExprI32Mul:
     279        5372 :       op = m->Int32Mul();
     280        5372 :       break;
     281             :     case wasm::kExprI32DivS:
     282         338 :       return BuildI32DivS(left, right, position);
     283             :     case wasm::kExprI32DivU:
     284         222 :       return BuildI32DivU(left, right, position);
     285             :     case wasm::kExprI32RemS:
     286         156 :       return BuildI32RemS(left, right, position);
     287             :     case wasm::kExprI32RemU:
     288         142 :       return BuildI32RemU(left, right, position);
     289             :     case wasm::kExprI32And:
     290      141523 :       op = m->Word32And();
     291      141523 :       break;
     292             :     case wasm::kExprI32Ior:
     293        7537 :       op = m->Word32Or();
     294        7537 :       break;
     295             :     case wasm::kExprI32Xor:
     296        1284 :       op = m->Word32Xor();
     297        1284 :       break;
     298             :     case wasm::kExprI32Shl:
     299       16006 :       op = m->Word32Shl();
     300       16006 :       right = MaskShiftCount32(right);
     301       16006 :       break;
     302             :     case wasm::kExprI32ShrU:
     303       21294 :       op = m->Word32Shr();
     304       21294 :       right = MaskShiftCount32(right);
     305       21294 :       break;
     306             :     case wasm::kExprI32ShrS:
     307        2177 :       op = m->Word32Sar();
     308        2177 :       right = MaskShiftCount32(right);
     309        2177 :       break;
     310             :     case wasm::kExprI32Ror:
     311         128 :       op = m->Word32Ror();
     312         128 :       right = MaskShiftCount32(right);
     313         128 :       break;
     314             :     case wasm::kExprI32Rol:
     315          64 :       right = MaskShiftCount32(right);
     316          64 :       return BuildI32Rol(left, right);
     317             :     case wasm::kExprI32Eq:
     318      155622 :       op = m->Word32Equal();
     319      155622 :       break;
     320             :     case wasm::kExprI32Ne:
     321       21559 :       return Invert(Binop(wasm::kExprI32Eq, left, right));
     322             :     case wasm::kExprI32LtS:
     323        2698 :       op = m->Int32LessThan();
     324        2698 :       break;
     325             :     case wasm::kExprI32LeS:
     326        1179 :       op = m->Int32LessThanOrEqual();
     327        1179 :       break;
     328             :     case wasm::kExprI32LtU:
     329        6051 :       op = m->Uint32LessThan();
     330        6051 :       break;
     331             :     case wasm::kExprI32LeU:
     332         176 :       op = m->Uint32LessThanOrEqual();
     333         176 :       break;
     334             :     case wasm::kExprI32GtS:
     335        3036 :       op = m->Int32LessThan();
     336             :       std::swap(left, right);
     337             :       break;
     338             :     case wasm::kExprI32GeS:
     339         830 :       op = m->Int32LessThanOrEqual();
     340             :       std::swap(left, right);
     341             :       break;
     342             :     case wasm::kExprI32GtU:
     343        2384 :       op = m->Uint32LessThan();
     344             :       std::swap(left, right);
     345             :       break;
     346             :     case wasm::kExprI32GeU:
     347         212 :       op = m->Uint32LessThanOrEqual();
     348             :       std::swap(left, right);
     349             :       break;
     350             :     case wasm::kExprI64And:
     351        9730 :       op = m->Word64And();
     352        9730 :       break;
     353             :     case wasm::kExprI64Add:
     354         208 :       op = m->Int64Add();
     355         208 :       break;
     356             :     case wasm::kExprI64Sub:
     357         389 :       op = m->Int64Sub();
     358         389 :       break;
     359             :     case wasm::kExprI64Mul:
     360         359 :       op = m->Int64Mul();
     361         359 :       break;
     362             :     case wasm::kExprI64DivS:
     363         306 :       return BuildI64DivS(left, right, position);
     364             :     case wasm::kExprI64DivU:
     365         154 :       return BuildI64DivU(left, right, position);
     366             :     case wasm::kExprI64RemS:
     367         134 :       return BuildI64RemS(left, right, position);
     368             :     case wasm::kExprI64RemU:
     369         134 :       return BuildI64RemU(left, right, position);
     370             :     case wasm::kExprI64Ior:
     371         178 :       op = m->Word64Or();
     372         178 :       break;
     373             :     case wasm::kExprI64Xor:
     374         134 :       op = m->Word64Xor();
     375         134 :       break;
     376             :     case wasm::kExprI64Shl:
     377         314 :       op = m->Word64Shl();
     378         313 :       right = MaskShiftCount64(right);
     379         314 :       break;
     380             :     case wasm::kExprI64ShrU:
     381         332 :       op = m->Word64Shr();
     382         332 :       right = MaskShiftCount64(right);
     383         332 :       break;
     384             :     case wasm::kExprI64ShrS:
     385         142 :       op = m->Word64Sar();
     386         142 :       right = MaskShiftCount64(right);
     387         142 :       break;
     388             :     case wasm::kExprI64Eq:
     389       41411 :       op = m->Word64Equal();
     390       41411 :       break;
     391             :     case wasm::kExprI64Ne:
     392          62 :       return Invert(Binop(wasm::kExprI64Eq, left, right));
     393             :     case wasm::kExprI64LtS:
     394          92 :       op = m->Int64LessThan();
     395          92 :       break;
     396             :     case wasm::kExprI64LeS:
     397          62 :       op = m->Int64LessThanOrEqual();
     398          62 :       break;
     399             :     case wasm::kExprI64LtU:
     400          72 :       op = m->Uint64LessThan();
     401          72 :       break;
     402             :     case wasm::kExprI64LeU:
     403          82 :       op = m->Uint64LessThanOrEqual();
     404          82 :       break;
     405             :     case wasm::kExprI64GtS:
     406          72 :       op = m->Int64LessThan();
     407             :       std::swap(left, right);
     408             :       break;
     409             :     case wasm::kExprI64GeS:
     410          62 :       op = m->Int64LessThanOrEqual();
     411             :       std::swap(left, right);
     412             :       break;
     413             :     case wasm::kExprI64GtU:
     414          72 :       op = m->Uint64LessThan();
     415             :       std::swap(left, right);
     416             :       break;
     417             :     case wasm::kExprI64GeU:
     418          62 :       op = m->Uint64LessThanOrEqual();
     419             :       std::swap(left, right);
     420             :       break;
     421             :     case wasm::kExprI64Ror:
     422         152 :       op = m->Word64Ror();
     423         152 :       right = MaskShiftCount64(right);
     424         152 :       break;
     425             :     case wasm::kExprI64Rol:
     426          76 :       return BuildI64Rol(left, right);
     427             :     case wasm::kExprF32CopySign:
     428          54 :       return BuildF32CopySign(left, right);
     429             :     case wasm::kExprF64CopySign:
     430          54 :       return BuildF64CopySign(left, right);
     431             :     case wasm::kExprF32Add:
     432         625 :       op = m->Float32Add();
     433         625 :       break;
     434             :     case wasm::kExprF32Sub:
     435         461 :       op = m->Float32Sub();
     436         461 :       break;
     437             :     case wasm::kExprF32Mul:
     438         577 :       op = m->Float32Mul();
     439         577 :       break;
     440             :     case wasm::kExprF32Div:
     441         508 :       op = m->Float32Div();
     442         509 :       break;
     443             :     case wasm::kExprF32Eq:
     444         580 :       op = m->Float32Equal();
     445         577 :       break;
     446             :     case wasm::kExprF32Ne:
     447         450 :       return Invert(Binop(wasm::kExprF32Eq, left, right));
     448             :     case wasm::kExprF32Lt:
     449         167 :       op = m->Float32LessThan();
     450         167 :       break;
     451             :     case wasm::kExprF32Ge:
     452         147 :       op = m->Float32LessThanOrEqual();
     453             :       std::swap(left, right);
     454             :       break;
     455             :     case wasm::kExprF32Gt:
     456         177 :       op = m->Float32LessThan();
     457             :       std::swap(left, right);
     458             :       break;
     459             :     case wasm::kExprF32Le:
     460         157 :       op = m->Float32LessThanOrEqual();
     461         157 :       break;
     462             :     case wasm::kExprF64Add:
     463        5801 :       op = m->Float64Add();
     464        5800 :       break;
     465             :     case wasm::kExprF64Sub:
     466        4095 :       op = m->Float64Sub();
     467        4095 :       break;
     468             :     case wasm::kExprF64Mul:
     469        9022 :       op = m->Float64Mul();
     470        9022 :       break;
     471             :     case wasm::kExprF64Div:
     472         984 :       op = m->Float64Div();
     473         984 :       break;
     474             :     case wasm::kExprF64Eq:
     475        1067 :       op = m->Float64Equal();
     476        1067 :       break;
     477             :     case wasm::kExprF64Ne:
     478         621 :       return Invert(Binop(wasm::kExprF64Eq, left, right));
     479             :     case wasm::kExprF64Lt:
     480        1007 :       op = m->Float64LessThan();
     481        1007 :       break;
     482             :     case wasm::kExprF64Le:
     483         400 :       op = m->Float64LessThanOrEqual();
     484         400 :       break;
     485             :     case wasm::kExprF64Gt:
     486         973 :       op = m->Float64LessThan();
     487             :       std::swap(left, right);
     488             :       break;
     489             :     case wasm::kExprF64Ge:
     490         428 :       op = m->Float64LessThanOrEqual();
     491             :       std::swap(left, right);
     492             :       break;
     493             :     case wasm::kExprF32Min:
     494          72 :       op = m->Float32Min();
     495          72 :       break;
     496             :     case wasm::kExprF64Min:
     497          66 :       op = m->Float64Min();
     498          66 :       break;
     499             :     case wasm::kExprF32Max:
     500          72 :       op = m->Float32Max();
     501          72 :       break;
     502             :     case wasm::kExprF64Max:
     503          66 :       op = m->Float64Max();
     504          66 :       break;
     505             :     case wasm::kExprF64Pow:
     506          13 :       return BuildF64Pow(left, right);
     507             :     case wasm::kExprF64Atan2:
     508          13 :       op = m->Float64Atan2();
     509          13 :       break;
     510             :     case wasm::kExprF64Mod:
     511          30 :       return BuildF64Mod(left, right);
     512             :     case wasm::kExprI32AsmjsDivS:
     513         524 :       return BuildI32AsmjsDivS(left, right);
     514             :     case wasm::kExprI32AsmjsDivU:
     515         191 :       return BuildI32AsmjsDivU(left, right);
     516             :     case wasm::kExprI32AsmjsRemS:
     517         608 :       return BuildI32AsmjsRemS(left, right);
     518             :     case wasm::kExprI32AsmjsRemU:
     519         260 :       return BuildI32AsmjsRemU(left, right);
     520             :     case wasm::kExprI32AsmjsStoreMem8:
     521        4069 :       return BuildAsmjsStoreMem(MachineType::Int8(), left, right);
     522             :     case wasm::kExprI32AsmjsStoreMem16:
     523        1891 :       return BuildAsmjsStoreMem(MachineType::Int16(), left, right);
     524             :     case wasm::kExprI32AsmjsStoreMem:
     525       42528 :       return BuildAsmjsStoreMem(MachineType::Int32(), left, right);
     526             :     case wasm::kExprF32AsmjsStoreMem:
     527        4615 :       return BuildAsmjsStoreMem(MachineType::Float32(), left, right);
     528             :     case wasm::kExprF64AsmjsStoreMem:
     529         895 :       return BuildAsmjsStoreMem(MachineType::Float64(), left, right);
     530             :     default:
     531           0 :       FATAL_UNSUPPORTED_OPCODE(opcode);
     532             :   }
     533      912386 :   return graph()->NewNode(op, left, right);
     534             : }
     535             : 
     536      391578 : Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input,
     537      556245 :                              wasm::WasmCodePosition position) {
     538             :   const Operator* op;
     539      391578 :   MachineOperatorBuilder* m = jsgraph()->machine();
     540      391578 :   switch (opcode) {
     541             :     case wasm::kExprI32Eqz:
     542      164455 :       op = m->Word32Equal();
     543      328918 :       return graph()->NewNode(op, input, jsgraph()->Int32Constant(0));
     544             :     case wasm::kExprF32Abs:
     545          86 :       op = m->Float32Abs();
     546          86 :       break;
     547             :     case wasm::kExprF32Neg: {
     548         288 :       op = m->Float32Neg();
     549         288 :       break;
     550             :     }
     551             :     case wasm::kExprF32Sqrt:
     552         202 :       op = m->Float32Sqrt();
     553         202 :       break;
     554             :     case wasm::kExprF64Abs:
     555         120 :       op = m->Float64Abs();
     556         120 :       break;
     557             :     case wasm::kExprF64Neg: {
     558        1455 :       op = m->Float64Neg();
     559        1455 :       break;
     560             :     }
     561             :     case wasm::kExprF64Sqrt:
     562         320 :       op = m->Float64Sqrt();
     563         320 :       break;
     564             :     case wasm::kExprI32SConvertF64:
     565         262 :       return BuildI32SConvertF64(input, position);
     566             :     case wasm::kExprI32UConvertF64:
     567          58 :       return BuildI32UConvertF64(input, position);
     568             :     case wasm::kExprI32AsmjsSConvertF64:
     569         130 :       return BuildI32AsmjsSConvertF64(input);
     570             :     case wasm::kExprI32AsmjsUConvertF64:
     571          12 :       return BuildI32AsmjsUConvertF64(input);
     572             :     case wasm::kExprF32ConvertF64:
     573        4839 :       op = m->TruncateFloat64ToFloat32();
     574        4838 :       break;
     575             :     case wasm::kExprF64SConvertI32:
     576         875 :       op = m->ChangeInt32ToFloat64();
     577         875 :       break;
     578             :     case wasm::kExprF64UConvertI32:
     579         399 :       op = m->ChangeUint32ToFloat64();
     580         399 :       break;
     581             :     case wasm::kExprF32SConvertI32:
     582         394 :       op = m->RoundInt32ToFloat32();
     583         394 :       break;
     584             :     case wasm::kExprF32UConvertI32:
     585         130 :       op = m->RoundUint32ToFloat32();
     586         130 :       break;
     587             :     case wasm::kExprI32SConvertF32:
     588         272 :       return BuildI32SConvertF32(input, position);
     589             :     case wasm::kExprI32UConvertF32:
     590          68 :       return BuildI32UConvertF32(input, position);
     591             :     case wasm::kExprI32AsmjsSConvertF32:
     592          12 :       return BuildI32AsmjsSConvertF32(input);
     593             :     case wasm::kExprI32AsmjsUConvertF32:
     594          12 :       return BuildI32AsmjsUConvertF32(input);
     595             :     case wasm::kExprF64ConvertF32:
     596        7789 :       op = m->ChangeFloat32ToFloat64();
     597        7789 :       break;
     598             :     case wasm::kExprF32ReinterpretI32:
     599         236 :       op = m->BitcastInt32ToFloat32();
     600         236 :       break;
     601             :     case wasm::kExprI32ReinterpretF32:
     602       62798 :       op = m->BitcastFloat32ToInt32();
     603       62798 :       break;
     604             :     case wasm::kExprI32Clz:
     605        1890 :       op = m->Word32Clz();
     606        1890 :       break;
     607             :     case wasm::kExprI32Ctz: {
     608         858 :       if (m->Word32Ctz().IsSupported()) {
     609         858 :         op = m->Word32Ctz().op();
     610         858 :         break;
     611           0 :       } else if (m->Word32ReverseBits().IsSupported()) {
     612           0 :         Node* reversed = graph()->NewNode(m->Word32ReverseBits().op(), input);
     613           0 :         Node* result = graph()->NewNode(m->Word32Clz(), reversed);
     614           0 :         return result;
     615             :       } else {
     616           0 :         return BuildI32Ctz(input);
     617             :       }
     618             :     }
     619             :     case wasm::kExprI32Popcnt: {
     620         158 :       if (m->Word32Popcnt().IsSupported()) {
     621         158 :         op = m->Word32Popcnt().op();
     622         158 :         break;
     623             :       } else {
     624           0 :         return BuildI32Popcnt(input);
     625             :       }
     626             :     }
     627             :     case wasm::kExprF32Floor: {
     628          57 :       if (!m->Float32RoundDown().IsSupported()) return BuildF32Floor(input);
     629          57 :       op = m->Float32RoundDown().op();
     630          57 :       break;
     631             :     }
     632             :     case wasm::kExprF32Ceil: {
     633          57 :       if (!m->Float32RoundUp().IsSupported()) return BuildF32Ceil(input);
     634          57 :       op = m->Float32RoundUp().op();
     635          57 :       break;
     636             :     }
     637             :     case wasm::kExprF32Trunc: {
     638         376 :       if (!m->Float32RoundTruncate().IsSupported()) return BuildF32Trunc(input);
     639         375 :       op = m->Float32RoundTruncate().op();
     640         375 :       break;
     641             :     }
     642             :     case wasm::kExprF32NearestInt: {
     643          38 :       if (!m->Float32RoundTiesEven().IsSupported())
     644           0 :         return BuildF32NearestInt(input);
     645          38 :       op = m->Float32RoundTiesEven().op();
     646          38 :       break;
     647             :     }
     648             :     case wasm::kExprF64Floor: {
     649         107 :       if (!m->Float64RoundDown().IsSupported()) return BuildF64Floor(input);
     650         107 :       op = m->Float64RoundDown().op();
     651         107 :       break;
     652             :     }
     653             :     case wasm::kExprF64Ceil: {
     654          69 :       if (!m->Float64RoundUp().IsSupported()) return BuildF64Ceil(input);
     655          69 :       op = m->Float64RoundUp().op();
     656          69 :       break;
     657             :     }
     658             :     case wasm::kExprF64Trunc: {
     659         357 :       if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input);
     660         356 :       op = m->Float64RoundTruncate().op();
     661         357 :       break;
     662             :     }
     663             :     case wasm::kExprF64NearestInt: {
     664          38 :       if (!m->Float64RoundTiesEven().IsSupported())
     665           0 :         return BuildF64NearestInt(input);
     666          38 :       op = m->Float64RoundTiesEven().op();
     667          38 :       break;
     668             :     }
     669             :     case wasm::kExprF64Acos: {
     670          19 :       return BuildF64Acos(input);
     671             :     }
     672             :     case wasm::kExprF64Asin: {
     673          19 :       return BuildF64Asin(input);
     674             :     }
     675             :     case wasm::kExprF64Atan:
     676          19 :       op = m->Float64Atan();
     677          19 :       break;
     678             :     case wasm::kExprF64Cos: {
     679         194 :       op = m->Float64Cos();
     680         194 :       break;
     681             :     }
     682             :     case wasm::kExprF64Sin: {
     683         194 :       op = m->Float64Sin();
     684         194 :       break;
     685             :     }
     686             :     case wasm::kExprF64Tan: {
     687          19 :       op = m->Float64Tan();
     688          19 :       break;
     689             :     }
     690             :     case wasm::kExprF64Exp: {
     691          19 :       op = m->Float64Exp();
     692          19 :       break;
     693             :     }
     694             :     case wasm::kExprF64Log:
     695          19 :       op = m->Float64Log();
     696          19 :       break;
     697             :     case wasm::kExprI32ConvertI64:
     698        1770 :       op = m->TruncateInt64ToInt32();
     699        1770 :       break;
     700             :     case wasm::kExprI64SConvertI32:
     701          90 :       op = m->ChangeInt32ToInt64();
     702          90 :       break;
     703             :     case wasm::kExprI64UConvertI32:
     704         172 :       op = m->ChangeUint32ToUint64();
     705         172 :       break;
     706             :     case wasm::kExprF64ReinterpretI64:
     707         292 :       op = m->BitcastInt64ToFloat64();
     708         292 :       break;
     709             :     case wasm::kExprI64ReinterpretF64:
     710       62404 :       op = m->BitcastFloat64ToInt64();
     711       62404 :       break;
     712             :     case wasm::kExprI64Clz:
     713          38 :       op = m->Word64Clz();
     714          38 :       break;
     715             :     case wasm::kExprI64Ctz: {
     716         188 :       OptionalOperator ctz64 = m->Word64Ctz();
     717         188 :       if (ctz64.IsSupported()) {
     718             :         op = ctz64.op();
     719         188 :         break;
     720           0 :       } else if (m->Is32() && m->Word32Ctz().IsSupported()) {
     721             :         op = ctz64.placeholder();
     722             :         break;
     723           0 :       } else if (m->Word64ReverseBits().IsSupported()) {
     724           0 :         Node* reversed = graph()->NewNode(m->Word64ReverseBits().op(), input);
     725           0 :         Node* result = graph()->NewNode(m->Word64Clz(), reversed);
     726           0 :         return result;
     727             :       } else {
     728           0 :         return BuildI64Ctz(input);
     729             :       }
     730             :     }
     731             :     case wasm::kExprI64Popcnt: {
     732          50 :       OptionalOperator popcnt64 = m->Word64Popcnt();
     733          50 :       if (popcnt64.IsSupported()) {
     734             :         op = popcnt64.op();
     735           0 :       } else if (m->Is32() && m->Word32Popcnt().IsSupported()) {
     736             :         op = popcnt64.placeholder();
     737             :       } else {
     738           0 :         return BuildI64Popcnt(input);
     739             :       }
     740          50 :       break;
     741             :     }
     742             :     case wasm::kExprI64Eqz:
     743         212 :       op = m->Word64Equal();
     744         424 :       return graph()->NewNode(op, input, jsgraph()->Int64Constant(0));
     745             :     case wasm::kExprF32SConvertI64:
     746          88 :       if (m->Is32()) {
     747           0 :         return BuildF32SConvertI64(input);
     748             :       }
     749          88 :       op = m->RoundInt64ToFloat32();
     750          88 :       break;
     751             :     case wasm::kExprF32UConvertI64:
     752          47 :       if (m->Is32()) {
     753           0 :         return BuildF32UConvertI64(input);
     754             :       }
     755          47 :       op = m->RoundUint64ToFloat32();
     756          47 :       break;
     757             :     case wasm::kExprF64SConvertI64:
     758         114 :       if (m->Is32()) {
     759           0 :         return BuildF64SConvertI64(input);
     760             :       }
     761         114 :       op = m->RoundInt64ToFloat64();
     762         114 :       break;
     763             :     case wasm::kExprF64UConvertI64:
     764         177 :       if (m->Is32()) {
     765           0 :         return BuildF64UConvertI64(input);
     766             :       }
     767         177 :       op = m->RoundUint64ToFloat64();
     768         175 :       break;
     769             :     case wasm::kExprI64SConvertF32:
     770          70 :       return BuildI64SConvertF32(input, position);
     771             :     case wasm::kExprI64SConvertF64:
     772         122 :       return BuildI64SConvertF64(input, position);
     773             :     case wasm::kExprI64UConvertF32:
     774          70 :       return BuildI64UConvertF32(input, position);
     775             :     case wasm::kExprI64UConvertF64:
     776          80 :       return BuildI64UConvertF64(input, position);
     777             :     case wasm::kExprI32AsmjsLoadMem8S:
     778        3770 :       return BuildAsmjsLoadMem(MachineType::Int8(), input);
     779             :     case wasm::kExprI32AsmjsLoadMem8U:
     780        2836 :       return BuildAsmjsLoadMem(MachineType::Uint8(), input);
     781             :     case wasm::kExprI32AsmjsLoadMem16S:
     782        1270 :       return BuildAsmjsLoadMem(MachineType::Int16(), input);
     783             :     case wasm::kExprI32AsmjsLoadMem16U:
     784         717 :       return BuildAsmjsLoadMem(MachineType::Uint16(), input);
     785             :     case wasm::kExprI32AsmjsLoadMem:
     786       58745 :       return BuildAsmjsLoadMem(MachineType::Int32(), input);
     787             :     case wasm::kExprF32AsmjsLoadMem:
     788        7558 :       return BuildAsmjsLoadMem(MachineType::Float32(), input);
     789             :     case wasm::kExprF64AsmjsLoadMem:
     790         979 :       return BuildAsmjsLoadMem(MachineType::Float64(), input);
     791             :     default:
     792           0 :       FATAL_UNSUPPORTED_OPCODE(opcode);
     793             :   }
     794      149820 :   return graph()->NewNode(op, input);
     795             : }
     796             : 
     797      147351 : Node* WasmGraphBuilder::Float32Constant(float value) {
     798      147351 :   return jsgraph()->Float32Constant(value);
     799             : }
     800             : 
     801      159314 : Node* WasmGraphBuilder::Float64Constant(double value) {
     802      159314 :   return jsgraph()->Float64Constant(value);
     803             : }
     804             : 
     805      332693 : Node* WasmGraphBuilder::HeapConstant(Handle<HeapObject> value) {
     806      332693 :   return jsgraph()->HeapConstant(value);
     807             : }
     808             : 
     809             : namespace {
     810     1359971 : Node* Branch(JSGraph* jsgraph, Node* cond, Node** true_node, Node** false_node,
     811             :              Node* control, BranchHint hint) {
     812             :   DCHECK_NOT_NULL(cond);
     813             :   DCHECK_NOT_NULL(control);
     814             :   Node* branch =
     815      226659 :       jsgraph->graph()->NewNode(jsgraph->common()->Branch(hint), cond, control);
     816      453324 :   *true_node = jsgraph->graph()->NewNode(jsgraph->common()->IfTrue(), branch);
     817      453327 :   *false_node = jsgraph->graph()->NewNode(jsgraph->common()->IfFalse(), branch);
     818      226664 :   return branch;
     819             : }
     820             : }  // namespace
     821             : 
     822      226012 : Node* WasmGraphBuilder::BranchNoHint(Node* cond, Node** true_node,
     823      226012 :                                      Node** false_node) {
     824             :   return Branch(jsgraph(), cond, true_node, false_node, *control_,
     825      452024 :                 BranchHint::kNone);
     826             : }
     827             : 
     828           0 : Node* WasmGraphBuilder::BranchExpectTrue(Node* cond, Node** true_node,
     829           0 :                                          Node** false_node) {
     830             :   return Branch(jsgraph(), cond, true_node, false_node, *control_,
     831           0 :                 BranchHint::kTrue);
     832             : }
     833             : 
     834           0 : Node* WasmGraphBuilder::BranchExpectFalse(Node* cond, Node** true_node,
     835         644 :                                           Node** false_node) {
     836             :   return Branch(jsgraph(), cond, true_node, false_node, *control_,
     837        1288 :                 BranchHint::kFalse);
     838             : }
     839             : 
     840      198441 : Builtins::Name WasmGraphBuilder::GetBuiltinIdForTrap(wasm::TrapReason reason) {
     841      198441 :   if (runtime_exception_support_ == kNoRuntimeExceptionSupport) {
     842             :     // We use Builtins::builtin_count as a marker to tell the code generator
     843             :     // to generate a call to a testing c-function instead of a runtime
     844             :     // function. This code should only be called from a cctest.
     845             :     return Builtins::builtin_count;
     846             :   }
     847             : 
     848      163413 :   switch (reason) {
     849             : #define TRAPREASON_TO_MESSAGE(name) \
     850             :   case wasm::k##name:               \
     851             :     return Builtins::kThrowWasm##name;
     852       27847 :     FOREACH_WASM_TRAPREASON(TRAPREASON_TO_MESSAGE)
     853             : #undef TRAPREASON_TO_MESSAGE
     854             :     default:
     855           0 :       UNREACHABLE();
     856             :   }
     857             : }
     858             : 
     859        1977 : Node* WasmGraphBuilder::TrapIfTrue(wasm::TrapReason reason, Node* cond,
     860        5934 :                                    wasm::WasmCodePosition position) {
     861        1977 :   Builtins::Name trap_id = GetBuiltinIdForTrap(reason);
     862             :   Node* node = graph()->NewNode(jsgraph()->common()->TrapIf(trap_id), cond,
     863        1978 :                                 Effect(), Control());
     864        1982 :   *control_ = node;
     865        1982 :   SetSourcePosition(node, position);
     866        1983 :   return node;
     867             : }
     868             : 
     869      196464 : Node* WasmGraphBuilder::TrapIfFalse(wasm::TrapReason reason, Node* cond,
     870      589443 :                                     wasm::WasmCodePosition position) {
     871      196464 :   Builtins::Name trap_id = GetBuiltinIdForTrap(reason);
     872             : 
     873             :   Node* node = graph()->NewNode(jsgraph()->common()->TrapUnless(trap_id), cond,
     874      196481 :                                 Effect(), Control());
     875      196486 :   *control_ = node;
     876      196486 :   SetSourcePosition(node, position);
     877      196494 :   return node;
     878             : }
     879             : 
     880             : // Add a check that traps if {node} is equal to {val}.
     881        1243 : Node* WasmGraphBuilder::TrapIfEq32(wasm::TrapReason reason, Node* node,
     882             :                                    int32_t val,
     883         632 :                                    wasm::WasmCodePosition position) {
     884             :   Int32Matcher m(node);
     885        2108 :   if (m.HasValue() && !m.Is(val)) return graph()->start();
     886         865 :   if (val == 0) {
     887         549 :     return TrapIfFalse(reason, node, position);
     888             :   } else {
     889             :     return TrapIfTrue(reason,
     890             :                       graph()->NewNode(jsgraph()->machine()->Word32Equal(),
     891             :                                        node, jsgraph()->Int32Constant(val)),
     892         948 :                       position);
     893             :   }
     894             : }
     895             : 
     896             : // Add a check that traps if {node} is zero.
     897           0 : Node* WasmGraphBuilder::ZeroCheck32(wasm::TrapReason reason, Node* node,
     898             :                                     wasm::WasmCodePosition position) {
     899         858 :   return TrapIfEq32(reason, node, 0, position);
     900             : }
     901             : 
     902             : // Add a check that traps if {node} is equal to {val}.
     903        1374 : Node* WasmGraphBuilder::TrapIfEq64(wasm::TrapReason reason, Node* node,
     904             :                                    int64_t val,
     905        2013 :                                    wasm::WasmCodePosition position) {
     906             :   Int64Matcher m(node);
     907        2142 :   if (m.HasValue() && !m.Is(val)) return graph()->start();
     908             :   return TrapIfTrue(reason,
     909             :                     graph()->NewNode(jsgraph()->machine()->Word64Equal(), node,
     910             :                                      jsgraph()->Int64Constant(val)),
     911        3021 :                     position);
     912             : }
     913             : 
     914             : // Add a check that traps if {node} is zero.
     915           0 : Node* WasmGraphBuilder::ZeroCheck64(wasm::TrapReason reason, Node* node,
     916             :                                     wasm::WasmCodePosition position) {
     917        1070 :   return TrapIfEq64(reason, node, 0, position);
     918             : }
     919             : 
     920       26148 : Node* WasmGraphBuilder::Switch(unsigned count, Node* key) {
     921       39222 :   return graph()->NewNode(jsgraph()->common()->Switch(count), key, *control_);
     922             : }
     923             : 
     924      284696 : Node* WasmGraphBuilder::IfValue(int32_t value, Node* sw) {
     925             :   DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
     926      569391 :   return graph()->NewNode(jsgraph()->common()->IfValue(value), sw);
     927             : }
     928             : 
     929       13074 : Node* WasmGraphBuilder::IfDefault(Node* sw) {
     930             :   DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
     931       26148 :   return graph()->NewNode(jsgraph()->common()->IfDefault(), sw);
     932             : }
     933             : 
     934     2373306 : Node* WasmGraphBuilder::Return(unsigned count, Node** vals) {
     935             :   DCHECK_NOT_NULL(*control_);
     936             :   DCHECK_NOT_NULL(*effect_);
     937             : 
     938             :   static const int kStackAllocatedNodeBufferSize = 8;
     939             :   Node* stack_buffer[kStackAllocatedNodeBufferSize];
     940             :   std::vector<Node*> heap_buffer;
     941             : 
     942             :   Node** buf = stack_buffer;
     943      593274 :   if (count + 3 > kStackAllocatedNodeBufferSize) {
     944           0 :     heap_buffer.resize(count + 3);
     945             :     buf = heap_buffer.data();
     946             :   }
     947             : 
     948      593274 :   buf[0] = jsgraph()->Int32Constant(0);
     949      593348 :   memcpy(buf + 1, vals, sizeof(void*) * count);
     950      593348 :   buf[count + 1] = *effect_;
     951      593348 :   buf[count + 2] = *control_;
     952             :   Node* ret =
     953     1779903 :       graph()->NewNode(jsgraph()->common()->Return(count), count + 3, buf);
     954             : 
     955      593410 :   MergeControlToEnd(jsgraph(), ret);
     956      593364 :   return ret;
     957             : }
     958             : 
     959      130051 : Node* WasmGraphBuilder::ReturnVoid() { return Return(0, nullptr); }
     960             : 
     961      129999 : Node* WasmGraphBuilder::Unreachable(wasm::WasmCodePosition position) {
     962      130001 :   TrapIfFalse(wasm::TrapReason::kTrapUnreachable, Int32Constant(0), position);
     963             :   ReturnVoid();
     964      130001 :   return nullptr;
     965             : }
     966             : 
     967       39704 : Node* WasmGraphBuilder::MaskShiftCount32(Node* node) {
     968             :   static const int32_t kMask32 = 0x1f;
     969       79336 :   if (!jsgraph()->machine()->Word32ShiftIsSafe()) {
     970             :     // Shifts by constants are so common we pattern-match them here.
     971             :     Int32Matcher match(node);
     972          36 :     if (match.HasValue()) {
     973           0 :       int32_t masked = (match.Value() & kMask32);
     974           0 :       if (match.Value() != masked) node = jsgraph()->Int32Constant(masked);
     975             :     } else {
     976             :       node = graph()->NewNode(jsgraph()->machine()->Word32And(), node,
     977          72 :                               jsgraph()->Int32Constant(kMask32));
     978             :     }
     979             :   }
     980       39668 :   return node;
     981             : }
     982             : 
     983         970 : Node* WasmGraphBuilder::MaskShiftCount64(Node* node) {
     984             :   static const int64_t kMask64 = 0x3f;
     985        1880 :   if (!jsgraph()->machine()->Word32ShiftIsSafe()) {
     986             :     // Shifts by constants are so common we pattern-match them here.
     987             :     Int64Matcher match(node);
     988          30 :     if (match.HasValue()) {
     989           0 :       int64_t masked = (match.Value() & kMask64);
     990           0 :       if (match.Value() != masked) node = jsgraph()->Int64Constant(masked);
     991             :     } else {
     992             :       node = graph()->NewNode(jsgraph()->machine()->Word64And(), node,
     993          60 :                               jsgraph()->Int64Constant(kMask64));
     994             :     }
     995             :   }
     996         940 :   return node;
     997             : }
     998             : 
     999           0 : static bool ReverseBytesSupported(MachineOperatorBuilder* m,
    1000             :                                   size_t size_in_bytes) {
    1001           0 :   switch (size_in_bytes) {
    1002             :     case 4:
    1003             :     case 16:
    1004           0 :       return m->Word32ReverseBytes().IsSupported();
    1005             :     case 8:
    1006           0 :       return m->Word64ReverseBytes().IsSupported();
    1007             :     default:
    1008             :       break;
    1009             :   }
    1010             :   return false;
    1011             : }
    1012             : 
    1013           0 : Node* WasmGraphBuilder::BuildChangeEndiannessStore(Node* node,
    1014             :                                                    MachineType memtype,
    1015           0 :                                                    wasm::ValueType wasmtype) {
    1016             :   Node* result;
    1017             :   Node* value = node;
    1018           0 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1019           0 :   int valueSizeInBytes = 1 << ElementSizeLog2Of(wasmtype);
    1020           0 :   int valueSizeInBits = 8 * valueSizeInBytes;
    1021             :   bool isFloat = false;
    1022             : 
    1023           0 :   switch (wasmtype) {
    1024             :     case wasm::kWasmF64:
    1025           0 :       value = graph()->NewNode(m->BitcastFloat64ToInt64(), node);
    1026             :       isFloat = true;
    1027             :     case wasm::kWasmI64:
    1028           0 :       result = jsgraph()->Int64Constant(0);
    1029           0 :       break;
    1030             :     case wasm::kWasmF32:
    1031           0 :       value = graph()->NewNode(m->BitcastFloat32ToInt32(), node);
    1032             :       isFloat = true;
    1033             :     case wasm::kWasmI32:
    1034           0 :       result = jsgraph()->Int32Constant(0);
    1035           0 :       break;
    1036             :     case wasm::kWasmS128:
    1037             :       DCHECK(ReverseBytesSupported(m, valueSizeInBytes));
    1038             :       break;
    1039             :     default:
    1040           0 :       UNREACHABLE();
    1041             :       break;
    1042             :   }
    1043             : 
    1044           0 :   if (memtype.representation() == MachineRepresentation::kWord8) {
    1045             :     // No need to change endianness for byte size, return original node
    1046             :     return node;
    1047             :   }
    1048           0 :   if (wasmtype == wasm::kWasmI64 &&
    1049             :       memtype.representation() < MachineRepresentation::kWord64) {
    1050             :     // In case we store lower part of WasmI64 expression, we can truncate
    1051             :     // upper 32bits
    1052           0 :     value = graph()->NewNode(m->TruncateInt64ToInt32(), value);
    1053           0 :     valueSizeInBytes = 1 << ElementSizeLog2Of(wasm::kWasmI32);
    1054           0 :     valueSizeInBits = 8 * valueSizeInBytes;
    1055           0 :     if (memtype.representation() == MachineRepresentation::kWord16) {
    1056             :       value =
    1057           0 :           graph()->NewNode(m->Word32Shl(), value, jsgraph()->Int32Constant(16));
    1058             :     }
    1059           0 :   } else if (wasmtype == wasm::kWasmI32 &&
    1060             :              memtype.representation() == MachineRepresentation::kWord16) {
    1061             :     value =
    1062           0 :         graph()->NewNode(m->Word32Shl(), value, jsgraph()->Int32Constant(16));
    1063             :   }
    1064             : 
    1065             :   int i;
    1066             :   uint32_t shiftCount;
    1067             : 
    1068           0 :   if (ReverseBytesSupported(m, valueSizeInBytes)) {
    1069           0 :     switch (valueSizeInBytes) {
    1070             :       case 4:
    1071           0 :         result = graph()->NewNode(m->Word32ReverseBytes().op(), value);
    1072           0 :         break;
    1073             :       case 8:
    1074           0 :         result = graph()->NewNode(m->Word64ReverseBytes().op(), value);
    1075           0 :         break;
    1076             :       case 16: {
    1077             :         Node* byte_reversed_lanes[4];
    1078           0 :         for (int lane = 0; lane < 4; lane++) {
    1079             :           byte_reversed_lanes[lane] = graph()->NewNode(
    1080             :               m->Word32ReverseBytes().op(),
    1081             :               graph()->NewNode(jsgraph()->machine()->I32x4ExtractLane(lane),
    1082           0 :                                value));
    1083             :         }
    1084             : 
    1085             :         // This is making a copy of the value.
    1086             :         result =
    1087           0 :             graph()->NewNode(jsgraph()->machine()->S128And(), value, value);
    1088             : 
    1089           0 :         for (int lane = 0; lane < 4; lane++) {
    1090             :           result =
    1091             :               graph()->NewNode(jsgraph()->machine()->I32x4ReplaceLane(3 - lane),
    1092           0 :                                result, byte_reversed_lanes[lane]);
    1093             :         }
    1094             : 
    1095             :         break;
    1096             :       }
    1097             :       default:
    1098           0 :         UNREACHABLE();
    1099             :         break;
    1100             :     }
    1101             :   } else {
    1102           0 :     for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2;
    1103             :          i += 8, shiftCount -= 16) {
    1104             :       Node* shiftLower;
    1105             :       Node* shiftHigher;
    1106             :       Node* lowerByte;
    1107             :       Node* higherByte;
    1108             : 
    1109             :       DCHECK_LT(0, shiftCount);
    1110             :       DCHECK_EQ(0, (shiftCount + 8) % 16);
    1111             : 
    1112           0 :       if (valueSizeInBits > 32) {
    1113             :         shiftLower = graph()->NewNode(m->Word64Shl(), value,
    1114           0 :                                       jsgraph()->Int64Constant(shiftCount));
    1115             :         shiftHigher = graph()->NewNode(m->Word64Shr(), value,
    1116           0 :                                        jsgraph()->Int64Constant(shiftCount));
    1117             :         lowerByte = graph()->NewNode(
    1118             :             m->Word64And(), shiftLower,
    1119             :             jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF)
    1120           0 :                                      << (valueSizeInBits - 8 - i)));
    1121             :         higherByte = graph()->NewNode(
    1122             :             m->Word64And(), shiftHigher,
    1123           0 :             jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i));
    1124           0 :         result = graph()->NewNode(m->Word64Or(), result, lowerByte);
    1125           0 :         result = graph()->NewNode(m->Word64Or(), result, higherByte);
    1126             :       } else {
    1127             :         shiftLower = graph()->NewNode(m->Word32Shl(), value,
    1128           0 :                                       jsgraph()->Int32Constant(shiftCount));
    1129             :         shiftHigher = graph()->NewNode(m->Word32Shr(), value,
    1130           0 :                                        jsgraph()->Int32Constant(shiftCount));
    1131             :         lowerByte = graph()->NewNode(
    1132             :             m->Word32And(), shiftLower,
    1133             :             jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF)
    1134           0 :                                      << (valueSizeInBits - 8 - i)));
    1135             :         higherByte = graph()->NewNode(
    1136             :             m->Word32And(), shiftHigher,
    1137           0 :             jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i));
    1138           0 :         result = graph()->NewNode(m->Word32Or(), result, lowerByte);
    1139           0 :         result = graph()->NewNode(m->Word32Or(), result, higherByte);
    1140             :       }
    1141             :     }
    1142             :   }
    1143             : 
    1144           0 :   if (isFloat) {
    1145           0 :     switch (wasmtype) {
    1146             :       case wasm::kWasmF64:
    1147           0 :         result = graph()->NewNode(m->BitcastInt64ToFloat64(), result);
    1148           0 :         break;
    1149             :       case wasm::kWasmF32:
    1150           0 :         result = graph()->NewNode(m->BitcastInt32ToFloat32(), result);
    1151           0 :         break;
    1152             :       default:
    1153           0 :         UNREACHABLE();
    1154             :         break;
    1155             :     }
    1156             :   }
    1157             : 
    1158           0 :   return result;
    1159             : }
    1160             : 
    1161           0 : Node* WasmGraphBuilder::BuildChangeEndiannessLoad(Node* node,
    1162             :                                                   MachineType memtype,
    1163           0 :                                                   wasm::ValueType wasmtype) {
    1164             :   Node* result;
    1165             :   Node* value = node;
    1166           0 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1167           0 :   int valueSizeInBytes = 1 << ElementSizeLog2Of(memtype.representation());
    1168           0 :   int valueSizeInBits = 8 * valueSizeInBytes;
    1169             :   bool isFloat = false;
    1170             : 
    1171           0 :   switch (memtype.representation()) {
    1172             :     case MachineRepresentation::kFloat64:
    1173           0 :       value = graph()->NewNode(m->BitcastFloat64ToInt64(), node);
    1174             :       isFloat = true;
    1175             :     case MachineRepresentation::kWord64:
    1176           0 :       result = jsgraph()->Int64Constant(0);
    1177           0 :       break;
    1178             :     case MachineRepresentation::kFloat32:
    1179           0 :       value = graph()->NewNode(m->BitcastFloat32ToInt32(), node);
    1180             :       isFloat = true;
    1181             :     case MachineRepresentation::kWord32:
    1182             :     case MachineRepresentation::kWord16:
    1183           0 :       result = jsgraph()->Int32Constant(0);
    1184           0 :       break;
    1185             :     case MachineRepresentation::kWord8:
    1186             :       // No need to change endianness for byte size, return original node
    1187             :       return node;
    1188             :       break;
    1189             :     case MachineRepresentation::kSimd128:
    1190             :       DCHECK(ReverseBytesSupported(m, valueSizeInBytes));
    1191             :       break;
    1192             :     default:
    1193           0 :       UNREACHABLE();
    1194             :       break;
    1195             :   }
    1196             : 
    1197             :   int i;
    1198             :   uint32_t shiftCount;
    1199             : 
    1200           0 :   if (ReverseBytesSupported(m, valueSizeInBytes < 4 ? 4 : valueSizeInBytes)) {
    1201           0 :     switch (valueSizeInBytes) {
    1202             :       case 2:
    1203             :         result =
    1204             :             graph()->NewNode(m->Word32ReverseBytes().op(),
    1205             :                              graph()->NewNode(m->Word32Shl(), value,
    1206           0 :                                               jsgraph()->Int32Constant(16)));
    1207           0 :         break;
    1208             :       case 4:
    1209           0 :         result = graph()->NewNode(m->Word32ReverseBytes().op(), value);
    1210           0 :         break;
    1211             :       case 8:
    1212           0 :         result = graph()->NewNode(m->Word64ReverseBytes().op(), value);
    1213           0 :         break;
    1214             :       case 16: {
    1215             :         Node* byte_reversed_lanes[4];
    1216           0 :         for (int lane = 0; lane < 4; lane++) {
    1217             :           byte_reversed_lanes[lane] = graph()->NewNode(
    1218             :               m->Word32ReverseBytes().op(),
    1219             :               graph()->NewNode(jsgraph()->machine()->I32x4ExtractLane(lane),
    1220           0 :                                value));
    1221             :         }
    1222             : 
    1223             :         // This is making a copy of the value.
    1224             :         result =
    1225           0 :             graph()->NewNode(jsgraph()->machine()->S128And(), value, value);
    1226             : 
    1227           0 :         for (int lane = 0; lane < 4; lane++) {
    1228             :           result =
    1229             :               graph()->NewNode(jsgraph()->machine()->I32x4ReplaceLane(3 - lane),
    1230           0 :                                result, byte_reversed_lanes[lane]);
    1231             :         }
    1232             : 
    1233             :         break;
    1234             :       }
    1235             :       default:
    1236           0 :         UNREACHABLE();
    1237             :     }
    1238             :   } else {
    1239           0 :     for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2;
    1240             :          i += 8, shiftCount -= 16) {
    1241             :       Node* shiftLower;
    1242             :       Node* shiftHigher;
    1243             :       Node* lowerByte;
    1244             :       Node* higherByte;
    1245             : 
    1246             :       DCHECK_LT(0, shiftCount);
    1247             :       DCHECK_EQ(0, (shiftCount + 8) % 16);
    1248             : 
    1249           0 :       if (valueSizeInBits > 32) {
    1250             :         shiftLower = graph()->NewNode(m->Word64Shl(), value,
    1251           0 :                                       jsgraph()->Int64Constant(shiftCount));
    1252             :         shiftHigher = graph()->NewNode(m->Word64Shr(), value,
    1253           0 :                                        jsgraph()->Int64Constant(shiftCount));
    1254             :         lowerByte = graph()->NewNode(
    1255             :             m->Word64And(), shiftLower,
    1256             :             jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF)
    1257           0 :                                      << (valueSizeInBits - 8 - i)));
    1258             :         higherByte = graph()->NewNode(
    1259             :             m->Word64And(), shiftHigher,
    1260           0 :             jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i));
    1261           0 :         result = graph()->NewNode(m->Word64Or(), result, lowerByte);
    1262           0 :         result = graph()->NewNode(m->Word64Or(), result, higherByte);
    1263             :       } else {
    1264             :         shiftLower = graph()->NewNode(m->Word32Shl(), value,
    1265           0 :                                       jsgraph()->Int32Constant(shiftCount));
    1266             :         shiftHigher = graph()->NewNode(m->Word32Shr(), value,
    1267           0 :                                        jsgraph()->Int32Constant(shiftCount));
    1268             :         lowerByte = graph()->NewNode(
    1269             :             m->Word32And(), shiftLower,
    1270             :             jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF)
    1271           0 :                                      << (valueSizeInBits - 8 - i)));
    1272             :         higherByte = graph()->NewNode(
    1273             :             m->Word32And(), shiftHigher,
    1274           0 :             jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i));
    1275           0 :         result = graph()->NewNode(m->Word32Or(), result, lowerByte);
    1276           0 :         result = graph()->NewNode(m->Word32Or(), result, higherByte);
    1277             :       }
    1278             :     }
    1279             :   }
    1280             : 
    1281           0 :   if (isFloat) {
    1282           0 :     switch (memtype.representation()) {
    1283             :       case MachineRepresentation::kFloat64:
    1284           0 :         result = graph()->NewNode(m->BitcastInt64ToFloat64(), result);
    1285           0 :         break;
    1286             :       case MachineRepresentation::kFloat32:
    1287           0 :         result = graph()->NewNode(m->BitcastInt32ToFloat32(), result);
    1288           0 :         break;
    1289             :       default:
    1290           0 :         UNREACHABLE();
    1291             :         break;
    1292             :     }
    1293             :   }
    1294             : 
    1295             :   // We need to sign extend the value
    1296           0 :   if (memtype.IsSigned()) {
    1297             :     DCHECK(!isFloat);
    1298           0 :     if (valueSizeInBits < 32) {
    1299             :       Node* shiftBitCount;
    1300             :       // Perform sign extension using following trick
    1301             :       // result = (x << machine_width - type_width) >> (machine_width -
    1302             :       // type_width)
    1303           0 :       if (wasmtype == wasm::kWasmI64) {
    1304           0 :         shiftBitCount = jsgraph()->Int32Constant(64 - valueSizeInBits);
    1305             :         result = graph()->NewNode(
    1306             :             m->Word64Sar(),
    1307             :             graph()->NewNode(m->Word64Shl(),
    1308             :                              graph()->NewNode(m->ChangeInt32ToInt64(), result),
    1309             :                              shiftBitCount),
    1310           0 :             shiftBitCount);
    1311           0 :       } else if (wasmtype == wasm::kWasmI32) {
    1312           0 :         shiftBitCount = jsgraph()->Int32Constant(32 - valueSizeInBits);
    1313             :         result = graph()->NewNode(
    1314             :             m->Word32Sar(),
    1315             :             graph()->NewNode(m->Word32Shl(), result, shiftBitCount),
    1316           0 :             shiftBitCount);
    1317             :       }
    1318             :     }
    1319             :   }
    1320             : 
    1321           0 :   return result;
    1322             : }
    1323             : 
    1324         108 : Node* WasmGraphBuilder::BuildF32CopySign(Node* left, Node* right) {
    1325             :   Node* result = Unop(
    1326             :       wasm::kExprF32ReinterpretI32,
    1327             :       Binop(wasm::kExprI32Ior,
    1328             :             Binop(wasm::kExprI32And, Unop(wasm::kExprI32ReinterpretF32, left),
    1329             :                   jsgraph()->Int32Constant(0x7fffffff)),
    1330             :             Binop(wasm::kExprI32And, Unop(wasm::kExprI32ReinterpretF32, right),
    1331         108 :                   jsgraph()->Int32Constant(0x80000000))));
    1332             : 
    1333          54 :   return result;
    1334             : }
    1335             : 
    1336         108 : Node* WasmGraphBuilder::BuildF64CopySign(Node* left, Node* right) {
    1337             : #if WASM_64
    1338             :   Node* result = Unop(
    1339             :       wasm::kExprF64ReinterpretI64,
    1340             :       Binop(wasm::kExprI64Ior,
    1341             :             Binop(wasm::kExprI64And, Unop(wasm::kExprI64ReinterpretF64, left),
    1342             :                   jsgraph()->Int64Constant(0x7fffffffffffffff)),
    1343             :             Binop(wasm::kExprI64And, Unop(wasm::kExprI64ReinterpretF64, right),
    1344         108 :                   jsgraph()->Int64Constant(0x8000000000000000))));
    1345             : 
    1346          54 :   return result;
    1347             : #else
    1348             :   MachineOperatorBuilder* m = jsgraph()->machine();
    1349             : 
    1350             :   Node* high_word_left = graph()->NewNode(m->Float64ExtractHighWord32(), left);
    1351             :   Node* high_word_right =
    1352             :       graph()->NewNode(m->Float64ExtractHighWord32(), right);
    1353             : 
    1354             :   Node* new_high_word =
    1355             :       Binop(wasm::kExprI32Ior, Binop(wasm::kExprI32And, high_word_left,
    1356             :                                      jsgraph()->Int32Constant(0x7fffffff)),
    1357             :             Binop(wasm::kExprI32And, high_word_right,
    1358             :                   jsgraph()->Int32Constant(0x80000000)));
    1359             : 
    1360             :   return graph()->NewNode(m->Float64InsertHighWord32(), left, new_high_word);
    1361             : #endif
    1362             : }
    1363             : 
    1364         272 : Node* WasmGraphBuilder::BuildI32SConvertF32(Node* input,
    1365         272 :                                             wasm::WasmCodePosition position) {
    1366         272 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1367             :   // Truncation of the input value is needed for the overflow check later.
    1368         272 :   Node* trunc = Unop(wasm::kExprF32Trunc, input);
    1369         272 :   Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc);
    1370             : 
    1371             :   // Convert the result back to f64. If we end up at a different value than the
    1372             :   // truncated input value, then there has been an overflow and we trap.
    1373         272 :   Node* check = Unop(wasm::kExprF32SConvertI32, result);
    1374         272 :   Node* overflow = Binop(wasm::kExprF32Ne, trunc, check);
    1375         272 :   TrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position);
    1376             : 
    1377         272 :   return result;
    1378             : }
    1379             : 
    1380         262 : Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input,
    1381         262 :                                             wasm::WasmCodePosition position) {
    1382         262 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1383             :   // Truncation of the input value is needed for the overflow check later.
    1384         262 :   Node* trunc = Unop(wasm::kExprF64Trunc, input);
    1385         262 :   Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), trunc);
    1386             : 
    1387             :   // Convert the result back to f64. If we end up at a different value than the
    1388             :   // truncated input value, then there has been an overflow and we trap.
    1389         262 :   Node* check = Unop(wasm::kExprF64SConvertI32, result);
    1390         262 :   Node* overflow = Binop(wasm::kExprF64Ne, trunc, check);
    1391         262 :   TrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position);
    1392             : 
    1393         262 :   return result;
    1394             : }
    1395             : 
    1396          68 : Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input,
    1397          68 :                                             wasm::WasmCodePosition position) {
    1398          68 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1399             :   // Truncation of the input value is needed for the overflow check later.
    1400          68 :   Node* trunc = Unop(wasm::kExprF32Trunc, input);
    1401          68 :   Node* result = graph()->NewNode(m->TruncateFloat32ToUint32(), trunc);
    1402             : 
    1403             :   // Convert the result back to f32. If we end up at a different value than the
    1404             :   // truncated input value, then there has been an overflow and we trap.
    1405          68 :   Node* check = Unop(wasm::kExprF32UConvertI32, result);
    1406          68 :   Node* overflow = Binop(wasm::kExprF32Ne, trunc, check);
    1407          68 :   TrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position);
    1408             : 
    1409          68 :   return result;
    1410             : }
    1411             : 
    1412          58 : Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input,
    1413          58 :                                             wasm::WasmCodePosition position) {
    1414          58 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1415             :   // Truncation of the input value is needed for the overflow check later.
    1416          58 :   Node* trunc = Unop(wasm::kExprF64Trunc, input);
    1417          58 :   Node* result = graph()->NewNode(m->TruncateFloat64ToUint32(), trunc);
    1418             : 
    1419             :   // Convert the result back to f64. If we end up at a different value than the
    1420             :   // truncated input value, then there has been an overflow and we trap.
    1421          58 :   Node* check = Unop(wasm::kExprF64UConvertI32, result);
    1422          58 :   Node* overflow = Binop(wasm::kExprF64Ne, trunc, check);
    1423          58 :   TrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position);
    1424             : 
    1425          58 :   return result;
    1426             : }
    1427             : 
    1428          12 : Node* WasmGraphBuilder::BuildI32AsmjsSConvertF32(Node* input) {
    1429          12 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1430             :   // asm.js must use the wacky JS semantics.
    1431          12 :   input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
    1432          24 :   return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
    1433             : }
    1434             : 
    1435         130 : Node* WasmGraphBuilder::BuildI32AsmjsSConvertF64(Node* input) {
    1436         130 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1437             :   // asm.js must use the wacky JS semantics.
    1438         260 :   return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
    1439             : }
    1440             : 
    1441          12 : Node* WasmGraphBuilder::BuildI32AsmjsUConvertF32(Node* input) {
    1442          12 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1443             :   // asm.js must use the wacky JS semantics.
    1444          12 :   input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
    1445          24 :   return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
    1446             : }
    1447             : 
    1448          12 : Node* WasmGraphBuilder::BuildI32AsmjsUConvertF64(Node* input) {
    1449          12 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1450             :   // asm.js must use the wacky JS semantics.
    1451          24 :   return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
    1452             : }
    1453             : 
    1454           0 : Node* WasmGraphBuilder::BuildBitCountingCall(Node* input, ExternalReference ref,
    1455           0 :                                              MachineRepresentation input_type) {
    1456             :   Node* stack_slot_param =
    1457           0 :       graph()->NewNode(jsgraph()->machine()->StackSlot(input_type));
    1458             : 
    1459             :   const Operator* store_op = jsgraph()->machine()->Store(
    1460           0 :       StoreRepresentation(input_type, kNoWriteBarrier));
    1461             :   *effect_ =
    1462             :       graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0),
    1463           0 :                        input, *effect_, *control_);
    1464             : 
    1465             :   MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 1);
    1466             :   sig_builder.AddReturn(MachineType::Int32());
    1467             :   sig_builder.AddParam(MachineType::Pointer());
    1468             : 
    1469           0 :   Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
    1470             : 
    1471           0 :   return BuildCCall(sig_builder.Build(), function, stack_slot_param);
    1472             : }
    1473             : 
    1474           0 : Node* WasmGraphBuilder::BuildI32Ctz(Node* input) {
    1475             :   return BuildBitCountingCall(
    1476             :       input, ExternalReference::wasm_word32_ctz(jsgraph()->isolate()),
    1477           0 :       MachineRepresentation::kWord32);
    1478             : }
    1479             : 
    1480           0 : Node* WasmGraphBuilder::BuildI64Ctz(Node* input) {
    1481             :   return Unop(wasm::kExprI64UConvertI32,
    1482             :               BuildBitCountingCall(input, ExternalReference::wasm_word64_ctz(
    1483             :                                               jsgraph()->isolate()),
    1484           0 :                                    MachineRepresentation::kWord64));
    1485             : }
    1486             : 
    1487           0 : Node* WasmGraphBuilder::BuildI32Popcnt(Node* input) {
    1488             :   return BuildBitCountingCall(
    1489             :       input, ExternalReference::wasm_word32_popcnt(jsgraph()->isolate()),
    1490           0 :       MachineRepresentation::kWord32);
    1491             : }
    1492             : 
    1493           0 : Node* WasmGraphBuilder::BuildI64Popcnt(Node* input) {
    1494             :   return Unop(wasm::kExprI64UConvertI32,
    1495             :               BuildBitCountingCall(input, ExternalReference::wasm_word64_popcnt(
    1496             :                                               jsgraph()->isolate()),
    1497           0 :                                    MachineRepresentation::kWord64));
    1498             : }
    1499             : 
    1500           0 : Node* WasmGraphBuilder::BuildF32Trunc(Node* input) {
    1501           0 :   MachineType type = MachineType::Float32();
    1502             :   ExternalReference ref =
    1503           0 :       ExternalReference::wasm_f32_trunc(jsgraph()->isolate());
    1504             : 
    1505           0 :   return BuildCFuncInstruction(ref, type, input);
    1506             : }
    1507             : 
    1508           0 : Node* WasmGraphBuilder::BuildF32Floor(Node* input) {
    1509           0 :   MachineType type = MachineType::Float32();
    1510             :   ExternalReference ref =
    1511           0 :       ExternalReference::wasm_f32_floor(jsgraph()->isolate());
    1512           0 :   return BuildCFuncInstruction(ref, type, input);
    1513             : }
    1514             : 
    1515           0 : Node* WasmGraphBuilder::BuildF32Ceil(Node* input) {
    1516           0 :   MachineType type = MachineType::Float32();
    1517             :   ExternalReference ref =
    1518           0 :       ExternalReference::wasm_f32_ceil(jsgraph()->isolate());
    1519           0 :   return BuildCFuncInstruction(ref, type, input);
    1520             : }
    1521             : 
    1522           0 : Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) {
    1523           0 :   MachineType type = MachineType::Float32();
    1524             :   ExternalReference ref =
    1525           0 :       ExternalReference::wasm_f32_nearest_int(jsgraph()->isolate());
    1526           0 :   return BuildCFuncInstruction(ref, type, input);
    1527             : }
    1528             : 
    1529           0 : Node* WasmGraphBuilder::BuildF64Trunc(Node* input) {
    1530           0 :   MachineType type = MachineType::Float64();
    1531             :   ExternalReference ref =
    1532           0 :       ExternalReference::wasm_f64_trunc(jsgraph()->isolate());
    1533           0 :   return BuildCFuncInstruction(ref, type, input);
    1534             : }
    1535             : 
    1536           0 : Node* WasmGraphBuilder::BuildF64Floor(Node* input) {
    1537           0 :   MachineType type = MachineType::Float64();
    1538             :   ExternalReference ref =
    1539           0 :       ExternalReference::wasm_f64_floor(jsgraph()->isolate());
    1540           0 :   return BuildCFuncInstruction(ref, type, input);
    1541             : }
    1542             : 
    1543           0 : Node* WasmGraphBuilder::BuildF64Ceil(Node* input) {
    1544           0 :   MachineType type = MachineType::Float64();
    1545             :   ExternalReference ref =
    1546           0 :       ExternalReference::wasm_f64_ceil(jsgraph()->isolate());
    1547           0 :   return BuildCFuncInstruction(ref, type, input);
    1548             : }
    1549             : 
    1550           0 : Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) {
    1551           0 :   MachineType type = MachineType::Float64();
    1552             :   ExternalReference ref =
    1553           0 :       ExternalReference::wasm_f64_nearest_int(jsgraph()->isolate());
    1554           0 :   return BuildCFuncInstruction(ref, type, input);
    1555             : }
    1556             : 
    1557          38 : Node* WasmGraphBuilder::BuildF64Acos(Node* input) {
    1558          19 :   MachineType type = MachineType::Float64();
    1559             :   ExternalReference ref =
    1560          19 :       ExternalReference::f64_acos_wrapper_function(jsgraph()->isolate());
    1561          19 :   return BuildCFuncInstruction(ref, type, input);
    1562             : }
    1563             : 
    1564          38 : Node* WasmGraphBuilder::BuildF64Asin(Node* input) {
    1565          19 :   MachineType type = MachineType::Float64();
    1566             :   ExternalReference ref =
    1567          19 :       ExternalReference::f64_asin_wrapper_function(jsgraph()->isolate());
    1568          19 :   return BuildCFuncInstruction(ref, type, input);
    1569             : }
    1570             : 
    1571          26 : Node* WasmGraphBuilder::BuildF64Pow(Node* left, Node* right) {
    1572          13 :   MachineType type = MachineType::Float64();
    1573             :   ExternalReference ref =
    1574          13 :       ExternalReference::wasm_float64_pow(jsgraph()->isolate());
    1575          13 :   return BuildCFuncInstruction(ref, type, left, right);
    1576             : }
    1577             : 
    1578          60 : Node* WasmGraphBuilder::BuildF64Mod(Node* left, Node* right) {
    1579          30 :   MachineType type = MachineType::Float64();
    1580             :   ExternalReference ref =
    1581          30 :       ExternalReference::f64_mod_wrapper_function(jsgraph()->isolate());
    1582          30 :   return BuildCFuncInstruction(ref, type, left, right);
    1583             : }
    1584             : 
    1585          81 : Node* WasmGraphBuilder::BuildCFuncInstruction(ExternalReference ref,
    1586             :                                               MachineType type, Node* input0,
    1587         696 :                                               Node* input1) {
    1588             :   // We do truncation by calling a C function which calculates the result.
    1589             :   // The input is passed to the C function as a double*'s to avoid double
    1590             :   // parameters. For this we reserve slots on the stack, store the parameters
    1591             :   // in those slots, pass pointers to the slot to the C function,
    1592             :   // and after calling the C function we collect the return value from
    1593             :   // the stack slot.
    1594             : 
    1595             :   Node* stack_slot_param0 =
    1596          81 :       graph()->NewNode(jsgraph()->machine()->StackSlot(type.representation()));
    1597             : 
    1598             :   const Operator* store_op0 = jsgraph()->machine()->Store(
    1599          81 :       StoreRepresentation(type.representation(), kNoWriteBarrier));
    1600             :   *effect_ = graph()->NewNode(store_op0, stack_slot_param0,
    1601             :                               jsgraph()->Int32Constant(0), input0, *effect_,
    1602         243 :                               *control_);
    1603             : 
    1604          81 :   Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
    1605             : 
    1606          81 :   if (input1 == nullptr) {
    1607             :     const int input_count = 1;
    1608             :     Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0,
    1609             :                                                 input_count);
    1610             :     sig_builder.AddParam(MachineType::Pointer());
    1611          38 :     BuildCCall(sig_builder.Build(), function, stack_slot_param0);
    1612             :   } else {
    1613             :     Node* stack_slot_param1 = graph()->NewNode(
    1614          43 :         jsgraph()->machine()->StackSlot(type.representation()));
    1615             :     const Operator* store_op1 = jsgraph()->machine()->Store(
    1616          43 :         StoreRepresentation(type.representation(), kNoWriteBarrier));
    1617             :     *effect_ = graph()->NewNode(store_op1, stack_slot_param1,
    1618             :                                 jsgraph()->Int32Constant(0), input1, *effect_,
    1619         129 :                                 *control_);
    1620             : 
    1621             :     const int input_count = 2;
    1622             :     Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0,
    1623             :                                                 input_count);
    1624             :     sig_builder.AddParam(MachineType::Pointer());
    1625             :     sig_builder.AddParam(MachineType::Pointer());
    1626             :     BuildCCall(sig_builder.Build(), function, stack_slot_param0,
    1627          43 :                stack_slot_param1);
    1628             :   }
    1629             : 
    1630          81 :   const Operator* load_op = jsgraph()->machine()->Load(type);
    1631             : 
    1632             :   Node* load =
    1633             :       graph()->NewNode(load_op, stack_slot_param0, jsgraph()->Int32Constant(0),
    1634         162 :                        *effect_, *control_);
    1635          81 :   *effect_ = load;
    1636          81 :   return load;
    1637             : }
    1638             : 
    1639           0 : Node* WasmGraphBuilder::BuildF32SConvertI64(Node* input) {
    1640             :   // TODO(titzer/bradnelson): Check handlng of asm.js case.
    1641             :   return BuildIntToFloatConversionInstruction(
    1642             :       input, ExternalReference::wasm_int64_to_float32(jsgraph()->isolate()),
    1643           0 :       MachineRepresentation::kWord64, MachineType::Float32());
    1644             : }
    1645           0 : Node* WasmGraphBuilder::BuildF32UConvertI64(Node* input) {
    1646             :   // TODO(titzer/bradnelson): Check handlng of asm.js case.
    1647             :   return BuildIntToFloatConversionInstruction(
    1648             :       input, ExternalReference::wasm_uint64_to_float32(jsgraph()->isolate()),
    1649           0 :       MachineRepresentation::kWord64, MachineType::Float32());
    1650             : }
    1651           0 : Node* WasmGraphBuilder::BuildF64SConvertI64(Node* input) {
    1652             :   return BuildIntToFloatConversionInstruction(
    1653             :       input, ExternalReference::wasm_int64_to_float64(jsgraph()->isolate()),
    1654           0 :       MachineRepresentation::kWord64, MachineType::Float64());
    1655             : }
    1656           0 : Node* WasmGraphBuilder::BuildF64UConvertI64(Node* input) {
    1657             :   return BuildIntToFloatConversionInstruction(
    1658             :       input, ExternalReference::wasm_uint64_to_float64(jsgraph()->isolate()),
    1659           0 :       MachineRepresentation::kWord64, MachineType::Float64());
    1660             : }
    1661             : 
    1662           0 : Node* WasmGraphBuilder::BuildIntToFloatConversionInstruction(
    1663             :     Node* input, ExternalReference ref,
    1664             :     MachineRepresentation parameter_representation,
    1665           0 :     const MachineType result_type) {
    1666             :   Node* stack_slot_param = graph()->NewNode(
    1667           0 :       jsgraph()->machine()->StackSlot(parameter_representation));
    1668             :   Node* stack_slot_result = graph()->NewNode(
    1669           0 :       jsgraph()->machine()->StackSlot(result_type.representation()));
    1670             :   const Operator* store_op = jsgraph()->machine()->Store(
    1671           0 :       StoreRepresentation(parameter_representation, kNoWriteBarrier));
    1672             :   *effect_ =
    1673             :       graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0),
    1674           0 :                        input, *effect_, *control_);
    1675             :   MachineSignature::Builder sig_builder(jsgraph()->zone(), 0, 2);
    1676             :   sig_builder.AddParam(MachineType::Pointer());
    1677             :   sig_builder.AddParam(MachineType::Pointer());
    1678           0 :   Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
    1679             :   BuildCCall(sig_builder.Build(), function, stack_slot_param,
    1680           0 :              stack_slot_result);
    1681           0 :   const Operator* load_op = jsgraph()->machine()->Load(result_type);
    1682             :   Node* load =
    1683             :       graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0),
    1684           0 :                        *effect_, *control_);
    1685           0 :   *effect_ = load;
    1686           0 :   return load;
    1687             : }
    1688             : 
    1689          70 : Node* WasmGraphBuilder::BuildI64SConvertF32(Node* input,
    1690          70 :                                             wasm::WasmCodePosition position) {
    1691         140 :   if (jsgraph()->machine()->Is32()) {
    1692             :     return BuildFloatToIntConversionInstruction(
    1693             :         input, ExternalReference::wasm_float32_to_int64(jsgraph()->isolate()),
    1694           0 :         MachineRepresentation::kFloat32, MachineType::Int64(), position);
    1695             :   } else {
    1696             :     Node* trunc = graph()->NewNode(
    1697          70 :         jsgraph()->machine()->TryTruncateFloat32ToInt64(), input);
    1698             :     Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
    1699          70 :                                     graph()->start());
    1700             :     Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
    1701          70 :                                       graph()->start());
    1702             :     ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
    1703          70 :     return result;
    1704             :   }
    1705             : }
    1706             : 
    1707          70 : Node* WasmGraphBuilder::BuildI64UConvertF32(Node* input,
    1708          70 :                                             wasm::WasmCodePosition position) {
    1709         140 :   if (jsgraph()->machine()->Is32()) {
    1710             :     return BuildFloatToIntConversionInstruction(
    1711             :         input, ExternalReference::wasm_float32_to_uint64(jsgraph()->isolate()),
    1712           0 :         MachineRepresentation::kFloat32, MachineType::Int64(), position);
    1713             :   } else {
    1714             :     Node* trunc = graph()->NewNode(
    1715          70 :         jsgraph()->machine()->TryTruncateFloat32ToUint64(), input);
    1716             :     Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
    1717          70 :                                     graph()->start());
    1718             :     Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
    1719          70 :                                       graph()->start());
    1720             :     ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
    1721          70 :     return result;
    1722             :   }
    1723             : }
    1724             : 
    1725         122 : Node* WasmGraphBuilder::BuildI64SConvertF64(Node* input,
    1726         122 :                                             wasm::WasmCodePosition position) {
    1727         244 :   if (jsgraph()->machine()->Is32()) {
    1728             :     return BuildFloatToIntConversionInstruction(
    1729             :         input, ExternalReference::wasm_float64_to_int64(jsgraph()->isolate()),
    1730           0 :         MachineRepresentation::kFloat64, MachineType::Int64(), position);
    1731             :   } else {
    1732             :     Node* trunc = graph()->NewNode(
    1733         122 :         jsgraph()->machine()->TryTruncateFloat64ToInt64(), input);
    1734             :     Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
    1735         122 :                                     graph()->start());
    1736             :     Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
    1737         122 :                                       graph()->start());
    1738             :     ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
    1739         122 :     return result;
    1740             :   }
    1741             : }
    1742             : 
    1743          80 : Node* WasmGraphBuilder::BuildI64UConvertF64(Node* input,
    1744          80 :                                             wasm::WasmCodePosition position) {
    1745         160 :   if (jsgraph()->machine()->Is32()) {
    1746             :     return BuildFloatToIntConversionInstruction(
    1747             :         input, ExternalReference::wasm_float64_to_uint64(jsgraph()->isolate()),
    1748           0 :         MachineRepresentation::kFloat64, MachineType::Int64(), position);
    1749             :   } else {
    1750             :     Node* trunc = graph()->NewNode(
    1751          80 :         jsgraph()->machine()->TryTruncateFloat64ToUint64(), input);
    1752             :     Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
    1753          80 :                                     graph()->start());
    1754             :     Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
    1755          80 :                                       graph()->start());
    1756             :     ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
    1757          80 :     return result;
    1758             :   }
    1759             : }
    1760             : 
    1761           0 : Node* WasmGraphBuilder::BuildFloatToIntConversionInstruction(
    1762             :     Node* input, ExternalReference ref,
    1763             :     MachineRepresentation parameter_representation,
    1764           0 :     const MachineType result_type, wasm::WasmCodePosition position) {
    1765             :   Node* stack_slot_param = graph()->NewNode(
    1766           0 :       jsgraph()->machine()->StackSlot(parameter_representation));
    1767             :   Node* stack_slot_result = graph()->NewNode(
    1768           0 :       jsgraph()->machine()->StackSlot(result_type.representation()));
    1769             :   const Operator* store_op = jsgraph()->machine()->Store(
    1770           0 :       StoreRepresentation(parameter_representation, kNoWriteBarrier));
    1771             :   *effect_ =
    1772             :       graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0),
    1773           0 :                        input, *effect_, *control_);
    1774             :   MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2);
    1775             :   sig_builder.AddReturn(MachineType::Int32());
    1776             :   sig_builder.AddParam(MachineType::Pointer());
    1777             :   sig_builder.AddParam(MachineType::Pointer());
    1778           0 :   Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
    1779             :   ZeroCheck32(wasm::kTrapFloatUnrepresentable,
    1780             :               BuildCCall(sig_builder.Build(), function, stack_slot_param,
    1781             :                          stack_slot_result),
    1782           0 :               position);
    1783           0 :   const Operator* load_op = jsgraph()->machine()->Load(result_type);
    1784             :   Node* load =
    1785             :       graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0),
    1786           0 :                        *effect_, *control_);
    1787           0 :   *effect_ = load;
    1788           0 :   return load;
    1789             : }
    1790             : 
    1791        6636 : Node* WasmGraphBuilder::GrowMemory(Node* input) {
    1792             :   SetNeedsStackCheck();
    1793             :   Diamond check_input_range(
    1794             :       graph(), jsgraph()->common(),
    1795             :       graph()->NewNode(jsgraph()->machine()->Uint32LessThanOrEqual(), input,
    1796             :                        jsgraph()->Uint32Constant(FLAG_wasm_max_mem_pages)),
    1797        4424 :       BranchHint::kTrue);
    1798             : 
    1799        1106 :   check_input_range.Chain(*control_);
    1800             : 
    1801        1106 :   Node* parameters[] = {BuildChangeUint32ToSmi(input)};
    1802        1106 :   Node* old_effect = *effect_;
    1803        1106 :   *control_ = check_input_range.if_true;
    1804             :   Node* call = BuildCallToRuntime(Runtime::kWasmGrowMemory, parameters,
    1805        1106 :                                   arraysize(parameters));
    1806             : 
    1807        1106 :   Node* result = BuildChangeSmiToInt32(call);
    1808             : 
    1809             :   result = check_input_range.Phi(MachineRepresentation::kWord32, result,
    1810        1106 :                                  jsgraph()->Int32Constant(-1));
    1811             :   *effect_ = graph()->NewNode(jsgraph()->common()->EffectPhi(2), *effect_,
    1812        3318 :                               old_effect, check_input_range.merge);
    1813        1106 :   *control_ = check_input_range.merge;
    1814        1106 :   return result;
    1815             : }
    1816             : 
    1817         210 : uint32_t WasmGraphBuilder::GetExceptionEncodedSize(
    1818             :     const wasm::WasmException* exception) const {
    1819         700 :   const wasm::WasmExceptionSig* sig = exception->sig;
    1820             :   uint32_t encoded_size = 0;
    1821         700 :   for (size_t i = 0; i < sig->parameter_count(); ++i) {
    1822         140 :     size_t byte_size = size_t(1) << ElementSizeLog2Of(sig->GetParam(i));
    1823             :     DCHECK_EQ(byte_size % kBytesPerExceptionValuesArrayElement, 0);
    1824             :     DCHECK_LE(1, byte_size / kBytesPerExceptionValuesArrayElement);
    1825         140 :     encoded_size += byte_size / kBytesPerExceptionValuesArrayElement;
    1826             :   }
    1827         210 :   return encoded_size;
    1828             : }
    1829             : 
    1830         140 : Node* WasmGraphBuilder::Throw(uint32_t tag,
    1831             :                               const wasm::WasmException* exception,
    1832         140 :                               const Vector<Node*> values) {
    1833             :   SetNeedsStackCheck();
    1834         140 :   uint32_t encoded_size = GetExceptionEncodedSize(exception);
    1835             :   Node* create_parameters[] = {
    1836         140 :       BuildChangeUint32ToSmi(ConvertExceptionTagToRuntimeId(tag)),
    1837         280 :       BuildChangeUint32ToSmi(Uint32Constant(encoded_size))};
    1838             :   BuildCallToRuntime(Runtime::kWasmThrowCreate, create_parameters,
    1839         140 :                      arraysize(create_parameters));
    1840         140 :   uint32_t index = 0;
    1841         480 :   const wasm::WasmExceptionSig* sig = exception->sig;
    1842         140 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1843         480 :   for (size_t i = 0; i < sig->parameter_count(); ++i) {
    1844         200 :     Node* value = values[i];
    1845         100 :     switch (sig->GetParam(i)) {
    1846             :       case wasm::kWasmF32:
    1847          20 :         value = graph()->NewNode(m->BitcastFloat32ToInt32(), value);
    1848             :       // Intentionally fall to next case.
    1849             :       case wasm::kWasmI32:
    1850          60 :         BuildEncodeException32BitValue(&index, value);
    1851          60 :         break;
    1852             :       case wasm::kWasmF64:
    1853          20 :         value = graph()->NewNode(m->BitcastFloat64ToInt64(), value);
    1854             :       // Intentionally fall to next case.
    1855             :       case wasm::kWasmI64: {
    1856             :         Node* upper32 = graph()->NewNode(
    1857             :             m->TruncateInt64ToInt32(),
    1858          40 :             Binop(wasm::kExprI64ShrU, value, Int64Constant(32)));
    1859          40 :         BuildEncodeException32BitValue(&index, upper32);
    1860          40 :         Node* lower32 = graph()->NewNode(m->TruncateInt64ToInt32(), value);
    1861          40 :         BuildEncodeException32BitValue(&index, lower32);
    1862          40 :         break;
    1863             :       }
    1864             :       default:
    1865           0 :         CHECK(false);
    1866             :         break;
    1867             :     }
    1868             :   }
    1869             :   DCHECK_EQ(encoded_size, index);
    1870         140 :   return BuildCallToRuntime(Runtime::kWasmThrow, nullptr, 0);
    1871             : }
    1872             : 
    1873         140 : void WasmGraphBuilder::BuildEncodeException32BitValue(uint32_t* index,
    1874         140 :                                                       Node* value) {
    1875         140 :   MachineOperatorBuilder* machine = jsgraph()->machine();
    1876             :   Node* upper_parameters[] = {
    1877         280 :       BuildChangeUint32ToSmi(Int32Constant(*index)),
    1878             :       BuildChangeUint32ToSmi(
    1879         280 :           graph()->NewNode(machine->Word32Shr(), value, Int32Constant(16))),
    1880         280 :   };
    1881             :   BuildCallToRuntime(Runtime::kWasmExceptionSetElement, upper_parameters,
    1882         140 :                      arraysize(upper_parameters));
    1883         140 :   ++(*index);
    1884             :   Node* lower_parameters[] = {
    1885         280 :       BuildChangeUint32ToSmi(Int32Constant(*index)),
    1886             :       BuildChangeUint32ToSmi(graph()->NewNode(machine->Word32And(), value,
    1887         280 :                                               Int32Constant(0xFFFFu))),
    1888         280 :   };
    1889             :   BuildCallToRuntime(Runtime::kWasmExceptionSetElement, lower_parameters,
    1890         140 :                      arraysize(lower_parameters));
    1891         140 :   ++(*index);
    1892         140 : }
    1893             : 
    1894          60 : Node* WasmGraphBuilder::BuildDecodeException32BitValue(Node* const* values,
    1895          60 :                                                        uint32_t* index) {
    1896          60 :   MachineOperatorBuilder* machine = jsgraph()->machine();
    1897          60 :   Node* upper = BuildChangeSmiToInt32(values[*index]);
    1898          60 :   (*index)++;
    1899          60 :   upper = graph()->NewNode(machine->Word32Shl(), upper, Int32Constant(16));
    1900          60 :   Node* lower = BuildChangeSmiToInt32(values[*index]);
    1901          60 :   (*index)++;
    1902          60 :   Node* value = graph()->NewNode(machine->Word32Or(), upper, lower);
    1903          60 :   return value;
    1904             : }
    1905             : 
    1906          70 : Node* WasmGraphBuilder::Rethrow() {
    1907             :   SetNeedsStackCheck();
    1908          70 :   Node* result = BuildCallToRuntime(Runtime::kWasmThrow, nullptr, 0);
    1909          70 :   return result;
    1910             : }
    1911             : 
    1912          70 : Node* WasmGraphBuilder::ConvertExceptionTagToRuntimeId(uint32_t tag) {
    1913             :   // TODO(kschimpf): Handle exceptions from different modules, when they are
    1914             :   // linked at runtime.
    1915          70 :   return Uint32Constant(tag);
    1916             : }
    1917             : 
    1918          70 : Node* WasmGraphBuilder::GetExceptionRuntimeId() {
    1919             :   SetNeedsStackCheck();
    1920             :   return BuildChangeSmiToInt32(
    1921          70 :       BuildCallToRuntime(Runtime::kWasmGetExceptionRuntimeId, nullptr, 0));
    1922             : }
    1923             : 
    1924          70 : Node** WasmGraphBuilder::GetExceptionValues(
    1925             :     const wasm::WasmException* except_decl) {
    1926             :   // TODO(kschimpf): We need to move this code to the function-body-decoder.cc
    1927             :   // in order to build landing-pad (exception) edges in case the runtime
    1928             :   // call causes an exception.
    1929             : 
    1930             :   // Start by getting the encoded values from the exception.
    1931          70 :   uint32_t encoded_size = GetExceptionEncodedSize(except_decl);
    1932          70 :   Node** values = Buffer(encoded_size);
    1933         190 :   for (uint32_t i = 0; i < encoded_size; ++i) {
    1934         120 :     Node* parameters[] = {BuildChangeUint32ToSmi(Uint32Constant(i))};
    1935         120 :     values[i] = BuildCallToRuntime(Runtime::kWasmExceptionGetElement,
    1936         120 :                                    parameters, arraysize(parameters));
    1937             :   }
    1938             : 
    1939             :   // Now convert the leading entries to the corresponding parameter values.
    1940          70 :   uint32_t index = 0;
    1941         220 :   const wasm::WasmExceptionSig* sig = except_decl->sig;
    1942         220 :   for (size_t i = 0; i < sig->parameter_count(); ++i) {
    1943          40 :     Node* value = BuildDecodeException32BitValue(values, &index);
    1944          40 :     switch (wasm::ValueType type = sig->GetParam(i)) {
    1945             :       case wasm::kWasmF32: {
    1946          10 :         value = Unop(wasm::kExprF32ReinterpretI32, value);
    1947          10 :         break;
    1948             :       }
    1949             :       case wasm::kWasmI32:
    1950             :         break;
    1951             :       case wasm::kWasmF64:
    1952             :       case wasm::kWasmI64: {
    1953             :         Node* upper =
    1954             :             Binop(wasm::kExprI64Shl, Unop(wasm::kExprI64UConvertI32, value),
    1955          20 :                   Int64Constant(32));
    1956             :         Node* lower = Unop(wasm::kExprI64UConvertI32,
    1957          20 :                            BuildDecodeException32BitValue(values, &index));
    1958          20 :         value = Binop(wasm::kExprI64Ior, upper, lower);
    1959          20 :         if (type == wasm::kWasmF64) {
    1960          10 :           value = Unop(wasm::kExprF64ReinterpretI64, value);
    1961             :         }
    1962             :         break;
    1963             :       }
    1964             :       default:
    1965           0 :         CHECK(false);
    1966             :         break;
    1967             :     }
    1968          40 :     values[i] = value;
    1969             :   }
    1970             :   DCHECK_EQ(index, encoded_size);
    1971          70 :   return values;
    1972             : }
    1973             : 
    1974         338 : Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right,
    1975         992 :                                      wasm::WasmCodePosition position) {
    1976         338 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1977             :   ZeroCheck32(wasm::kTrapDivByZero, right, position);
    1978         338 :   Node* before = *control_;
    1979             :   Node* denom_is_m1;
    1980             :   Node* denom_is_not_m1;
    1981             :   BranchExpectFalse(
    1982             :       graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
    1983         338 :       &denom_is_m1, &denom_is_not_m1);
    1984         338 :   *control_ = denom_is_m1;
    1985         338 :   TrapIfEq32(wasm::kTrapDivUnrepresentable, left, kMinInt, position);
    1986         338 :   if (*control_ != denom_is_m1) {
    1987             :     *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1,
    1988         948 :                                  *control_);
    1989             :   } else {
    1990          22 :     *control_ = before;
    1991             :   }
    1992         676 :   return graph()->NewNode(m->Int32Div(), left, right, *control_);
    1993             : }
    1994             : 
    1995         156 : Node* WasmGraphBuilder::BuildI32RemS(Node* left, Node* right,
    1996         624 :                                      wasm::WasmCodePosition position) {
    1997         156 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1998             : 
    1999             :   ZeroCheck32(wasm::kTrapRemByZero, right, position);
    2000             : 
    2001             :   Diamond d(
    2002             :       graph(), jsgraph()->common(),
    2003             :       graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
    2004         468 :       BranchHint::kFalse);
    2005         156 :   d.Chain(*control_);
    2006             : 
    2007             :   return d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
    2008         312 :                graph()->NewNode(m->Int32Mod(), left, right, d.if_false));
    2009             : }
    2010             : 
    2011         222 : Node* WasmGraphBuilder::BuildI32DivU(Node* left, Node* right,
    2012         222 :                                      wasm::WasmCodePosition position) {
    2013         222 :   MachineOperatorBuilder* m = jsgraph()->machine();
    2014             :   return graph()->NewNode(m->Uint32Div(), left, right,
    2015         444 :                           ZeroCheck32(wasm::kTrapDivByZero, right, position));
    2016             : }
    2017             : 
    2018         142 : Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right,
    2019         142 :                                      wasm::WasmCodePosition position) {
    2020         142 :   MachineOperatorBuilder* m = jsgraph()->machine();
    2021             :   return graph()->NewNode(m->Uint32Mod(), left, right,
    2022         284 :                           ZeroCheck32(wasm::kTrapRemByZero, right, position));
    2023             : }
    2024             : 
    2025         989 : Node* WasmGraphBuilder::BuildI32AsmjsDivS(Node* left, Node* right) {
    2026         524 :   MachineOperatorBuilder* m = jsgraph()->machine();
    2027             : 
    2028             :   Int32Matcher mr(right);
    2029         524 :   if (mr.HasValue()) {
    2030         431 :     if (mr.Value() == 0) {
    2031          19 :       return jsgraph()->Int32Constant(0);
    2032         412 :     } else if (mr.Value() == -1) {
    2033             :       // The result is the negation of the left input.
    2034          38 :       return graph()->NewNode(m->Int32Sub(), jsgraph()->Int32Constant(0), left);
    2035             :     }
    2036         786 :     return graph()->NewNode(m->Int32Div(), left, right, *control_);
    2037             :   }
    2038             : 
    2039             :   // asm.js semantics return 0 on divide or mod by zero.
    2040          93 :   if (m->Int32DivIsSafe()) {
    2041             :     // The hardware instruction does the right thing (e.g. arm).
    2042           0 :     return graph()->NewNode(m->Int32Div(), left, right, graph()->start());
    2043             :   }
    2044             : 
    2045             :   // Check denominator for zero.
    2046             :   Diamond z(
    2047             :       graph(), jsgraph()->common(),
    2048             :       graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
    2049         279 :       BranchHint::kFalse);
    2050             : 
    2051             :   // Check numerator for -1. (avoid minint / -1 case).
    2052             :   Diamond n(
    2053             :       graph(), jsgraph()->common(),
    2054             :       graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
    2055         279 :       BranchHint::kFalse);
    2056             : 
    2057          93 :   Node* div = graph()->NewNode(m->Int32Div(), left, right, z.if_false);
    2058             :   Node* neg =
    2059          93 :       graph()->NewNode(m->Int32Sub(), jsgraph()->Int32Constant(0), left);
    2060             : 
    2061             :   return n.Phi(
    2062             :       MachineRepresentation::kWord32, neg,
    2063          93 :       z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), div));
    2064             : }
    2065             : 
    2066         700 : Node* WasmGraphBuilder::BuildI32AsmjsRemS(Node* left, Node* right) {
    2067         608 :   CommonOperatorBuilder* c = jsgraph()->common();
    2068         608 :   MachineOperatorBuilder* m = jsgraph()->machine();
    2069         608 :   Node* const zero = jsgraph()->Int32Constant(0);
    2070             : 
    2071             :   Int32Matcher mr(right);
    2072         608 :   if (mr.HasValue()) {
    2073         516 :     if (mr.Value() == 0 || mr.Value() == -1) {
    2074             :       return zero;
    2075             :     }
    2076         956 :     return graph()->NewNode(m->Int32Mod(), left, right, *control_);
    2077             :   }
    2078             : 
    2079             :   // General case for signed integer modulus, with optimization for (unknown)
    2080             :   // power of 2 right hand side.
    2081             :   //
    2082             :   //   if 0 < right then
    2083             :   //     msk = right - 1
    2084             :   //     if right & msk != 0 then
    2085             :   //       left % right
    2086             :   //     else
    2087             :   //       if left < 0 then
    2088             :   //         -(-left & msk)
    2089             :   //       else
    2090             :   //         left & msk
    2091             :   //   else
    2092             :   //     if right < -1 then
    2093             :   //       left % right
    2094             :   //     else
    2095             :   //       zero
    2096             :   //
    2097             :   // Note: We do not use the Diamond helper class here, because it really hurts
    2098             :   // readability with nested diamonds.
    2099          92 :   Node* const minus_one = jsgraph()->Int32Constant(-1);
    2100             : 
    2101          92 :   const Operator* const merge_op = c->Merge(2);
    2102          92 :   const Operator* const phi_op = c->Phi(MachineRepresentation::kWord32, 2);
    2103             : 
    2104          92 :   Node* check0 = graph()->NewNode(m->Int32LessThan(), zero, right);
    2105             :   Node* branch0 =
    2106          92 :       graph()->NewNode(c->Branch(BranchHint::kTrue), check0, graph()->start());
    2107             : 
    2108          92 :   Node* if_true0 = graph()->NewNode(c->IfTrue(), branch0);
    2109             :   Node* true0;
    2110             :   {
    2111          92 :     Node* msk = graph()->NewNode(m->Int32Add(), right, minus_one);
    2112             : 
    2113          92 :     Node* check1 = graph()->NewNode(m->Word32And(), right, msk);
    2114          92 :     Node* branch1 = graph()->NewNode(c->Branch(), check1, if_true0);
    2115             : 
    2116          92 :     Node* if_true1 = graph()->NewNode(c->IfTrue(), branch1);
    2117          92 :     Node* true1 = graph()->NewNode(m->Int32Mod(), left, right, if_true1);
    2118             : 
    2119          92 :     Node* if_false1 = graph()->NewNode(c->IfFalse(), branch1);
    2120             :     Node* false1;
    2121             :     {
    2122          92 :       Node* check2 = graph()->NewNode(m->Int32LessThan(), left, zero);
    2123             :       Node* branch2 =
    2124          92 :           graph()->NewNode(c->Branch(BranchHint::kFalse), check2, if_false1);
    2125             : 
    2126          92 :       Node* if_true2 = graph()->NewNode(c->IfTrue(), branch2);
    2127             :       Node* true2 = graph()->NewNode(
    2128             :           m->Int32Sub(), zero,
    2129             :           graph()->NewNode(m->Word32And(),
    2130         276 :                            graph()->NewNode(m->Int32Sub(), zero, left), msk));
    2131             : 
    2132          92 :       Node* if_false2 = graph()->NewNode(c->IfFalse(), branch2);
    2133          92 :       Node* false2 = graph()->NewNode(m->Word32And(), left, msk);
    2134             : 
    2135             :       if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
    2136             :       false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
    2137             :     }
    2138             : 
    2139             :     if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
    2140             :     true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
    2141             :   }
    2142             : 
    2143          92 :   Node* if_false0 = graph()->NewNode(c->IfFalse(), branch0);
    2144             :   Node* false0;
    2145             :   {
    2146          92 :     Node* check1 = graph()->NewNode(m->Int32LessThan(), right, minus_one);
    2147             :     Node* branch1 =
    2148          92 :         graph()->NewNode(c->Branch(BranchHint::kTrue), check1, if_false0);
    2149             : 
    2150          92 :     Node* if_true1 = graph()->NewNode(c->IfTrue(), branch1);
    2151          92 :     Node* true1 = graph()->NewNode(m->Int32Mod(), left, right, if_true1);
    2152             : 
    2153          92 :     Node* if_false1 = graph()->NewNode(c->IfFalse(), branch1);
    2154             :     Node* false1 = zero;
    2155             : 
    2156             :     if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
    2157             :     false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
    2158             :   }
    2159             : 
    2160             :   Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
    2161          92 :   return graph()->NewNode(phi_op, true0, false0, merge0);
    2162             : }
    2163             : 
    2164         764 : Node* WasmGraphBuilder::BuildI32AsmjsDivU(Node* left, Node* right) {
    2165         191 :   MachineOperatorBuilder* m = jsgraph()->machine();
    2166             :   // asm.js semantics return 0 on divide or mod by zero.
    2167         191 :   if (m->Uint32DivIsSafe()) {
    2168             :     // The hardware instruction does the right thing (e.g. arm).
    2169           0 :     return graph()->NewNode(m->Uint32Div(), left, right, graph()->start());
    2170             :   }
    2171             : 
    2172             :   // Explicit check for x % 0.
    2173             :   Diamond z(
    2174             :       graph(), jsgraph()->common(),
    2175             :       graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
    2176         573 :       BranchHint::kFalse);
    2177             : 
    2178             :   return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
    2179             :                graph()->NewNode(jsgraph()->machine()->Uint32Div(), left, right,
    2180         573 :                                 z.if_false));
    2181             : }
    2182             : 
    2183        1040 : Node* WasmGraphBuilder::BuildI32AsmjsRemU(Node* left, Node* right) {
    2184         260 :   MachineOperatorBuilder* m = jsgraph()->machine();
    2185             :   // asm.js semantics return 0 on divide or mod by zero.
    2186             :   // Explicit check for x % 0.
    2187             :   Diamond z(
    2188             :       graph(), jsgraph()->common(),
    2189             :       graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
    2190         780 :       BranchHint::kFalse);
    2191             : 
    2192             :   Node* rem = graph()->NewNode(jsgraph()->machine()->Uint32Mod(), left, right,
    2193         520 :                                z.if_false);
    2194             :   return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
    2195         260 :                rem);
    2196             : }
    2197             : 
    2198         306 : Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right,
    2199        1518 :                                      wasm::WasmCodePosition position) {
    2200         612 :   if (jsgraph()->machine()->Is32()) {
    2201             :     return BuildDiv64Call(
    2202             :         left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()),
    2203           0 :         MachineType::Int64(), wasm::kTrapDivByZero, position);
    2204             :   }
    2205             :   ZeroCheck64(wasm::kTrapDivByZero, right, position);
    2206         306 :   Node* before = *control_;
    2207             :   Node* denom_is_m1;
    2208             :   Node* denom_is_not_m1;
    2209             :   BranchExpectFalse(graph()->NewNode(jsgraph()->machine()->Word64Equal(), right,
    2210             :                                      jsgraph()->Int64Constant(-1)),
    2211         612 :                     &denom_is_m1, &denom_is_not_m1);
    2212         306 :   *control_ = denom_is_m1;
    2213             :   TrapIfEq64(wasm::kTrapDivUnrepresentable, left,
    2214         306 :              std::numeric_limits<int64_t>::min(), position);
    2215         306 :   if (*control_ != denom_is_m1) {
    2216             :     *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1,
    2217         882 :                                  *control_);
    2218             :   } else {
    2219          12 :     *control_ = before;
    2220             :   }
    2221             :   return graph()->NewNode(jsgraph()->machine()->Int64Div(), left, right,
    2222         918 :                           *control_);
    2223             : }
    2224             : 
    2225         134 : Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right,
    2226         804 :                                      wasm::WasmCodePosition position) {
    2227         268 :   if (jsgraph()->machine()->Is32()) {
    2228             :     return BuildDiv64Call(
    2229             :         left, right, ExternalReference::wasm_int64_mod(jsgraph()->isolate()),
    2230           0 :         MachineType::Int64(), wasm::kTrapRemByZero, position);
    2231             :   }
    2232             :   ZeroCheck64(wasm::kTrapRemByZero, right, position);
    2233             :   Diamond d(jsgraph()->graph(), jsgraph()->common(),
    2234             :             graph()->NewNode(jsgraph()->machine()->Word64Equal(), right,
    2235         402 :                              jsgraph()->Int64Constant(-1)));
    2236             : 
    2237         134 :   d.Chain(*control_);
    2238             : 
    2239             :   Node* rem = graph()->NewNode(jsgraph()->machine()->Int64Mod(), left, right,
    2240         268 :                                d.if_false);
    2241             : 
    2242             :   return d.Phi(MachineRepresentation::kWord64, jsgraph()->Int64Constant(0),
    2243         134 :                rem);
    2244             : }
    2245             : 
    2246         154 : Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right,
    2247         308 :                                      wasm::WasmCodePosition position) {
    2248         308 :   if (jsgraph()->machine()->Is32()) {
    2249             :     return BuildDiv64Call(
    2250             :         left, right, ExternalReference::wasm_uint64_div(jsgraph()->isolate()),
    2251           0 :         MachineType::Int64(), wasm::kTrapDivByZero, position);
    2252             :   }
    2253             :   return graph()->NewNode(jsgraph()->machine()->Uint64Div(), left, right,
    2254         308 :                           ZeroCheck64(wasm::kTrapDivByZero, right, position));
    2255             : }
    2256         134 : Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right,
    2257         268 :                                      wasm::WasmCodePosition position) {
    2258         268 :   if (jsgraph()->machine()->Is32()) {
    2259             :     return BuildDiv64Call(
    2260             :         left, right, ExternalReference::wasm_uint64_mod(jsgraph()->isolate()),
    2261           0 :         MachineType::Int64(), wasm::kTrapRemByZero, position);
    2262             :   }
    2263             :   return graph()->NewNode(jsgraph()->machine()->Uint64Mod(), left, right,
    2264         268 :                           ZeroCheck64(wasm::kTrapRemByZero, right, position));
    2265             : }
    2266             : 
    2267           0 : Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right,
    2268             :                                        ExternalReference ref,
    2269             :                                        MachineType result_type, int trap_zero,
    2270           0 :                                        wasm::WasmCodePosition position) {
    2271             :   Node* stack_slot_dst = graph()->NewNode(
    2272           0 :       jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64));
    2273             :   Node* stack_slot_src = graph()->NewNode(
    2274           0 :       jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64));
    2275             : 
    2276             :   const Operator* store_op = jsgraph()->machine()->Store(
    2277           0 :       StoreRepresentation(MachineRepresentation::kWord64, kNoWriteBarrier));
    2278             :   *effect_ =
    2279             :       graph()->NewNode(store_op, stack_slot_dst, jsgraph()->Int32Constant(0),
    2280           0 :                        left, *effect_, *control_);
    2281             :   *effect_ =
    2282             :       graph()->NewNode(store_op, stack_slot_src, jsgraph()->Int32Constant(0),
    2283           0 :                        right, *effect_, *control_);
    2284             : 
    2285             :   MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2);
    2286             :   sig_builder.AddReturn(MachineType::Int32());
    2287             :   sig_builder.AddParam(MachineType::Pointer());
    2288             :   sig_builder.AddParam(MachineType::Pointer());
    2289             : 
    2290           0 :   Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
    2291             :   Node* call =
    2292           0 :       BuildCCall(sig_builder.Build(), function, stack_slot_dst, stack_slot_src);
    2293             : 
    2294           0 :   ZeroCheck32(static_cast<wasm::TrapReason>(trap_zero), call, position);
    2295           0 :   TrapIfEq32(wasm::kTrapDivUnrepresentable, call, -1, position);
    2296           0 :   const Operator* load_op = jsgraph()->machine()->Load(result_type);
    2297             :   Node* load =
    2298             :       graph()->NewNode(load_op, stack_slot_dst, jsgraph()->Int32Constant(0),
    2299           0 :                        *effect_, *control_);
    2300           0 :   *effect_ = load;
    2301           0 :   return load;
    2302             : }
    2303             : 
    2304             : template <typename... Args>
    2305       35865 : Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node* function,
    2306       71568 :                                    Args... args) {
    2307             :   DCHECK_LE(sig->return_count(), 1);
    2308             :   DCHECK_EQ(sizeof...(args), sig->parameter_count());
    2309       35865 :   Node* const call_args[] = {function, args..., *effect_, *control_};
    2310             : 
    2311             :   CallDescriptor* desc =
    2312       35865 :       Linkage::GetSimplifiedCDescriptor(jsgraph()->zone(), sig);
    2313             : 
    2314       35865 :   const Operator* op = jsgraph()->common()->Call(desc);
    2315       35865 :   Node* call = graph()->NewNode(op, arraysize(call_args), call_args);
    2316       35865 :   *effect_ = call;
    2317       35865 :   return call;
    2318             : }
    2319             : 
    2320      527441 : Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args,
    2321             :                                       Node*** rets,
    2322      351628 :                                       wasm::WasmCodePosition position) {
    2323             :   DCHECK_NOT_NULL(wasm_context_);
    2324             :   SetNeedsStackCheck();
    2325             :   const size_t params = sig->parameter_count();
    2326             :   const size_t extra = 3;  // wasm_context, effect, and control.
    2327      175813 :   const size_t count = 1 + params + extra;
    2328             : 
    2329             :   // Reallocate the buffer to make space for extra inputs.
    2330      175813 :   args = Realloc(args, 1 + params, count);
    2331             : 
    2332             :   // Make room for the wasm_context parameter at index 1, just after code.
    2333      175825 :   memmove(&args[2], &args[1], params * sizeof(Node*));
    2334      175825 :   args[1] = wasm_context_;
    2335             : 
    2336             :   // Add effect and control inputs.
    2337      175825 :   args[params + 2] = *effect_;
    2338      175825 :   args[params + 3] = *control_;
    2339             : 
    2340      175825 :   CallDescriptor* descriptor = GetWasmCallDescriptor(jsgraph()->zone(), sig);
    2341      175803 :   const Operator* op = jsgraph()->common()->Call(descriptor);
    2342      351636 :   Node* call = graph()->NewNode(op, static_cast<int>(count), args);
    2343      175815 :   SetSourcePosition(call, position);
    2344             : 
    2345      175815 :   *effect_ = call;
    2346             :   size_t ret_count = sig->return_count();
    2347      175815 :   if (ret_count == 0) return call;  // No return value.
    2348             : 
    2349      153485 :   *rets = Buffer(ret_count);
    2350      153491 :   if (ret_count == 1) {
    2351             :     // Only a single return value.
    2352      151943 :     (*rets)[0] = call;
    2353             :   } else {
    2354             :     // Create projections for all return values.
    2355        3096 :     for (size_t i = 0; i < ret_count; i++) {
    2356        3096 :       (*rets)[i] = graph()->NewNode(jsgraph()->common()->Projection(i), call,
    2357        6192 :                                     graph()->start());
    2358             :     }
    2359             :   }
    2360             :   return call;
    2361             : }
    2362             : 
    2363      172517 : Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, Node*** rets,
    2364             :                                    wasm::WasmCodePosition position) {
    2365             :   DCHECK_NULL(args[0]);
    2366             : 
    2367             :   // Add code object as constant.
    2368      172517 :   Handle<Code> code = index < env_->function_code.size()
    2369             :                           ? env_->function_code[index]
    2370      340054 :                           : env_->default_function_code;
    2371             : 
    2372             :   DCHECK(!code.is_null());
    2373      172537 :   args[0] = HeapConstant(code);
    2374      345074 :   wasm::FunctionSig* sig = env_->module->functions[index].sig;
    2375             : 
    2376      172537 :   return BuildWasmCall(sig, args, rets, position);
    2377             : }
    2378             : 
    2379        3290 : Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args,
    2380             :                                      Node*** rets,
    2381       19737 :                                      wasm::WasmCodePosition position) {
    2382             :   DCHECK_NOT_NULL(args[0]);
    2383             :   DCHECK_NOT_NULL(env_);
    2384             : 
    2385             :   // Assume only one table for now.
    2386             :   uint32_t table_index = 0;
    2387        6580 :   wasm::FunctionSig* sig = env_->module->signatures[sig_index];
    2388             : 
    2389        3290 :   EnsureFunctionTableNodes();
    2390        3290 :   MachineOperatorBuilder* machine = jsgraph()->machine();
    2391        3290 :   Node* key = args[0];
    2392             : 
    2393             :   // Bounds check against the table size.
    2394        3290 :   Node* size = function_table_sizes_[table_index];
    2395        3290 :   Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size);
    2396        3290 :   TrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position);
    2397        3289 :   Node* table_address = function_tables_[table_index];
    2398             :   Node* table = graph()->NewNode(
    2399             :       jsgraph()->machine()->Load(MachineType::AnyTagged()), table_address,
    2400        9868 :       jsgraph()->IntPtrConstant(0), *effect_, *control_);
    2401        3289 :   Node* signatures_address = signature_tables_[table_index];
    2402             :   Node* signatures = graph()->NewNode(
    2403             :       jsgraph()->machine()->Load(MachineType::AnyTagged()), signatures_address,
    2404        9868 :       jsgraph()->IntPtrConstant(0), *effect_, *control_);
    2405             :   // Load signature from the table and check.
    2406             :   // The table is a FixedArray; signatures are encoded as SMIs.
    2407             :   // [sig1, sig2, sig3, ...., code1, code2, code3 ...]
    2408        3290 :   ElementAccess access = AccessBuilder::ForFixedArrayElement();
    2409        6580 :   const int fixed_offset = access.header_size - access.tag();
    2410             :   {
    2411             :     Node* load_sig = graph()->NewNode(
    2412             :         machine->Load(MachineType::AnyTagged()), signatures,
    2413             :         graph()->NewNode(machine->Int32Add(),
    2414             :                          graph()->NewNode(machine->Word32Shl(), key,
    2415             :                                           Int32Constant(kPointerSizeLog2)),
    2416             :                          Int32Constant(fixed_offset)),
    2417       13159 :         *effect_, *control_);
    2418        6578 :     int32_t canonical_sig_num = env_->module->signature_ids[sig_index];
    2419             :     CHECK_GE(sig_index, 0);
    2420             :     Node* sig_match =
    2421             :         graph()->NewNode(machine->WordEqual(), load_sig,
    2422        3290 :                          jsgraph()->SmiConstant(canonical_sig_num));
    2423        3289 :     TrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position);
    2424             :   }
    2425             : 
    2426             :   // Load code object from the table.
    2427             :   Node* load_code = graph()->NewNode(
    2428             :       machine->Load(MachineType::AnyTagged()), table,
    2429             :       graph()->NewNode(machine->Int32Add(),
    2430             :                        graph()->NewNode(machine->Word32Shl(), key,
    2431             :                                         Int32Constant(kPointerSizeLog2)),
    2432             :                        Uint32Constant(fixed_offset)),
    2433       13157 :       *effect_, *control_);
    2434             : 
    2435        3290 :   args[0] = load_code;
    2436        3290 :   return BuildWasmCall(sig, args, rets, position);
    2437             : }
    2438             : 
    2439         128 : Node* WasmGraphBuilder::BuildI32Rol(Node* left, Node* right) {
    2440             :   // Implement Rol by Ror since TurboFan does not have Rol opcode.
    2441             :   // TODO(weiliang): support Word32Rol opcode in TurboFan.
    2442             :   Int32Matcher m(right);
    2443          64 :   if (m.HasValue()) {
    2444             :     return Binop(wasm::kExprI32Ror, left,
    2445          48 :                  jsgraph()->Int32Constant(32 - m.Value()));
    2446             :   } else {
    2447             :     return Binop(wasm::kExprI32Ror, left,
    2448          40 :                  Binop(wasm::kExprI32Sub, jsgraph()->Int32Constant(32), right));
    2449             :   }
    2450             : }
    2451             : 
    2452         152 : Node* WasmGraphBuilder::BuildI64Rol(Node* left, Node* right) {
    2453             :   // Implement Rol by Ror since TurboFan does not have Rol opcode.
    2454             :   // TODO(weiliang): support Word64Rol opcode in TurboFan.
    2455             :   Int64Matcher m(right);
    2456          76 :   if (m.HasValue()) {
    2457             :     return Binop(wasm::kExprI64Ror, left,
    2458          48 :                  jsgraph()->Int64Constant(64 - m.Value()));
    2459             :   } else {
    2460             :     return Binop(wasm::kExprI64Ror, left,
    2461          52 :                  Binop(wasm::kExprI64Sub, jsgraph()->Int64Constant(64), right));
    2462             :   }
    2463             : }
    2464             : 
    2465       22692 : Node* WasmGraphBuilder::Invert(Node* node) {
    2466       22692 :   return Unop(wasm::kExprI32Eqz, node);
    2467             : }
    2468             : 
    2469       28964 : Node* WasmGraphBuilder::BuildChangeInt32ToTagged(Node* value) {
    2470       28964 :   MachineOperatorBuilder* machine = jsgraph()->machine();
    2471       28964 :   CommonOperatorBuilder* common = jsgraph()->common();
    2472             : 
    2473       28964 :   if (machine->Is64()) {
    2474       28964 :     return BuildChangeInt32ToSmi(value);
    2475             :   }
    2476             : 
    2477             :   Node* add = graph()->NewNode(machine->Int32AddWithOverflow(), value, value,
    2478           0 :                                graph()->start());
    2479             : 
    2480           0 :   Node* ovf = graph()->NewNode(common->Projection(1), add, graph()->start());
    2481             :   Node* branch = graph()->NewNode(common->Branch(BranchHint::kFalse), ovf,
    2482           0 :                                   graph()->start());
    2483             : 
    2484           0 :   Node* if_true = graph()->NewNode(common->IfTrue(), branch);
    2485             :   Node* vtrue = BuildAllocateHeapNumberWithValue(
    2486           0 :       graph()->NewNode(machine->ChangeInt32ToFloat64(), value), if_true);
    2487             : 
    2488           0 :   Node* if_false = graph()->NewNode(common->IfFalse(), branch);
    2489           0 :   Node* vfalse = graph()->NewNode(common->Projection(0), add, if_false);
    2490             : 
    2491           0 :   Node* merge = graph()->NewNode(common->Merge(2), if_true, if_false);
    2492             :   Node* phi = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2),
    2493           0 :                                vtrue, vfalse, merge);
    2494           0 :   return phi;
    2495             : }
    2496             : 
    2497      133347 : Node* WasmGraphBuilder::BuildChangeFloat64ToTagged(Node* value) {
    2498       44449 :   MachineOperatorBuilder* machine = jsgraph()->machine();
    2499       44449 :   CommonOperatorBuilder* common = jsgraph()->common();
    2500             : 
    2501       44449 :   Node* value32 = graph()->NewNode(machine->RoundFloat64ToInt32(), value);
    2502             :   Node* check_same = graph()->NewNode(
    2503             :       machine->Float64Equal(), value,
    2504       88898 :       graph()->NewNode(machine->ChangeInt32ToFloat64(), value32));
    2505             :   Node* branch_same =
    2506       44449 :       graph()->NewNode(common->Branch(), check_same, graph()->start());
    2507             : 
    2508       44449 :   Node* if_smi = graph()->NewNode(common->IfTrue(), branch_same);
    2509             :   Node* vsmi;
    2510       44449 :   Node* if_box = graph()->NewNode(common->IfFalse(), branch_same);
    2511             :   Node* vbox;
    2512             : 
    2513             :   // We only need to check for -0 if the {value} can potentially contain -0.
    2514             :   Node* check_zero = graph()->NewNode(machine->Word32Equal(), value32,
    2515       44449 :                                       jsgraph()->Int32Constant(0));
    2516             :   Node* branch_zero =
    2517       44449 :       graph()->NewNode(common->Branch(BranchHint::kFalse), check_zero, if_smi);
    2518             : 
    2519       44449 :   Node* if_zero = graph()->NewNode(common->IfTrue(), branch_zero);
    2520       44449 :   Node* if_notzero = graph()->NewNode(common->IfFalse(), branch_zero);
    2521             : 
    2522             :   // In case of 0, we need to check the high bits for the IEEE -0 pattern.
    2523             :   Node* check_negative = graph()->NewNode(
    2524             :       machine->Int32LessThan(),
    2525             :       graph()->NewNode(machine->Float64ExtractHighWord32(), value),
    2526       88898 :       jsgraph()->Int32Constant(0));
    2527             :   Node* branch_negative = graph()->NewNode(common->Branch(BranchHint::kFalse),
    2528       44449 :                                            check_negative, if_zero);
    2529             : 
    2530       44449 :   Node* if_negative = graph()->NewNode(common->IfTrue(), branch_negative);
    2531       44449 :   Node* if_notnegative = graph()->NewNode(common->IfFalse(), branch_negative);
    2532             : 
    2533             :   // We need to create a box for negative 0.
    2534       44449 :   if_smi = graph()->NewNode(common->Merge(2), if_notzero, if_notnegative);
    2535       44449 :   if_box = graph()->NewNode(common->Merge(2), if_box, if_negative);
    2536             : 
    2537             :   // On 64-bit machines we can just wrap the 32-bit integer in a smi, for 32-bit
    2538             :   // machines we need to deal with potential overflow and fallback to boxing.
    2539       44449 :   if (machine->Is64()) {
    2540       44449 :     vsmi = BuildChangeInt32ToSmi(value32);
    2541             :   } else {
    2542             :     Node* smi_tag = graph()->NewNode(machine->Int32AddWithOverflow(), value32,
    2543           0 :                                      value32, if_smi);
    2544             : 
    2545           0 :     Node* check_ovf = graph()->NewNode(common->Projection(1), smi_tag, if_smi);
    2546             :     Node* branch_ovf =
    2547           0 :         graph()->NewNode(common->Branch(BranchHint::kFalse), check_ovf, if_smi);
    2548             : 
    2549           0 :     Node* if_ovf = graph()->NewNode(common->IfTrue(), branch_ovf);
    2550           0 :     if_box = graph()->NewNode(common->Merge(2), if_ovf, if_box);
    2551             : 
    2552           0 :     if_smi = graph()->NewNode(common->IfFalse(), branch_ovf);
    2553           0 :     vsmi = graph()->NewNode(common->Projection(0), smi_tag, if_smi);
    2554             :   }
    2555             : 
    2556             :   // Allocate the box for the {value}.
    2557       44449 :   vbox = BuildAllocateHeapNumberWithValue(value, if_box);
    2558             : 
    2559       44449 :   Node* control = graph()->NewNode(common->Merge(2), if_smi, if_box);
    2560             :   value = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2), vsmi,
    2561       44449 :                            vbox, control);
    2562       44449 :   return value;
    2563             : }
    2564             : 
    2565      369464 : Node* WasmGraphBuilder::ToJS(Node* node, wasm::ValueType type) {
    2566      214658 :   switch (type) {
    2567             :     case wasm::kWasmI32:
    2568       28964 :       return BuildChangeInt32ToTagged(node);
    2569             :     case wasm::kWasmS128:
    2570             :     case wasm::kWasmI64:
    2571           0 :       UNREACHABLE();
    2572             :     case wasm::kWasmF32:
    2573             :       node = graph()->NewNode(jsgraph()->machine()->ChangeFloat32ToFloat64(),
    2574       13561 :                               node);
    2575       13561 :       return BuildChangeFloat64ToTagged(node);
    2576             :     case wasm::kWasmF64:
    2577       30888 :       return BuildChangeFloat64ToTagged(node);
    2578             :     case wasm::kWasmStmt:
    2579      141245 :       return jsgraph()->UndefinedConstant();
    2580             :     default:
    2581           0 :       UNREACHABLE();
    2582             :   }
    2583             : }
    2584             : 
    2585      347296 : Node* WasmGraphBuilder::BuildJavaScriptToNumber(Node* node, Node* js_context) {
    2586             :   Callable callable =
    2587       86824 :       Builtins::CallableFor(jsgraph()->isolate(), Builtins::kToNumber);
    2588             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2589             :       jsgraph()->isolate(), jsgraph()->zone(), callable.descriptor(), 0,
    2590      173648 :       CallDescriptor::kNoFlags, Operator::kNoProperties);
    2591       86824 :   Node* stub_code = jsgraph()->HeapConstant(callable.code());
    2592             : 
    2593             :   Node* result = graph()->NewNode(jsgraph()->common()->Call(desc), stub_code,
    2594      173648 :                                   node, js_context, *effect_, *control_);
    2595             : 
    2596       86824 :   SetSourcePosition(result, 1);
    2597             : 
    2598       86824 :   *effect_ = result;
    2599             : 
    2600       86824 :   return result;
    2601             : }
    2602             : 
    2603           0 : bool CanCover(Node* value, IrOpcode::Value opcode) {
    2604           0 :   if (value->opcode() != opcode) return false;
    2605             :   bool first = true;
    2606           0 :   for (Edge const edge : value->use_edges()) {
    2607           0 :     if (NodeProperties::IsControlEdge(edge)) continue;
    2608           0 :     if (NodeProperties::IsEffectEdge(edge)) continue;
    2609             :     DCHECK(NodeProperties::IsValueEdge(edge));
    2610           0 :     if (!first) return false;
    2611             :     first = false;
    2612             :   }
    2613           0 :   return true;
    2614             : }
    2615             : 
    2616      260472 : Node* WasmGraphBuilder::BuildChangeTaggedToFloat64(Node* value) {
    2617       86824 :   MachineOperatorBuilder* machine = jsgraph()->machine();
    2618       86824 :   CommonOperatorBuilder* common = jsgraph()->common();
    2619             : 
    2620       86824 :   Node* check = BuildTestNotSmi(value);
    2621             :   Node* branch = graph()->NewNode(common->Branch(BranchHint::kFalse), check,
    2622       86824 :                                   graph()->start());
    2623             : 
    2624       86824 :   Node* if_not_smi = graph()->NewNode(common->IfTrue(), branch);
    2625             : 
    2626             :   Node* vnot_smi;
    2627             :   Node* check_undefined = graph()->NewNode(machine->WordEqual(), value,
    2628       86824 :                                            jsgraph()->UndefinedConstant());
    2629             :   Node* branch_undefined = graph()->NewNode(common->Branch(BranchHint::kFalse),
    2630       86824 :                                             check_undefined, if_not_smi);
    2631             : 
    2632       86824 :   Node* if_undefined = graph()->NewNode(common->IfTrue(), branch_undefined);
    2633             :   Node* vundefined =
    2634       86824 :       jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
    2635             : 
    2636             :   Node* if_not_undefined =
    2637       86824 :       graph()->NewNode(common->IfFalse(), branch_undefined);
    2638       86824 :   Node* vheap_number = BuildLoadHeapNumberValue(value, if_not_undefined);
    2639             : 
    2640             :   if_not_smi =
    2641       86824 :       graph()->NewNode(common->Merge(2), if_undefined, if_not_undefined);
    2642             :   vnot_smi = graph()->NewNode(common->Phi(MachineRepresentation::kFloat64, 2),
    2643       86824 :                               vundefined, vheap_number, if_not_smi);
    2644             : 
    2645       86824 :   Node* if_smi = graph()->NewNode(common->IfFalse(), branch);
    2646       86824 :   Node* vfrom_smi = BuildChangeSmiToFloat64(value);
    2647             : 
    2648       86824 :   Node* merge = graph()->NewNode(common->Merge(2), if_not_smi, if_smi);
    2649             :   Node* phi = graph()->NewNode(common->Phi(MachineRepresentation::kFloat64, 2),
    2650       86824 :                                vnot_smi, vfrom_smi, merge);
    2651             : 
    2652       86824 :   return phi;
    2653             : }
    2654             : 
    2655       86824 : Node* WasmGraphBuilder::FromJS(Node* node, Node* js_context,
    2656      130747 :                                wasm::ValueType type) {
    2657             :   DCHECK_NE(wasm::kWasmStmt, type);
    2658             : 
    2659             :   // Do a JavaScript ToNumber.
    2660       86824 :   Node* num = BuildJavaScriptToNumber(node, js_context);
    2661             : 
    2662             :   // Change representation.
    2663       86824 :   SimplifiedOperatorBuilder simplified(jsgraph()->zone());
    2664       86824 :   num = BuildChangeTaggedToFloat64(num);
    2665             : 
    2666       86824 :   switch (type) {
    2667             :     case wasm::kWasmI32: {
    2668             :       num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToWord32(),
    2669       28989 :                              num);
    2670       28989 :       break;
    2671             :     }
    2672             :     case wasm::kWasmS128:
    2673             :     case wasm::kWasmI64:
    2674           0 :       UNREACHABLE();
    2675             :     case wasm::kWasmF32:
    2676             :       num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToFloat32(),
    2677       14934 :                              num);
    2678       14934 :       break;
    2679             :     case wasm::kWasmF64:
    2680             :       break;
    2681             :     default:
    2682           0 :       UNREACHABLE();
    2683             :   }
    2684       86824 :   return num;
    2685             : }
    2686             : 
    2687      147065 : Node* WasmGraphBuilder::BuildChangeInt32ToSmi(Node* value) {
    2688      147064 :   if (jsgraph()->machine()->Is64()) {
    2689       73531 :     value = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), value);
    2690             :   }
    2691             :   return graph()->NewNode(jsgraph()->machine()->WordShl(), value,
    2692      147066 :                           BuildSmiShiftBitsConstant());
    2693             : }
    2694             : 
    2695      264360 : Node* WasmGraphBuilder::BuildChangeSmiToInt32(Node* value) {
    2696             :   value = graph()->NewNode(jsgraph()->machine()->WordSar(), value,
    2697       88120 :                            BuildSmiShiftBitsConstant());
    2698      176240 :   if (jsgraph()->machine()->Is64()) {
    2699             :     value =
    2700       88120 :         graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(), value);
    2701             :   }
    2702       88120 :   return value;
    2703             : }
    2704             : 
    2705        4132 : Node* WasmGraphBuilder::BuildChangeUint32ToSmi(Node* value) {
    2706        4132 :   if (jsgraph()->machine()->Is64()) {
    2707             :     value =
    2708        2066 :         graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), value);
    2709             :   }
    2710             :   return graph()->NewNode(jsgraph()->machine()->WordShl(), value,
    2711        4132 :                           BuildSmiShiftBitsConstant());
    2712             : }
    2713             : 
    2714      173648 : Node* WasmGraphBuilder::BuildChangeSmiToFloat64(Node* value) {
    2715             :   return graph()->NewNode(jsgraph()->machine()->ChangeInt32ToFloat64(),
    2716      260472 :                           BuildChangeSmiToInt32(value));
    2717             : }
    2718             : 
    2719      173648 : Node* WasmGraphBuilder::BuildTestNotSmi(Node* value) {
    2720             :   STATIC_ASSERT(kSmiTag == 0);
    2721             :   STATIC_ASSERT(kSmiTagMask == 1);
    2722             :   return graph()->NewNode(jsgraph()->machine()->WordAnd(), value,
    2723      260472 :                           jsgraph()->IntPtrConstant(kSmiTagMask));
    2724             : }
    2725             : 
    2726      163718 : Node* WasmGraphBuilder::BuildSmiShiftBitsConstant() {
    2727      163718 :   return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize);
    2728             : }
    2729             : 
    2730       44449 : Node* WasmGraphBuilder::BuildAllocateHeapNumberWithValue(Node* value,
    2731      144750 :                                                          Node* control) {
    2732       44449 :   MachineOperatorBuilder* machine = jsgraph()->machine();
    2733       44449 :   CommonOperatorBuilder* common = jsgraph()->common();
    2734             :   // The AllocateHeapNumber builtin does not use the js_context, so we can
    2735             :   // safely pass in Smi zero here.
    2736             :   Callable callable = Builtins::CallableFor(jsgraph()->isolate(),
    2737       44449 :                                             Builtins::kAllocateHeapNumber);
    2738       44449 :   Node* target = jsgraph()->HeapConstant(callable.code());
    2739             :   Node* js_context = jsgraph()->NoContextConstant();
    2740             :   Node* effect =
    2741             :       graph()->NewNode(common->BeginRegion(RegionObservability::kNotObservable),
    2742       44449 :                        graph()->start());
    2743       44449 :   if (!allocate_heap_number_operator_.is_set()) {
    2744             :     CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
    2745             :         jsgraph()->isolate(), jsgraph()->zone(), callable.descriptor(), 0,
    2746       22806 :         CallDescriptor::kNoFlags, Operator::kNoThrow);
    2747       11403 :     allocate_heap_number_operator_.set(common->Call(descriptor));
    2748             :   }
    2749             :   Node* heap_number = graph()->NewNode(allocate_heap_number_operator_.get(),
    2750             :                                        target, js_context, effect, control);
    2751             :   Node* store =
    2752             :       graph()->NewNode(machine->Store(StoreRepresentation(
    2753             :                            MachineRepresentation::kFloat64, kNoWriteBarrier)),
    2754             :                        heap_number, BuildHeapNumberValueIndexConstant(), value,
    2755       88898 :                        heap_number, control);
    2756       88898 :   return graph()->NewNode(common->FinishRegion(), heap_number, store);
    2757             : }
    2758             : 
    2759      173648 : Node* WasmGraphBuilder::BuildLoadHeapNumberValue(Node* value, Node* control) {
    2760             :   return graph()->NewNode(jsgraph()->machine()->Load(MachineType::Float64()),
    2761             :                           value, BuildHeapNumberValueIndexConstant(),
    2762      260472 :                           graph()->start(), control);
    2763             : }
    2764             : 
    2765       44449 : Node* WasmGraphBuilder::BuildHeapNumberValueIndexConstant() {
    2766      131273 :   return jsgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag);
    2767             : }
    2768             : 
    2769      160176 : void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code,
    2770      482248 :                                             Address wasm_context_address) {
    2771      416729 :   const int wasm_count = static_cast<int>(sig_->parameter_count());
    2772             :   const int count =
    2773      160176 :       wasm_count + 4;  // wasm_code, wasm_context, effect, and control.
    2774      160176 :   Node** args = Buffer(count);
    2775             : 
    2776             :   // Build the start and the JS parameter nodes.
    2777      160176 :   Node* start = Start(wasm_count + 5);
    2778      160176 :   *control_ = start;
    2779      160176 :   *effect_ = start;
    2780             : 
    2781             :   // Create the js_context parameter
    2782             :   Node* js_context = graph()->NewNode(
    2783             :       jsgraph()->common()->Parameter(
    2784             :           Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"),
    2785      320352 :       graph()->start());
    2786             : 
    2787             :   // Create the wasm_context node to pass as parameter. This must be a
    2788             :   // RelocatableIntPtrConstant because JSToWasm wrappers are compiled at module
    2789             :   // compile time and patched at instance build time.
    2790             :   DCHECK_NULL(wasm_context_);
    2791             :   wasm_context_ = jsgraph()->RelocatableIntPtrConstant(
    2792             :       reinterpret_cast<uintptr_t>(wasm_context_address),
    2793      320352 :       RelocInfo::WASM_CONTEXT_REFERENCE);
    2794             : 
    2795      160176 :   if (!wasm::IsJSCompatibleSignature(sig_)) {
    2796             :     // Throw a TypeError. Use the js_context of the calling javascript function
    2797             :     // (passed as a parameter), such that the generated code is js_context
    2798             :     // independent.
    2799             :     BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError, js_context,
    2800         860 :                                   nullptr, 0);
    2801             : 
    2802             :     // Add a dummy call to the wasm function so that the generated wrapper
    2803             :     // contains a reference to the wrapped wasm function. Without this reference
    2804             :     // the wasm function could not be re-imported into another wasm module.
    2805             :     int pos = 0;
    2806         860 :     args[pos++] = HeapConstant(wasm_code);
    2807         860 :     args[pos++] = wasm_context_;
    2808         860 :     args[pos++] = *effect_;
    2809         860 :     args[pos++] = *control_;
    2810             : 
    2811             :     // We only need a dummy call descriptor.
    2812             :     wasm::FunctionSig::Builder dummy_sig_builder(jsgraph()->zone(), 0, 0);
    2813             :     CallDescriptor* desc =
    2814        1720 :         GetWasmCallDescriptor(jsgraph()->zone(), dummy_sig_builder.Build());
    2815        2580 :     *effect_ = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args);
    2816         860 :     Return(jsgraph()->UndefinedConstant());
    2817      160176 :     return;
    2818             :   }
    2819             : 
    2820             :   int pos = 0;
    2821      159316 :   args[pos++] = HeapConstant(wasm_code);
    2822      159316 :   args[pos++] = wasm_context_;
    2823             : 
    2824             :   // Convert JS parameters to wasm numbers.
    2825      397798 :   for (int i = 0; i < wasm_count; ++i) {
    2826       79166 :     Node* param = Param(i + 1);
    2827      158332 :     Node* wasm_param = FromJS(param, js_context, sig_->GetParam(i));
    2828       79166 :     args[pos++] = wasm_param;
    2829             :   }
    2830             : 
    2831             :   // Set the ThreadInWasm flag before we do the actual call.
    2832      159316 :   BuildModifyThreadInWasmFlag(true);
    2833             : 
    2834      159316 :   args[pos++] = *effect_;
    2835      159316 :   args[pos++] = *control_;
    2836             : 
    2837             :   // Call the wasm code.
    2838      318632 :   CallDescriptor* desc = GetWasmCallDescriptor(jsgraph()->zone(), sig_);
    2839             : 
    2840      318632 :   Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args);
    2841      159316 :   *effect_ = call;
    2842             : 
    2843             :   // Clear the ThreadInWasmFlag
    2844      159316 :   BuildModifyThreadInWasmFlag(false);
    2845             : 
    2846             :   Node* retval = call;
    2847             :   Node* jsval = ToJS(
    2848      477948 :       retval, sig_->return_count() == 0 ? wasm::kWasmStmt : sig_->GetReturn());
    2849             :   Return(jsval);
    2850             : }
    2851             : 
    2852       13442 : int WasmGraphBuilder::AddParameterNodes(Node** args, int pos, int param_count,
    2853       55342 :                                         wasm::FunctionSig* sig) {
    2854             :   // Convert wasm numbers to JS values.
    2855       82226 :   for (int i = 0; i < param_count; ++i) {
    2856       55342 :     Node* param = Param(i + 1);  // Start from index 1 to drop the wasm_context.
    2857      110684 :     args[pos++] = ToJS(param, sig->GetParam(i));
    2858             :   }
    2859       13442 :   return pos;
    2860             : }
    2861             : 
    2862      128289 : Node* WasmGraphBuilder::LoadImportDataAtOffset(int offset, Node* table) {
    2863             :   offset = FixedArray::OffsetOfElementAt(offset) - kHeapObjectTag;
    2864       42763 :   Node* offset_node = jsgraph()->Int32Constant(offset);
    2865             :   Node* import_data = graph()->NewNode(
    2866             :       jsgraph()->machine()->Load(LoadRepresentation::TaggedPointer()), table,
    2867       85526 :       offset_node, *effect_, *control_);
    2868       42763 :   *effect_ = import_data;
    2869       42763 :   return import_data;
    2870             : }
    2871             : 
    2872           0 : Node* WasmGraphBuilder::LoadNativeContext(Node* table) {
    2873             :   // The js_imports_table is set up so that index 0 has isolate->native_context
    2874       12391 :   return LoadImportDataAtOffset(0, table);
    2875             : }
    2876             : 
    2877           0 : int OffsetForImportData(int index, WasmGraphBuilder::ImportDataType type) {
    2878             :   // The js_imports_table is set up so that index 0 has isolate->native_context
    2879             :   // and for every index, 3*index+1 has the JSReceiver, 3*index+2 has function's
    2880             :   // global proxy and 3*index+3 has function's context.
    2881       80290 :   return 3 * index + type;
    2882             : }
    2883             : 
    2884           0 : Node* WasmGraphBuilder::LoadImportData(int index, ImportDataType type,
    2885             :                                        Node* table) {
    2886       30372 :   return LoadImportDataAtOffset(OffsetForImportData(index, type), table);
    2887             : }
    2888             : 
    2889       13492 : bool WasmGraphBuilder::BuildWasmToJSWrapper(
    2890             :     Handle<JSReceiver> target, Handle<FixedArray> global_js_imports_table,
    2891      105080 :     int index) {
    2892             :   DCHECK(target->IsCallable());
    2893             : 
    2894       34592 :   int wasm_count = static_cast<int>(sig_->parameter_count());
    2895             : 
    2896             :   // Build the start and the parameter nodes.
    2897       13492 :   Isolate* isolate = jsgraph()->isolate();
    2898             :   CallDescriptor* desc;
    2899       13492 :   Node* start = Start(wasm_count + 3);
    2900       13492 :   *effect_ = start;
    2901       13492 :   *control_ = start;
    2902             : 
    2903             :   // We add the target function to a table and look it up during runtime. This
    2904             :   // ensures that if the GC kicks in, it doesn't need to patch the code for the
    2905             :   // JS function.
    2906             :   // js_imports_table is fixed array with global handle scope whose lifetime is
    2907             :   // tied to the instance.
    2908             :   // TODO(aseemgarg): explore using per-import global handle instead of a table
    2909             :   Node* table_ptr = jsgraph()->IntPtrConstant(
    2910       26984 :       reinterpret_cast<intptr_t>(global_js_imports_table.location()));
    2911             :   Node* table = graph()->NewNode(
    2912             :       jsgraph()->machine()->Load(LoadRepresentation::TaggedPointer()),
    2913       40476 :       table_ptr, jsgraph()->IntPtrConstant(0), *effect_, *control_);
    2914       13492 :   *effect_ = table;
    2915             : 
    2916       13492 :   if (!wasm::IsJSCompatibleSignature(sig_)) {
    2917             :     // Throw a TypeError.
    2918             :     Node* native_context = LoadNativeContext(table);
    2919             :     BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError, native_context,
    2920          50 :                                   nullptr, 0);
    2921             :     // We don't need to return a value here, as the runtime call will not return
    2922             :     // anyway (the c entry stub will trigger stack unwinding).
    2923             :     ReturnVoid();
    2924          50 :     return false;
    2925             :   }
    2926             : 
    2927       13442 :   Node** args = Buffer(wasm_count + 7);
    2928             : 
    2929             :   Node* call = nullptr;
    2930             : 
    2931       13442 :   BuildModifyThreadInWasmFlag(false);
    2932             : 
    2933       13442 :   if (target->IsJSFunction()) {
    2934             :     Handle<JSFunction> function = Handle<JSFunction>::cast(target);
    2935       11492 :     if (function->shared()->internal_formal_parameter_count() == wasm_count) {
    2936             :       int pos = 0;
    2937             :       args[pos++] =
    2938        8490 :           LoadImportData(index, kFunction, table);  // target callable.
    2939             :       // Receiver.
    2940       16930 :       if (is_sloppy(function->shared()->language_mode()) &&
    2941             :           !function->shared()->native()) {
    2942        8440 :         args[pos++] = LoadImportData(index, kGlobalProxy, table);
    2943             :       } else {
    2944             :         args[pos++] = jsgraph()->Constant(
    2945         100 :             handle(isolate->heap()->undefined_value(), isolate));
    2946             :       }
    2947             : 
    2948             :       desc = Linkage::GetJSCallDescriptor(
    2949       16980 :           graph()->zone(), false, wasm_count + 1, CallDescriptor::kNoFlags);
    2950             : 
    2951             :       // Convert wasm numbers to JS values.
    2952        8490 :       pos = AddParameterNodes(args, pos, wasm_count, sig_);
    2953             : 
    2954       16980 :       args[pos++] = jsgraph()->UndefinedConstant();        // new target
    2955       16980 :       args[pos++] = jsgraph()->Int32Constant(wasm_count);  // argument count
    2956       16980 :       args[pos++] = LoadImportData(index, kFunctionContext, table);
    2957        8490 :       args[pos++] = *effect_;
    2958        8490 :       args[pos++] = *control_;
    2959             : 
    2960       16980 :       call = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args);
    2961             :     }
    2962             :   }
    2963             : 
    2964             :   // We cannot call the target directly, we have to use the Call builtin.
    2965             :   Node* native_context = nullptr;
    2966       13442 :   if (!call) {
    2967             :     int pos = 0;
    2968        4952 :     Callable callable = CodeFactory::Call(isolate);
    2969        4952 :     args[pos++] = jsgraph()->HeapConstant(callable.code());
    2970        4952 :     args[pos++] = LoadImportData(index, kFunction, table);  // target callable.
    2971        4952 :     args[pos++] = jsgraph()->Int32Constant(wasm_count);  // argument count
    2972             :     args[pos++] = jsgraph()->Constant(
    2973        9904 :         handle(isolate->heap()->undefined_value(), isolate));  // receiver
    2974             : 
    2975             :     desc = Linkage::GetStubCallDescriptor(isolate, graph()->zone(),
    2976             :                                           callable.descriptor(), wasm_count + 1,
    2977       14856 :                                           CallDescriptor::kNoFlags);
    2978             : 
    2979             :     // Convert wasm numbers to JS values.
    2980        4952 :     pos = AddParameterNodes(args, pos, wasm_count, sig_);
    2981             : 
    2982             :     // The native_context is sufficient here, because all kind of callables
    2983             :     // which depend on the context provide their own context. The context here
    2984             :     // is only needed if the target is a constructor to throw a TypeError, if
    2985             :     // the target is a native function, or if the target is a callable JSObject,
    2986             :     // which can only be constructed by the runtime.
    2987             :     native_context = LoadNativeContext(table);
    2988        4952 :     args[pos++] = native_context;
    2989        4952 :     args[pos++] = *effect_;
    2990        4952 :     args[pos++] = *control_;
    2991             : 
    2992        9904 :     call = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args);
    2993             :   }
    2994             : 
    2995       13442 :   *effect_ = call;
    2996       13442 :   SetSourcePosition(call, 0);
    2997             : 
    2998       13442 :   BuildModifyThreadInWasmFlag(true);
    2999             : 
    3000             :   // Convert the return value back.
    3001       13442 :   Node* val = sig_->return_count() == 0
    3002             :                   ? jsgraph()->Int32Constant(0)
    3003             :                   : FromJS(call,
    3004             :                            native_context != nullptr ? native_context
    3005             :                                                      : LoadNativeContext(table),
    3006       34542 :                            sig_->GetReturn());
    3007             :   Return(val);
    3008       13442 :   return true;
    3009             : }
    3010             : 
    3011             : namespace {
    3012             : bool HasInt64ParamOrReturn(wasm::FunctionSig* sig) {
    3013      741918 :   for (auto type : sig->all()) {
    3014      375623 :     if (type == wasm::kWasmI64) return true;
    3015             :   }
    3016             :   return false;
    3017             : }
    3018             : }  // namespace
    3019             : 
    3020      135895 : void WasmGraphBuilder::BuildWasmToWasmWrapper(Handle<Code> target,
    3021      679475 :                                               Address new_context_address) {
    3022      135895 :   int wasm_count = static_cast<int>(sig_->parameter_count());
    3023      135895 :   int count = wasm_count + 4;  // wasm_code, wasm_context, effect, and control.
    3024      135895 :   Node** args = Buffer(count);
    3025             : 
    3026             :   // Build the start node.
    3027      135895 :   Node* start = Start(count + 1);
    3028      135895 :   *control_ = start;
    3029      135895 :   *effect_ = start;
    3030             : 
    3031             :   int pos = 0;
    3032             :   // Add the wasm code target.
    3033      135895 :   args[pos++] = jsgraph()->HeapConstant(target);
    3034             :   // Add the wasm_context of the other instance.
    3035             :   args[pos++] = jsgraph()->IntPtrConstant(
    3036      271790 :       reinterpret_cast<uintptr_t>(new_context_address));
    3037             :   // Add the parameters starting from index 1 since the parameter with index 0
    3038             :   // is the old wasm_context.
    3039      521190 :   for (int i = 0; i < wasm_count; ++i) {
    3040      249400 :     args[pos++] = Param(i + 1);
    3041             :   }
    3042      135895 :   args[pos++] = *effect_;
    3043      135895 :   args[pos++] = *control_;
    3044             : 
    3045             :   // Tail-call the wasm code.
    3046      271790 :   CallDescriptor* desc = GetWasmCallDescriptor(jsgraph()->zone(), sig_, true);
    3047             :   Node* tail_call =
    3048      271790 :       graph()->NewNode(jsgraph()->common()->TailCall(desc), count, args);
    3049      135895 :   MergeControlToEnd(jsgraph(), tail_call);
    3050      135895 : }
    3051             : 
    3052        1125 : void WasmGraphBuilder::BuildWasmInterpreterEntry(
    3053        4293 :     uint32_t func_index, Handle<WasmInstanceObject> instance) {
    3054        4191 :   int param_count = static_cast<int>(sig_->parameter_count());
    3055             : 
    3056             :   // Build the start and the parameter nodes.
    3057        1125 :   Node* start = Start(param_count + 3);
    3058        1125 :   *effect_ = start;
    3059        1125 :   *control_ = start;
    3060             : 
    3061             :   // Compute size for the argument buffer.
    3062        1125 :   int args_size_bytes = 0;
    3063        3273 :   for (wasm::ValueType type : sig_->parameters()) {
    3064        1023 :     args_size_bytes += 1 << ElementSizeLog2Of(type);
    3065             :   }
    3066             : 
    3067             :   // The return value is also passed via this buffer:
    3068             :   DCHECK_GE(wasm::kV8MaxWasmFunctionReturns, sig_->return_count());
    3069             :   // TODO(wasm): Handle multi-value returns.
    3070             :   DCHECK_EQ(1, wasm::kV8MaxWasmFunctionReturns);
    3071             :   int return_size_bytes =
    3072        2043 :       sig_->return_count() == 0 ? 0 : 1 << ElementSizeLog2Of(sig_->GetReturn());
    3073             : 
    3074             :   // Get a stack slot for the arguments.
    3075             :   Node* arg_buffer =
    3076        1125 :       args_size_bytes == 0 && return_size_bytes == 0
    3077             :           ? jsgraph()->IntPtrConstant(0)
    3078             :           : graph()->NewNode(jsgraph()->machine()->StackSlot(
    3079        3279 :                 std::max(args_size_bytes, return_size_bytes), 8));
    3080             : 
    3081             :   // Now store all our arguments to the buffer.
    3082             :   int offset = 0;
    3083             : 
    3084        3273 :   for (int i = 0; i < param_count; ++i) {
    3085        1023 :     wasm::ValueType type = sig_->GetParam(i);
    3086             :     // Start from the parameter with index 1 to drop the wasm_context.
    3087             :     *effect_ = graph()->NewNode(GetSafeStoreOperator(offset, type), arg_buffer,
    3088        1023 :                                 Int32Constant(offset), Param(i + 1), *effect_,
    3089        4092 :                                 *control_);
    3090        1023 :     offset += 1 << ElementSizeLog2Of(type);
    3091             :   }
    3092             :   DCHECK_EQ(args_size_bytes, offset);
    3093             : 
    3094             :   // We are passing the raw arg_buffer here. To the GC and other parts, it looks
    3095             :   // like a Smi (lowest bit not set). In the runtime function however, don't
    3096             :   // call Smi::value on it, but just cast it to a byte pointer.
    3097             :   Node* parameters[] = {
    3098        2250 :       jsgraph()->HeapConstant(instance),   // wasm instance
    3099        1125 :       jsgraph()->SmiConstant(func_index),  // function index
    3100             :       arg_buffer,                          // argument buffer
    3101        2250 :   };
    3102             :   BuildCallToRuntime(Runtime::kWasmRunInterpreter, parameters,
    3103        1125 :                      arraysize(parameters));
    3104             : 
    3105             :   // Read back the return value.
    3106        2250 :   if (sig_->return_count() == 0) {
    3107             :     Return(Int32Constant(0));
    3108             :   } else {
    3109             :     // TODO(wasm): Implement multi-return.
    3110             :     DCHECK_EQ(1, sig_->return_count());
    3111         918 :     MachineType load_rep = wasm::WasmOpcodes::MachineTypeFor(sig_->GetReturn());
    3112             :     Node* val =
    3113             :         graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer,
    3114        1836 :                          Int32Constant(0), *effect_, *control_);
    3115             :     Return(val);
    3116             :   }
    3117             : 
    3118        2250 :   if (HasInt64ParamOrReturn(sig_)) LowerInt64();
    3119        1125 : }
    3120             : 
    3121         672 : void WasmGraphBuilder::BuildCWasmEntry(Address wasm_context_address) {
    3122             :   // Build the start and the JS parameter nodes.
    3123          96 :   Node* start = Start(CWasmEntryParameters::kNumParameters + 5);
    3124          96 :   *control_ = start;
    3125          96 :   *effect_ = start;
    3126             : 
    3127             :   // Create the wasm_context node to pass as parameter.
    3128             :   DCHECK_NULL(wasm_context_);
    3129             :   wasm_context_ = jsgraph()->IntPtrConstant(
    3130         192 :       reinterpret_cast<uintptr_t>(wasm_context_address));
    3131             : 
    3132             :   // Create parameter nodes (offset by 1 for the receiver parameter).
    3133          96 :   Node* code_obj = Param(CWasmEntryParameters::kCodeObject + 1);
    3134          96 :   Node* arg_buffer = Param(CWasmEntryParameters::kArgumentsBuffer + 1);
    3135             : 
    3136         288 :   int wasm_arg_count = static_cast<int>(sig_->parameter_count());
    3137          96 :   int arg_count = wasm_arg_count + 4;  // code, wasm_context, control, effect
    3138          96 :   Node** args = Buffer(arg_count);
    3139             : 
    3140             :   int pos = 0;
    3141          96 :   args[pos++] = code_obj;
    3142          96 :   args[pos++] = wasm_context_;
    3143             : 
    3144             :   int offset = 0;
    3145         312 :   for (wasm::ValueType type : sig_->parameters()) {
    3146             :     Node* arg_load =
    3147             :         graph()->NewNode(GetSafeLoadOperator(offset, type), arg_buffer,
    3148         240 :                          Int32Constant(offset), *effect_, *control_);
    3149         120 :     *effect_ = arg_load;
    3150         120 :     args[pos++] = arg_load;
    3151         120 :     offset += 1 << ElementSizeLog2Of(type);
    3152             :   }
    3153             : 
    3154          96 :   args[pos++] = *effect_;
    3155          96 :   args[pos++] = *control_;
    3156             :   DCHECK_EQ(arg_count, pos);
    3157             : 
    3158             :   // Call the wasm code.
    3159         192 :   CallDescriptor* desc = GetWasmCallDescriptor(jsgraph()->zone(), sig_);
    3160             : 
    3161             :   Node* call =
    3162         192 :       graph()->NewNode(jsgraph()->common()->Call(desc), arg_count, args);
    3163          96 :   *effect_ = call;
    3164             : 
    3165             :   // Store the return value.
    3166             :   DCHECK_GE(1, sig_->return_count());
    3167         192 :   if (sig_->return_count() == 1) {
    3168             :     StoreRepresentation store_rep(sig_->GetReturn(), kNoWriteBarrier);
    3169             :     Node* store =
    3170             :         graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer,
    3171         192 :                          Int32Constant(0), call, *effect_, *control_);
    3172          96 :     *effect_ = store;
    3173             :   }
    3174             :   Return(jsgraph()->SmiConstant(0));
    3175             : 
    3176         192 :   if (jsgraph()->machine()->Is32() && HasInt64ParamOrReturn(sig_)) {
    3177             :     MachineRepresentation sig_reps[] = {
    3178             :         MachineRepresentation::kWord32,  // return value
    3179             :         MachineRepresentation::kTagged,  // receiver
    3180             :         MachineRepresentation::kTagged,  // arg0 (code)
    3181             :         MachineRepresentation::kTagged   // arg1 (buffer)
    3182           0 :     };
    3183             :     wasm::FunctionSig c_entry_sig(1, 2, sig_reps);
    3184             :     Int64Lowering r(jsgraph()->graph(), jsgraph()->machine(),
    3185           0 :                     jsgraph()->common(), jsgraph()->zone(), &c_entry_sig);
    3186           0 :     r.LowerGraph();
    3187             :   }
    3188          96 : }
    3189             : 
    3190             : // This function is used by WasmFullDecoder to create a node that loads the
    3191             : // {mem_start} variable from the WasmContext. It should not be used directly by
    3192             : // the WasmGraphBuilder. The WasmGraphBuilder should directly use {mem_start_},
    3193             : // which will always contain the correct node (stored in the SsaEnv).
    3194     1233891 : Node* WasmGraphBuilder::LoadMemStart() {
    3195             :   DCHECK_NOT_NULL(wasm_context_);
    3196             :   Node* mem_buffer = graph()->NewNode(
    3197             :       jsgraph()->machine()->Load(MachineType::UintPtr()), wasm_context_,
    3198             :       jsgraph()->Int32Constant(
    3199             :           static_cast<int32_t>(offsetof(WasmContext, mem_start))),
    3200     1233891 :       *effect_, *control_);
    3201      411370 :   *effect_ = mem_buffer;
    3202      411370 :   return mem_buffer;
    3203             : }
    3204             : 
    3205             : // This function is used by WasmFullDecoder to create a node that loads the
    3206             : // {mem_size} variable from the WasmContext. It should not be used directly by
    3207             : // the WasmGraphBuilder. The WasmGraphBuilder should directly use {mem_size_},
    3208             : // which will always contain the correct node (stored in the SsaEnv).
    3209     1645286 : Node* WasmGraphBuilder::LoadMemSize() {
    3210             :   // Load mem_size from the WasmContext at runtime.
    3211             :   DCHECK_NOT_NULL(wasm_context_);
    3212             :   Node* mem_size = graph()->NewNode(
    3213             :       jsgraph()->machine()->Load(MachineType::Uint32()), wasm_context_,
    3214             :       jsgraph()->Int32Constant(
    3215             :           static_cast<int32_t>(offsetof(WasmContext, mem_size))),
    3216     1233929 :       *effect_, *control_);
    3217      411357 :   *effect_ = mem_size;
    3218      822714 :   if (jsgraph()->machine()->Is64()) {
    3219             :     mem_size = graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(),
    3220      411308 :                                 mem_size);
    3221             :   }
    3222      411367 :   return mem_size;
    3223             : }
    3224             : 
    3225       31608 : void WasmGraphBuilder::GetGlobalBaseAndOffset(MachineType mem_type,
    3226             :                                               uint32_t offset, Node** base_node,
    3227       36651 :                                               Node** offset_node) {
    3228             :   DCHECK_NOT_NULL(wasm_context_);
    3229       31608 :   if (globals_start_ == nullptr) {
    3230             :     // Load globals_start from the WasmContext at runtime.
    3231             :     // TODO(wasm): we currently generate only one load of the {globals_start}
    3232             :     // start per graph, which means it can be placed anywhere by the scheduler.
    3233             :     // This is legal because the globals_start should never change.
    3234             :     // However, in some cases (e.g. if the WasmContext is already in a
    3235             :     // register), it is slightly more efficient to reload this value from the
    3236             :     // WasmContext. Since this depends on register allocation, it is not
    3237             :     // possible to express in the graph, and would essentially constitute a
    3238             :     // "mem2reg" optimization in TurboFan.
    3239             :     globals_start_ = graph()->NewNode(
    3240             :         jsgraph()->machine()->Load(MachineType::UintPtr()), wasm_context_,
    3241             :         jsgraph()->Int32Constant(
    3242             :             static_cast<int32_t>(offsetof(WasmContext, globals_start))),
    3243       14261 :         graph()->start(), graph()->start());
    3244             :   }
    3245       31609 :   *base_node = globals_start_;
    3246       63218 :   *offset_node = jsgraph()->Int32Constant(offset);
    3247             : 
    3248       31607 :   if (mem_type == MachineType::Simd128() && offset != 0) {
    3249             :     // TODO(titzer,bbudge): code generation for SIMD memory offsets is broken.
    3250             :     *base_node =
    3251             :         graph()->NewNode(kPointerSize == 4 ? jsgraph()->machine()->Int32Add()
    3252             :                                            : jsgraph()->machine()->Int64Add(),
    3253         432 :                          *base_node, *offset_node);
    3254         144 :     *offset_node = jsgraph()->Int32Constant(0);
    3255             :   }
    3256       31607 : }
    3257             : 
    3258       98396 : Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
    3259             :   DCHECK_NOT_NULL(*mem_start_);
    3260       48144 :   if (offset == 0) return *mem_start_;
    3261             :   return graph()->NewNode(jsgraph()->machine()->IntAdd(), *mem_start_,
    3262      100504 :                           jsgraph()->IntPtrConstant(offset));
    3263             : }
    3264             : 
    3265        2272 : Node* WasmGraphBuilder::CurrentMemoryPages() {
    3266             :   // CurrentMemoryPages can not be called from asm.js.
    3267             :   DCHECK_EQ(wasm::kWasmOrigin, env_->module->origin());
    3268             :   DCHECK_NOT_NULL(*mem_size_);
    3269         568 :   Node* mem_size = *mem_size_;
    3270        1136 :   if (jsgraph()->machine()->Is64()) {
    3271             :     mem_size = graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(),
    3272         568 :                                 mem_size);
    3273             :   }
    3274             :   return graph()->NewNode(
    3275             :       jsgraph()->machine()->Word32Shr(), mem_size,
    3276        2272 :       jsgraph()->Int32Constant(WhichPowerOf2(wasm::WasmModule::kPageSize)));
    3277             : }
    3278             : 
    3279       10259 : void WasmGraphBuilder::EnsureFunctionTableNodes() {
    3280        9870 :   if (function_tables_.size() > 0) return;
    3281        4646 :   size_t tables_size = env_->function_tables.size();
    3282        4646 :   for (size_t i = 0; i < tables_size; ++i) {
    3283             :     wasm::GlobalHandleAddress function_handle_address =
    3284        4646 :         env_->function_tables[i];
    3285             :     wasm::GlobalHandleAddress signature_handle_address =
    3286        4646 :         env_->signature_tables[i];
    3287             :     function_tables_.push_back(jsgraph()->RelocatableIntPtrConstant(
    3288             :         reinterpret_cast<intptr_t>(function_handle_address),
    3289        6969 :         RelocInfo::WASM_GLOBAL_HANDLE));
    3290             :     signature_tables_.push_back(jsgraph()->RelocatableIntPtrConstant(
    3291             :         reinterpret_cast<intptr_t>(signature_handle_address),
    3292        6969 :         RelocInfo::WASM_GLOBAL_HANDLE));
    3293        4646 :     uint32_t table_size = env_->module->function_tables[i].initial_size;
    3294             :     function_table_sizes_.push_back(jsgraph()->RelocatableInt32Constant(
    3295             :         static_cast<uint32_t>(table_size),
    3296        6969 :         RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE));
    3297             :   }
    3298             : }
    3299             : 
    3300      452868 : Node* WasmGraphBuilder::BuildModifyThreadInWasmFlag(bool new_value) {
    3301             :   // TODO(eholk): generate code to modify the thread-local storage directly,
    3302             :   // rather than calling the runtime.
    3303      345516 :   if (!trap_handler::UseTrapHandler()) {
    3304      309732 :     return *control_;
    3305             :   }
    3306             : 
    3307             :   // Using two functions instead of taking the new value as a parameter saves
    3308             :   // one instruction on each call to set up the parameter.
    3309             :   ExternalReference ref =
    3310             :       new_value ? ExternalReference::wasm_set_thread_in_wasm_flag(
    3311       17892 :                       jsgraph()->isolate())
    3312             :                 : ExternalReference::wasm_clear_thread_in_wasm_flag(
    3313       71568 :                       jsgraph()->isolate());
    3314             :   MachineSignature::Builder sig_builder(jsgraph()->zone(), 0, 0);
    3315             :   return BuildCCall(
    3316             :       sig_builder.Build(),
    3317       71568 :       graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)));
    3318             : }
    3319             : 
    3320             : // Only call this function for code which is not reused across instantiations,
    3321             : // as we do not patch the embedded js_context.
    3322        4018 : Node* WasmGraphBuilder::BuildCallToRuntimeWithContext(Runtime::FunctionId f,
    3323             :                                                       Node* js_context,
    3324             :                                                       Node** parameters,
    3325       24120 :                                                       int parameter_count) {
    3326        4018 :   const Runtime::Function* fun = Runtime::FunctionForId(f);
    3327             :   CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
    3328             :       jsgraph()->zone(), f, fun->nargs, Operator::kNoProperties,
    3329        8038 :       CallDescriptor::kNoFlags);
    3330             :   // CEntryStubConstant nodes have to be created and cached in the main
    3331             :   // thread. At the moment this is only done for CEntryStubConstant(1).
    3332             :   DCHECK_EQ(1, fun->result_size);
    3333             :   // At the moment we only allow 4 parameters. If more parameters are needed,
    3334             :   // increase this constant accordingly.
    3335             :   static const int kMaxParams = 4;
    3336             :   DCHECK_GE(kMaxParams, parameter_count);
    3337             :   Node* inputs[kMaxParams + 6];
    3338             :   int count = 0;
    3339        4021 :   inputs[count++] = centry_stub_node_;
    3340        9702 :   for (int i = 0; i < parameter_count; i++) {
    3341        5681 :     inputs[count++] = parameters[i];
    3342             :   }
    3343        4021 :   inputs[count++] = jsgraph()->ExternalConstant(
    3344        8041 :       ExternalReference(f, jsgraph()->isolate()));         // ref
    3345        8040 :   inputs[count++] = jsgraph()->Int32Constant(fun->nargs);  // arity
    3346        4020 :   inputs[count++] = js_context;                            // js_context
    3347        4020 :   inputs[count++] = *effect_;
    3348        4020 :   inputs[count++] = *control_;
    3349             : 
    3350             :   Node* node = jsgraph()->graph()->NewNode(jsgraph()->common()->Call(desc),
    3351        8040 :                                            count, inputs);
    3352        4021 :   *effect_ = node;
    3353             : 
    3354        4021 :   return node;
    3355             : }
    3356             : 
    3357        3108 : Node* WasmGraphBuilder::BuildCallToRuntime(Runtime::FunctionId f,
    3358             :                                            Node** parameters,
    3359        3108 :                                            int parameter_count) {
    3360             :   return BuildCallToRuntimeWithContext(f, jsgraph()->NoContextConstant(),
    3361        3110 :                                        parameters, parameter_count);
    3362             : }
    3363             : 
    3364       39324 : Node* WasmGraphBuilder::GetGlobal(uint32_t index) {
    3365             :   MachineType mem_type =
    3366       58983 :       wasm::WasmOpcodes::MachineTypeFor(env_->module->globals[index].type);
    3367       19661 :   Node* base = nullptr;
    3368       19661 :   Node* offset = nullptr;
    3369       19661 :   GetGlobalBaseAndOffset(mem_type, env_->module->globals[index].offset, &base,
    3370       19661 :                          &offset);
    3371             :   Node* node = graph()->NewNode(jsgraph()->machine()->Load(mem_type), base,
    3372       39326 :                                 offset, *effect_, *control_);
    3373       19662 :   *effect_ = node;
    3374       19662 :   return node;
    3375             : }
    3376             : 
    3377       23891 : Node* WasmGraphBuilder::SetGlobal(uint32_t index, Node* val) {
    3378             :   MachineType mem_type =
    3379       35836 :       wasm::WasmOpcodes::MachineTypeFor(env_->module->globals[index].type);
    3380       11946 :   Node* base = nullptr;
    3381       11946 :   Node* offset = nullptr;
    3382       11946 :   GetGlobalBaseAndOffset(mem_type, env_->module->globals[index].offset, &base,
    3383       11946 :                          &offset);
    3384             :   const Operator* op = jsgraph()->machine()->Store(
    3385       23892 :       StoreRepresentation(mem_type.representation(), kNoWriteBarrier));
    3386       11945 :   Node* node = graph()->NewNode(op, base, offset, val, *effect_, *control_);
    3387       11945 :   *effect_ = node;
    3388       11945 :   return node;
    3389             : }
    3390             : 
    3391       85691 : void WasmGraphBuilder::BoundsCheckMem(MachineType memtype, Node* index,
    3392             :                                       uint32_t offset,
    3393      161496 :                                       wasm::WasmCodePosition position) {
    3394       42843 :   if (FLAG_wasm_no_bounds_checks) return;
    3395             :   DCHECK_NOT_NULL(*mem_size_);
    3396             : 
    3397       42848 :   uint32_t min_size = env_->module->initial_pages * wasm::WasmModule::kPageSize;
    3398             :   uint32_t max_size =
    3399             :       (env_->module->has_maximum_pages ? env_->module->maximum_pages
    3400             :                                        : wasm::kV8MaxWasmMemoryPages) *
    3401       42848 :       wasm::WasmModule::kPageSize;
    3402             : 
    3403             :   byte access_size = wasm::WasmOpcodes::MemSize(memtype);
    3404             : 
    3405       42850 :   if (access_size > max_size || offset > max_size - access_size) {
    3406             :     // The access will be out of bounds, even for the largest memory.
    3407             :     TrapIfEq32(wasm::kTrapMemOutOfBounds, jsgraph()->Int32Constant(0), 0,
    3408          42 :                position);
    3409          47 :     return;
    3410             :   }
    3411       42808 :   uint32_t end_offset = offset + access_size;
    3412             : 
    3413       42808 :   if (end_offset > min_size) {
    3414             :     // The end offset is larger than the smallest memory.
    3415             :     // Dynamically check the end offset against the actual memory size, which
    3416             :     // is not known at compile time.
    3417             :     Node* cond;
    3418       33196 :     if (jsgraph()->machine()->Is32()) {
    3419             :       cond = graph()->NewNode(jsgraph()->machine()->Uint32LessThanOrEqual(),
    3420           0 :                               jsgraph()->Int32Constant(end_offset), *mem_size_);
    3421             :     } else {
    3422             :       cond = graph()->NewNode(
    3423             :           jsgraph()->machine()->Uint64LessThanOrEqual(),
    3424             :           jsgraph()->Int64Constant(static_cast<int64_t>(end_offset)),
    3425       33194 :           *mem_size_);
    3426             :     }
    3427       16597 :     TrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position);
    3428             :   } else {
    3429             :     // The end offset is within the bounds of the smallest memory, so only
    3430             :     // one check is required. Check to see if the index is also a constant.
    3431             :     UintPtrMatcher m(index);
    3432       26210 :     if (m.HasValue()) {
    3433             :       uint64_t index_val = m.Value();
    3434          52 :       if ((index_val + offset + access_size) <= min_size) {
    3435             :         // The input index is a constant and everything is statically within
    3436             :         // bounds of the smallest possible memory.
    3437             :         return;
    3438             :       }
    3439             :     }
    3440             :   }
    3441             : 
    3442             :   Node* effective_size;
    3443       85508 :   if (jsgraph()->machine()->Is32()) {
    3444             :     effective_size =
    3445             :         graph()->NewNode(jsgraph()->machine()->Int32Sub(), *mem_size_,
    3446           0 :                          jsgraph()->Int32Constant(end_offset - 1));
    3447             :   } else {
    3448             :     effective_size = graph()->NewNode(
    3449             :         jsgraph()->machine()->Int64Sub(), *mem_size_,
    3450       85509 :         jsgraph()->Int64Constant(static_cast<int64_t>(end_offset - 1)));
    3451             :   }
    3452             : 
    3453       42751 :   const Operator* less = jsgraph()->machine()->Is32()
    3454             :                              ? jsgraph()->machine()->Uint32LessThan()
    3455       42751 :                              : jsgraph()->machine()->Uint64LessThan();
    3456             : 
    3457             :   Node* cond = graph()->NewNode(less, index, effective_size);
    3458       42755 :   TrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position);
    3459             : }
    3460             : 
    3461         120 : const Operator* WasmGraphBuilder::GetSafeLoadOperator(int offset,
    3462         126 :                                                       wasm::ValueType type) {
    3463         120 :   int alignment = offset % (1 << ElementSizeLog2Of(type));
    3464         120 :   MachineType mach_type = wasm::WasmOpcodes::MachineTypeFor(type);
    3465         132 :   if (alignment == 0 || jsgraph()->machine()->UnalignedLoadSupported(type)) {
    3466         120 :     return jsgraph()->machine()->Load(mach_type);
    3467             :   }
    3468           0 :   return jsgraph()->machine()->UnalignedLoad(mach_type);
    3469             : }
    3470             : 
    3471        1023 : const Operator* WasmGraphBuilder::GetSafeStoreOperator(int offset,
    3472        1039 :                                                        wasm::ValueType type) {
    3473        1023 :   int alignment = offset % (1 << ElementSizeLog2Of(type));
    3474        1055 :   if (alignment == 0 || jsgraph()->machine()->UnalignedStoreSupported(type)) {
    3475             :     StoreRepresentation rep(type, WriteBarrierKind::kNoWriteBarrier);
    3476        1023 :     return jsgraph()->machine()->Store(rep);
    3477             :   }
    3478             :   UnalignedStoreRepresentation rep(type);
    3479           0 :   return jsgraph()->machine()->UnalignedStore(rep);
    3480             : }
    3481             : 
    3482          55 : Node* WasmGraphBuilder::TraceMemoryOperation(bool is_store,
    3483             :                                              MachineRepresentation rep,
    3484             :                                              Node* index, uint32_t offset,
    3485         293 :                                              wasm::WasmCodePosition position) {
    3486             :   Node* address = graph()->NewNode(jsgraph()->machine()->Int32Add(),
    3487         112 :                                    Int32Constant(offset), index);
    3488             :   Node* addr_low = BuildChangeInt32ToSmi(graph()->NewNode(
    3489         117 :       jsgraph()->machine()->Word32And(), address, Int32Constant(0xffff)));
    3490             :   Node* addr_high = BuildChangeInt32ToSmi(graph()->NewNode(
    3491         118 :       jsgraph()->machine()->Word32Shr(), address, Int32Constant(16)));
    3492             :   int32_t rep_i = static_cast<int32_t>(rep);
    3493             :   Node* params[] = {
    3494          60 :       jsgraph()->SmiConstant(is_store),  // is_store
    3495             :       jsgraph()->SmiConstant(rep_i),     // mem rep
    3496             :       addr_low,                          // address lower half word
    3497             :       addr_high                          // address higher half word
    3498         119 :   };
    3499             :   Node* call =
    3500          59 :       BuildCallToRuntime(Runtime::kWasmTraceMemory, params, arraysize(params));
    3501          59 :   SetSourcePosition(call, position);
    3502          60 :   return call;
    3503             : }
    3504             : 
    3505       33073 : Node* WasmGraphBuilder::LoadMem(wasm::ValueType type, MachineType memtype,
    3506             :                                 Node* index, uint32_t offset,
    3507             :                                 uint32_t alignment,
    3508       95579 :                                 wasm::WasmCodePosition position) {
    3509             :   Node* load;
    3510             : 
    3511       66146 :   if (jsgraph()->machine()->Is64()) {
    3512             :     index =
    3513       33076 :         graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), index);
    3514             :   }
    3515             :   // Wasm semantics throw on OOB. Introduce explicit bounds check.
    3516       33076 :   if (!FLAG_wasm_trap_handler || !V8_TRAP_HANDLER_SUPPORTED) {
    3517       29313 :     BoundsCheckMem(memtype, index, offset, position);
    3518             :   }
    3519             : 
    3520       62219 :   if (memtype.representation() == MachineRepresentation::kWord8 ||
    3521       29137 :       jsgraph()->machine()->UnalignedLoadSupported(memtype.representation())) {
    3522       33082 :     if (trap_handler::UseTrapHandler()) {
    3523             :       load = graph()->NewNode(jsgraph()->machine()->ProtectedLoad(memtype),
    3524        7528 :                               MemBuffer(offset), index, *effect_, *control_);
    3525        3766 :       SetSourcePosition(load, position);
    3526             :     } else {
    3527             :       load = graph()->NewNode(jsgraph()->machine()->Load(memtype),
    3528       58631 :                               MemBuffer(offset), index, *effect_, *control_);
    3529             :     }
    3530             :   } else {
    3531             :     // TODO(eholk): Support unaligned loads with trap handlers.
    3532             :     DCHECK(!FLAG_wasm_trap_handler || !V8_TRAP_HANDLER_SUPPORTED);
    3533             :     load = graph()->NewNode(jsgraph()->machine()->UnalignedLoad(memtype),
    3534           0 :                             MemBuffer(offset), index, *effect_, *control_);
    3535             :   }
    3536             : 
    3537       33086 :   *effect_ = load;
    3538             : 
    3539             : #if defined(V8_TARGET_BIG_ENDIAN)
    3540             :   load = BuildChangeEndiannessLoad(load, memtype, type);
    3541             : #endif
    3542             : 
    3543       45809 :   if (type == wasm::kWasmI64 &&
    3544       12726 :       ElementSizeLog2Of(memtype.representation()) < 3) {
    3545             :     // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes.
    3546         292 :     if (memtype.IsSigned()) {
    3547             :       // sign extend
    3548         182 :       load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load);
    3549             :     } else {
    3550             :       // zero extend
    3551             :       load =
    3552         110 :           graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), load);
    3553             :     }
    3554             :   }
    3555             : 
    3556       33083 :   if (FLAG_wasm_trace_memory) {
    3557             :     TraceMemoryOperation(false, memtype.representation(), index, offset,
    3558          34 :                          position);
    3559             :   }
    3560             : 
    3561       33085 :   return load;
    3562             : }
    3563             : 
    3564       14561 : Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index,
    3565             :                                  uint32_t offset, uint32_t alignment, Node* val,
    3566             :                                  wasm::WasmCodePosition position,
    3567       43052 :                                  wasm::ValueType type) {
    3568             :   Node* store;
    3569             : 
    3570       29122 :   if (jsgraph()->machine()->Is64()) {
    3571             :     index =
    3572       14563 :         graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), index);
    3573             :   }
    3574             :   // Wasm semantics throw on OOB. Introduce explicit bounds check.
    3575       14564 :   if (!FLAG_wasm_trap_handler || !V8_TRAP_HANDLER_SUPPORTED) {
    3576       13028 :     BoundsCheckMem(memtype, index, offset, position);
    3577             :   }
    3578             : 
    3579             : #if defined(V8_TARGET_BIG_ENDIAN)
    3580             :   val = BuildChangeEndiannessStore(val, memtype, type);
    3581             : #endif
    3582             : 
    3583       28494 :   if (memtype.representation() == MachineRepresentation::kWord8 ||
    3584       13924 :       jsgraph()->machine()->UnalignedStoreSupported(memtype.representation())) {
    3585       14570 :     if (FLAG_wasm_trap_handler && V8_TRAP_HANDLER_SUPPORTED) {
    3586             :       store = graph()->NewNode(
    3587             :           jsgraph()->machine()->ProtectedStore(memtype.representation()),
    3588        3070 :           MemBuffer(offset), index, val, *effect_, *control_);
    3589        1535 :       SetSourcePosition(store, position);
    3590             :     } else {
    3591             :       StoreRepresentation rep(memtype.representation(), kNoWriteBarrier);
    3592             :       store =
    3593             :           graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset),
    3594       26067 :                            index, val, *effect_, *control_);
    3595             :     }
    3596             :   } else {
    3597             :     // TODO(eholk): Support unaligned stores with trap handlers.
    3598             :     DCHECK(!FLAG_wasm_trap_handler || !V8_TRAP_HANDLER_SUPPORTED);
    3599             :     UnalignedStoreRepresentation rep(memtype.representation());
    3600             :     store =
    3601             :         graph()->NewNode(jsgraph()->machine()->UnalignedStore(rep),
    3602           0 :                          MemBuffer(offset), index, val, *effect_, *control_);
    3603             :   }
    3604             : 
    3605       14566 :   *effect_ = store;
    3606             : 
    3607       14566 :   if (FLAG_wasm_trace_memory) {
    3608             :     TraceMemoryOperation(true, memtype.representation(), index, offset,
    3609          23 :                          position);
    3610             :   }
    3611             : 
    3612       14567 :   return store;
    3613             : }
    3614             : 
    3615      151750 : Node* WasmGraphBuilder::BuildAsmjsLoadMem(MachineType type, Node* index) {
    3616             :   // TODO(turbofan): fold bounds checks for constant asm.js loads.
    3617             :   // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish).
    3618             :   DCHECK_NOT_NULL(*mem_size_);
    3619             :   DCHECK_NOT_NULL(*mem_start_);
    3620      151750 :   if (jsgraph()->machine()->Is64()) {
    3621             :     index =
    3622       75875 :         graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), index);
    3623             :   }
    3624       75875 :   const Operator* op = jsgraph()->machine()->CheckedLoad(type);
    3625             :   Node* load =
    3626       75875 :       graph()->NewNode(op, *mem_start_, index, *mem_size_, *effect_, *control_);
    3627       75875 :   *effect_ = load;
    3628       75875 :   return load;
    3629             : }
    3630             : 
    3631       53998 : Node* WasmGraphBuilder::BuildAsmjsStoreMem(MachineType type, Node* index,
    3632      107996 :                                            Node* val) {
    3633             :   // TODO(turbofan): fold bounds checks for constant asm.js stores.
    3634             :   // asm.js semantics use CheckedStore (i.e. ignore OOB writes).
    3635             :   DCHECK_NOT_NULL(*mem_size_);
    3636             :   DCHECK_NOT_NULL(*mem_start_);
    3637      107996 :   if (jsgraph()->machine()->Is64()) {
    3638             :     index =
    3639       53998 :         graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), index);
    3640             :   }
    3641             :   const Operator* op =
    3642      107996 :       jsgraph()->machine()->CheckedStore(type.representation());
    3643             :   Node* store = graph()->NewNode(op, *mem_start_, index, *mem_size_, val,
    3644       53998 :                                  *effect_, *control_);
    3645       53998 :   *effect_ = store;
    3646       53998 :   return val;
    3647             : }
    3648             : 
    3649           0 : void WasmGraphBuilder::PrintDebugName(Node* node) {
    3650           0 :   PrintF("#%d:%s", node->id(), node->op()->mnemonic());
    3651           0 : }
    3652             : 
    3653           0 : Node* WasmGraphBuilder::String(const char* string) {
    3654             :   return jsgraph()->Constant(
    3655           0 :       jsgraph()->isolate()->factory()->NewStringFromAsciiChecked(string));
    3656             : }
    3657             : 
    3658    12331108 : Graph* WasmGraphBuilder::graph() { return jsgraph()->graph(); }
    3659             : 
    3660      238008 : void WasmGraphBuilder::LowerInt64() {
    3661      714024 :   if (jsgraph()->machine()->Is64()) return;
    3662             :   Int64Lowering r(jsgraph()->graph(), jsgraph()->machine(), jsgraph()->common(),
    3663           0 :                   jsgraph()->zone(), sig_);
    3664           0 :   r.LowerGraph();
    3665             : }
    3666             : 
    3667           0 : void WasmGraphBuilder::SimdScalarLoweringForTesting() {
    3668           0 :   SimdScalarLowering(jsgraph(), sig_).LowerGraph();
    3669           0 : }
    3670             : 
    3671      635962 : void WasmGraphBuilder::SetSourcePosition(Node* node,
    3672             :                                          wasm::WasmCodePosition position) {
    3673             :   DCHECK_NE(position, wasm::kNoCodePosition);
    3674      635962 :   if (source_position_table_)
    3675      541298 :     source_position_table_->SetSourcePosition(node, SourcePosition(position));
    3676      635986 : }
    3677             : 
    3678        1992 : Node* WasmGraphBuilder::S128Zero() {
    3679         996 :   has_simd_ = true;
    3680        1992 :   return graph()->NewNode(jsgraph()->machine()->S128Zero());
    3681             : }
    3682             : 
    3683        5388 : Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) {
    3684        2694 :   has_simd_ = true;
    3685        2694 :   switch (opcode) {
    3686             :     case wasm::kExprF32x4Splat:
    3687           0 :       return graph()->NewNode(jsgraph()->machine()->F32x4Splat(), inputs[0]);
    3688             :     case wasm::kExprF32x4SConvertI32x4:
    3689             :       return graph()->NewNode(jsgraph()->machine()->F32x4SConvertI32x4(),
    3690           0 :                               inputs[0]);
    3691             :     case wasm::kExprF32x4UConvertI32x4:
    3692             :       return graph()->NewNode(jsgraph()->machine()->F32x4UConvertI32x4(),
    3693           0 :                               inputs[0]);
    3694             :     case wasm::kExprF32x4Abs:
    3695           0 :       return graph()->NewNode(jsgraph()->machine()->F32x4Abs(), inputs[0]);
    3696             :     case wasm::kExprF32x4Neg:
    3697           0 :       return graph()->NewNode(jsgraph()->machine()->F32x4Neg(), inputs[0]);
    3698             :     case wasm::kExprF32x4RecipApprox:
    3699             :       return graph()->NewNode(jsgraph()->machine()->F32x4RecipApprox(),
    3700           0 :                               inputs[0]);
    3701             :     case wasm::kExprF32x4RecipSqrtApprox:
    3702             :       return graph()->NewNode(jsgraph()->machine()->F32x4RecipSqrtApprox(),
    3703           0 :                               inputs[0]);
    3704             :     case wasm::kExprF32x4Add:
    3705             :       return graph()->NewNode(jsgraph()->machine()->F32x4Add(), inputs[0],
    3706           0 :                               inputs[1]);
    3707             :     case wasm::kExprF32x4AddHoriz:
    3708             :       return graph()->NewNode(jsgraph()->machine()->F32x4AddHoriz(), inputs[0],
    3709           0 :                               inputs[1]);
    3710             :     case wasm::kExprF32x4Sub:
    3711             :       return graph()->NewNode(jsgraph()->machine()->F32x4Sub(), inputs[0],
    3712           0 :                               inputs[1]);
    3713             :     case wasm::kExprF32x4Mul:
    3714             :       return graph()->NewNode(jsgraph()->machine()->F32x4Mul(), inputs[0],
    3715           0 :                               inputs[1]);
    3716             :     case wasm::kExprF32x4Min:
    3717             :       return graph()->NewNode(jsgraph()->machine()->F32x4Min(), inputs[0],
    3718           0 :                               inputs[1]);
    3719             :     case wasm::kExprF32x4Max:
    3720             :       return graph()->NewNode(jsgraph()->machine()->F32x4Max(), inputs[0],
    3721           0 :                               inputs[1]);
    3722             :     case wasm::kExprF32x4Eq:
    3723             :       return graph()->NewNode(jsgraph()->machine()->F32x4Eq(), inputs[0],
    3724           0 :                               inputs[1]);
    3725             :     case wasm::kExprF32x4Ne:
    3726             :       return graph()->NewNode(jsgraph()->machine()->F32x4Ne(), inputs[0],
    3727           0 :                               inputs[1]);
    3728             :     case wasm::kExprF32x4Lt:
    3729             :       return graph()->NewNode(jsgraph()->machine()->F32x4Lt(), inputs[0],
    3730           0 :                               inputs[1]);
    3731             :     case wasm::kExprF32x4Le:
    3732             :       return graph()->NewNode(jsgraph()->machine()->F32x4Le(), inputs[0],
    3733           0 :                               inputs[1]);
    3734             :     case wasm::kExprF32x4Gt:
    3735             :       return graph()->NewNode(jsgraph()->machine()->F32x4Lt(), inputs[1],
    3736           0 :                               inputs[0]);
    3737             :     case wasm::kExprF32x4Ge:
    3738             :       return graph()->NewNode(jsgraph()->machine()->F32x4Le(), inputs[1],
    3739           0 :                               inputs[0]);
    3740             :     case wasm::kExprI32x4Splat:
    3741        2016 :       return graph()->NewNode(jsgraph()->machine()->I32x4Splat(), inputs[0]);
    3742             :     case wasm::kExprI32x4SConvertF32x4:
    3743             :       return graph()->NewNode(jsgraph()->machine()->I32x4SConvertF32x4(),
    3744           0 :                               inputs[0]);
    3745             :     case wasm::kExprI32x4UConvertF32x4:
    3746             :       return graph()->NewNode(jsgraph()->machine()->I32x4UConvertF32x4(),
    3747           0 :                               inputs[0]);
    3748             :     case wasm::kExprI32x4SConvertI16x8Low:
    3749             :       return graph()->NewNode(jsgraph()->machine()->I32x4SConvertI16x8Low(),
    3750           0 :                               inputs[0]);
    3751             :     case wasm::kExprI32x4SConvertI16x8High:
    3752             :       return graph()->NewNode(jsgraph()->machine()->I32x4SConvertI16x8High(),
    3753           0 :                               inputs[0]);
    3754             :     case wasm::kExprI32x4Neg:
    3755          36 :       return graph()->NewNode(jsgraph()->machine()->I32x4Neg(), inputs[0]);
    3756             :     case wasm::kExprI32x4Add:
    3757             :       return graph()->NewNode(jsgraph()->machine()->I32x4Add(), inputs[0],
    3758          72 :                               inputs[1]);
    3759             :     case wasm::kExprI32x4AddHoriz:
    3760             :       return graph()->NewNode(jsgraph()->machine()->I32x4AddHoriz(), inputs[0],
    3761          18 :                               inputs[1]);
    3762             :     case wasm::kExprI32x4Sub:
    3763             :       return graph()->NewNode(jsgraph()->machine()->I32x4Sub(), inputs[0],
    3764          36 :                               inputs[1]);
    3765             :     case wasm::kExprI32x4Mul:
    3766             :       return graph()->NewNode(jsgraph()->machine()->I32x4Mul(), inputs[0],
    3767          36 :                               inputs[1]);
    3768             :     case wasm::kExprI32x4MinS:
    3769             :       return graph()->NewNode(jsgraph()->machine()->I32x4MinS(), inputs[0],
    3770          36 :                               inputs[1]);
    3771             :     case wasm::kExprI32x4MaxS:
    3772             :       return graph()->NewNode(jsgraph()->machine()->I32x4MaxS(), inputs[0],
    3773          36 :                               inputs[1]);
    3774             :     case wasm::kExprI32x4Eq:
    3775             :       return graph()->NewNode(jsgraph()->machine()->I32x4Eq(), inputs[0],
    3776          36 :                               inputs[1]);
    3777             :     case wasm::kExprI32x4Ne:
    3778             :       return graph()->NewNode(jsgraph()->machine()->I32x4Ne(), inputs[0],
    3779          54 :                               inputs[1]);
    3780             :     case wasm::kExprI32x4LtS:
    3781             :       return graph()->NewNode(jsgraph()->machine()->I32x4GtS(), inputs[1],
    3782          36 :                               inputs[0]);
    3783             :     case wasm::kExprI32x4LeS:
    3784             :       return graph()->NewNode(jsgraph()->machine()->I32x4GeS(), inputs[1],
    3785          36 :                               inputs[0]);
    3786             :     case wasm::kExprI32x4GtS:
    3787             :       return graph()->NewNode(jsgraph()->machine()->I32x4GtS(), inputs[0],
    3788          36 :                               inputs[1]);
    3789             :     case wasm::kExprI32x4GeS:
    3790             :       return graph()->NewNode(jsgraph()->machine()->I32x4GeS(), inputs[0],
    3791          36 :                               inputs[1]);
    3792             :     case wasm::kExprI32x4UConvertI16x8Low:
    3793             :       return graph()->NewNode(jsgraph()->machine()->I32x4UConvertI16x8Low(),
    3794           0 :                               inputs[0]);
    3795             :     case wasm::kExprI32x4UConvertI16x8High:
    3796             :       return graph()->NewNode(jsgraph()->machine()->I32x4UConvertI16x8High(),
    3797           0 :                               inputs[0]);
    3798             :     case wasm::kExprI32x4MinU:
    3799             :       return graph()->NewNode(jsgraph()->machine()->I32x4MinU(), inputs[0],
    3800          36 :                               inputs[1]);
    3801             :     case wasm::kExprI32x4MaxU:
    3802             :       return graph()->NewNode(jsgraph()->machine()->I32x4MaxU(), inputs[0],
    3803          36 :                               inputs[1]);
    3804             :     case wasm::kExprI32x4LtU:
    3805             :       return graph()->NewNode(jsgraph()->machine()->I32x4GtU(), inputs[1],
    3806          36 :                               inputs[0]);
    3807             :     case wasm::kExprI32x4LeU:
    3808             :       return graph()->NewNode(jsgraph()->machine()->I32x4GeU(), inputs[1],
    3809          36 :                               inputs[0]);
    3810             :     case wasm::kExprI32x4GtU:
    3811             :       return graph()->NewNode(jsgraph()->machine()->I32x4GtU(), inputs[0],
    3812          36 :                               inputs[1]);
    3813             :     case wasm::kExprI32x4GeU:
    3814             :       return graph()->NewNode(jsgraph()->machine()->I32x4GeU(), inputs[0],
    3815          36 :                               inputs[1]);
    3816             :     case wasm::kExprI16x8Splat:
    3817        1836 :       return graph()->NewNode(jsgraph()->machine()->I16x8Splat(), inputs[0]);
    3818             :     case wasm::kExprI16x8SConvertI8x16Low:
    3819             :       return graph()->NewNode(jsgraph()->machine()->I16x8SConvertI8x16Low(),
    3820           0 :                               inputs[0]);
    3821             :     case wasm::kExprI16x8SConvertI8x16High:
    3822             :       return graph()->NewNode(jsgraph()->machine()->I16x8SConvertI8x16High(),
    3823           0 :                               inputs[0]);
    3824             :     case wasm::kExprI16x8Neg:
    3825          36 :       return graph()->NewNode(jsgraph()->machine()->I16x8Neg(), inputs[0]);
    3826             :     case wasm::kExprI16x8SConvertI32x4:
    3827             :       return graph()->NewNode(jsgraph()->machine()->I16x8SConvertI32x4(),
    3828           0 :                               inputs[0], inputs[1]);
    3829             :     case wasm::kExprI16x8Add:
    3830             :       return graph()->NewNode(jsgraph()->machine()->I16x8Add(), inputs[0],
    3831          36 :                               inputs[1]);
    3832             :     case wasm::kExprI16x8AddSaturateS:
    3833             :       return graph()->NewNode(jsgraph()->machine()->I16x8AddSaturateS(),
    3834          36 :                               inputs[0], inputs[1]);
    3835             :     case wasm::kExprI16x8AddHoriz:
    3836             :       return graph()->NewNode(jsgraph()->machine()->I16x8AddHoriz(), inputs[0],
    3837          18 :                               inputs[1]);
    3838             :     case wasm::kExprI16x8Sub:
    3839             :       return graph()->NewNode(jsgraph()->machine()->I16x8Sub(), inputs[0],
    3840          36 :                               inputs[1]);
    3841             :     case wasm::kExprI16x8SubSaturateS:
    3842             :       return graph()->NewNode(jsgraph()->machine()->I16x8SubSaturateS(),
    3843          36 :                               inputs[0], inputs[1]);
    3844             :     case wasm::kExprI16x8Mul:
    3845             :       return graph()->NewNode(jsgraph()->machine()->I16x8Mul(), inputs[0],
    3846          36 :                               inputs[1]);
    3847             :     case wasm::kExprI16x8MinS:
    3848             :       return graph()->NewNode(jsgraph()->machine()->I16x8MinS(), inputs[0],
    3849          36 :                               inputs[1]);
    3850             :     case wasm::kExprI16x8MaxS:
    3851             :       return graph()->NewNode(jsgraph()->machine()->I16x8MaxS(), inputs[0],
    3852          36 :                               inputs[1]);
    3853             :     case wasm::kExprI16x8Eq:
    3854             :       return graph()->NewNode(jsgraph()->machine()->I16x8Eq(), inputs[0],
    3855          36 :                               inputs[1]);
    3856             :     case wasm::kExprI16x8Ne:
    3857             :       return graph()->NewNode(jsgraph()->machine()->I16x8Ne(), inputs[0],
    3858          54 :                               inputs[1]);
    3859             :     case wasm::kExprI16x8LtS:
    3860             :       return graph()->NewNode(jsgraph()->machine()->I16x8GtS(), inputs[1],
    3861          36 :                               inputs[0]);
    3862             :     case wasm::kExprI16x8LeS:
    3863             :       return graph()->NewNode(jsgraph()->machine()->I16x8GeS(), inputs[1],
    3864          36 :                               inputs[0]);
    3865             :     case wasm::kExprI16x8GtS:
    3866             :       return graph()->NewNode(jsgraph()->machine()->I16x8GtS(), inputs[0],
    3867          36 :                               inputs[1]);
    3868             :     case wasm::kExprI16x8GeS:
    3869             :       return graph()->NewNode(jsgraph()->machine()->I16x8GeS(), inputs[0],
    3870          36 :                               inputs[1]);
    3871             :     case wasm::kExprI16x8UConvertI8x16Low:
    3872             :       return graph()->NewNode(jsgraph()->machine()->I16x8UConvertI8x16Low(),
    3873           0 :                               inputs[0]);
    3874             :     case wasm::kExprI16x8UConvertI8x16High:
    3875             :       return graph()->NewNode(jsgraph()->machine()->I16x8UConvertI8x16High(),
    3876           0 :                               inputs[0]);
    3877             :     case wasm::kExprI16x8UConvertI32x4:
    3878             :       return graph()->NewNode(jsgraph()->machine()->I16x8UConvertI32x4(),
    3879           0 :                               inputs[0], inputs[1]);
    3880             :     case wasm::kExprI16x8AddSaturateU:
    3881             :       return graph()->NewNode(jsgraph()->machine()->I16x8AddSaturateU(),
    3882          36 :                               inputs[0], inputs[1]);
    3883             :     case wasm::kExprI16x8SubSaturateU:
    3884             :       return graph()->NewNode(jsgraph()->machine()->I16x8SubSaturateU(),
    3885          36 :                               inputs[0], inputs[1]);
    3886             :     case wasm::kExprI16x8MinU:
    3887             :       return graph()->NewNode(jsgraph()->machine()->I16x8MinU(), inputs[0],
    3888          36 :                               inputs[1]);
    3889             :     case wasm::kExprI16x8MaxU:
    3890             :       return graph()->NewNode(jsgraph()->machine()->I16x8MaxU(), inputs[0],
    3891          36 :                               inputs[1]);
    3892             :     case wasm::kExprI16x8LtU:
    3893             :       return graph()->NewNode(jsgraph()->machine()->I16x8GtU(), inputs[1],
    3894          36 :                               inputs[0]);
    3895             :     case wasm::kExprI16x8LeU:
    3896             :       return graph()->NewNode(jsgraph()->machine()->I16x8GeU(), inputs[1],
    3897          36 :                               inputs[0]);
    3898             :     case wasm::kExprI16x8GtU:
    3899             :       return graph()->NewNode(jsgraph()->machine()->I16x8GtU(), inputs[0],
    3900          36 :                               inputs[1]);
    3901             :     case wasm::kExprI16x8GeU:
    3902             :       return graph()->NewNode(jsgraph()->machine()->I16x8GeU(), inputs[0],
    3903          36 :                               inputs[1]);
    3904             :     case wasm::kExprI8x16Splat:
    3905        1656 :       return graph()->NewNode(jsgraph()->machine()->I8x16Splat(), inputs[0]);
    3906             :     case wasm::kExprI8x16Neg:
    3907          36 :       return graph()->NewNode(jsgraph()->machine()->I8x16Neg(), inputs[0]);
    3908             :     case wasm::kExprI8x16SConvertI16x8:
    3909             :       return graph()->NewNode(jsgraph()->machine()->I8x16SConvertI16x8(),
    3910           0 :                               inputs[0], inputs[1]);
    3911             :     case wasm::kExprI8x16Add:
    3912             :       return graph()->NewNode(jsgraph()->machine()->I8x16Add(), inputs[0],
    3913          36 :                               inputs[1]);
    3914             :     case wasm::kExprI8x16AddSaturateS:
    3915             :       return graph()->NewNode(jsgraph()->machine()->I8x16AddSaturateS(),
    3916          36 :                               inputs[0], inputs[1]);
    3917             :     case wasm::kExprI8x16Sub:
    3918             :       return graph()->NewNode(jsgraph()->machine()->I8x16Sub(), inputs[0],
    3919          36 :                               inputs[1]);
    3920             :     case wasm::kExprI8x16SubSaturateS:
    3921             :       return graph()->NewNode(jsgraph()->machine()->I8x16SubSaturateS(),
    3922          36 :                               inputs[0], inputs[1]);
    3923             :     case wasm::kExprI8x16Mul:
    3924             :       return graph()->NewNode(jsgraph()->machine()->I8x16Mul(), inputs[0],
    3925           0 :                               inputs[1]);
    3926             :     case wasm::kExprI8x16MinS:
    3927             :       return graph()->NewNode(jsgraph()->machine()->I8x16MinS(), inputs[0],
    3928          36 :                               inputs[1]);
    3929             :     case wasm::kExprI8x16MaxS:
    3930             :       return graph()->NewNode(jsgraph()->machine()->I8x16MaxS(), inputs[0],
    3931          36 :                               inputs[1]);
    3932             :     case wasm::kExprI8x16Eq:
    3933             :       return graph()->NewNode(jsgraph()->machine()->I8x16Eq(), inputs[0],
    3934          36 :                               inputs[1]);
    3935             :     case wasm::kExprI8x16Ne:
    3936             :       return graph()->NewNode(jsgraph()->machine()->I8x16Ne(), inputs[0],
    3937          54 :                               inputs[1]);
    3938             :     case wasm::kExprI8x16LtS:
    3939             :       return graph()->NewNode(jsgraph()->machine()->I8x16GtS(), inputs[1],
    3940          36 :                               inputs[0]);
    3941             :     case wasm::kExprI8x16LeS:
    3942             :       return graph()->NewNode(jsgraph()->machine()->I8x16GeS(), inputs[1],
    3943          36 :                               inputs[0]);
    3944             :     case wasm::kExprI8x16GtS:
    3945             :       return graph()->NewNode(jsgraph()->machine()->I8x16GtS(), inputs[0],
    3946          36 :                               inputs[1]);
    3947             :     case wasm::kExprI8x16GeS:
    3948             :       return graph()->NewNode(jsgraph()->machine()->I8x16GeS(), inputs[0],
    3949          36 :                               inputs[1]);
    3950             :     case wasm::kExprI8x16UConvertI16x8:
    3951             :       return graph()->NewNode(jsgraph()->machine()->I8x16UConvertI16x8(),
    3952           0 :                               inputs[0], inputs[1]);
    3953             :     case wasm::kExprI8x16AddSaturateU:
    3954             :       return graph()->NewNode(jsgraph()->machine()->I8x16AddSaturateU(),
    3955          36 :                               inputs[0], inputs[1]);
    3956             :     case wasm::kExprI8x16SubSaturateU:
    3957             :       return graph()->NewNode(jsgraph()->machine()->I8x16SubSaturateU(),
    3958          36 :                               inputs[0], inputs[1]);
    3959             :     case wasm::kExprI8x16MinU:
    3960             :       return graph()->NewNode(jsgraph()->machine()->I8x16MinU(), inputs[0],
    3961          36 :                               inputs[1]);
    3962             :     case wasm::kExprI8x16MaxU:
    3963             :       return graph()->NewNode(jsgraph()->machine()->I8x16MaxU(), inputs[0],
    3964          36 :                               inputs[1]);
    3965             :     case wasm::kExprI8x16LtU:
    3966             :       return graph()->NewNode(jsgraph()->machine()->I8x16GtU(), inputs[1],
    3967          36 :                               inputs[0]);
    3968             :     case wasm::kExprI8x16LeU:
    3969             :       return graph()->NewNode(jsgraph()->machine()->I8x16GeU(), inputs[1],
    3970          36 :                               inputs[0]);
    3971             :     case wasm::kExprI8x16GtU:
    3972             :       return graph()->NewNode(jsgraph()->machine()->I8x16GtU(), inputs[0],
    3973          36 :                               inputs[1]);
    3974             :     case wasm::kExprI8x16GeU:
    3975             :       return graph()->NewNode(jsgraph()->machine()->I8x16GeU(), inputs[0],
    3976          36 :                               inputs[1]);
    3977             :     case wasm::kExprS128And:
    3978             :       return graph()->NewNode(jsgraph()->machine()->S128And(), inputs[0],
    3979          36 :                               inputs[1]);
    3980             :     case wasm::kExprS128Or:
    3981             :       return graph()->NewNode(jsgraph()->machine()->S128Or(), inputs[0],
    3982          36 :                               inputs[1]);
    3983             :     case wasm::kExprS128Xor:
    3984             :       return graph()->NewNode(jsgraph()->machine()->S128Xor(), inputs[0],
    3985          36 :                               inputs[1]);
    3986             :     case wasm::kExprS128Not:
    3987          36 :       return graph()->NewNode(jsgraph()->machine()->S128Not(), inputs[0]);
    3988             :     case wasm::kExprS128Select:
    3989             :       return graph()->NewNode(jsgraph()->machine()->S128Select(), inputs[0],
    3990         108 :                               inputs[1], inputs[2]);
    3991             :     case wasm::kExprS1x4AnyTrue:
    3992           0 :       return graph()->NewNode(jsgraph()->machine()->S1x4AnyTrue(), inputs[0]);
    3993             :     case wasm::kExprS1x4AllTrue:
    3994           0 :       return graph()->NewNode(jsgraph()->machine()->S1x4AllTrue(), inputs[0]);
    3995             :     case wasm::kExprS1x8AnyTrue:
    3996           0 :       return graph()->NewNode(jsgraph()->machine()->S1x8AnyTrue(), inputs[0]);
    3997             :     case wasm::kExprS1x8AllTrue:
    3998           0 :       return graph()->NewNode(jsgraph()->machine()->S1x8AllTrue(), inputs[0]);
    3999             :     case wasm::kExprS1x16AnyTrue:
    4000           0 :       return graph()->NewNode(jsgraph()->machine()->S1x16AnyTrue(), inputs[0]);
    4001             :     case wasm::kExprS1x16AllTrue:
    4002           0 :       return graph()->NewNode(jsgraph()->machine()->S1x16AllTrue(), inputs[0]);
    4003             :     default:
    4004           0 :       FATAL_UNSUPPORTED_OPCODE(opcode);
    4005             :   }
    4006             : }
    4007             : 
    4008       12654 : Node* WasmGraphBuilder::SimdLaneOp(wasm::WasmOpcode opcode, uint8_t lane,
    4009       12654 :                                    Node* const* inputs) {
    4010       12654 :   has_simd_ = true;
    4011       12654 :   switch (opcode) {
    4012             :     case wasm::kExprF32x4ExtractLane:
    4013             :       return graph()->NewNode(jsgraph()->machine()->F32x4ExtractLane(lane),
    4014           0 :                               inputs[0]);
    4015             :     case wasm::kExprF32x4ReplaceLane:
    4016             :       return graph()->NewNode(jsgraph()->machine()->F32x4ReplaceLane(lane),
    4017           0 :                               inputs[0], inputs[1]);
    4018             :     case wasm::kExprI32x4ExtractLane:
    4019             :       return graph()->NewNode(jsgraph()->machine()->I32x4ExtractLane(lane),
    4020        4878 :                               inputs[0]);
    4021             :     case wasm::kExprI32x4ReplaceLane:
    4022             :       return graph()->NewNode(jsgraph()->machine()->I32x4ReplaceLane(lane),
    4023         396 :                               inputs[0], inputs[1]);
    4024             :     case wasm::kExprI16x8ExtractLane:
    4025             :       return graph()->NewNode(jsgraph()->machine()->I16x8ExtractLane(lane),
    4026        9936 :                               inputs[0]);
    4027             :     case wasm::kExprI16x8ReplaceLane:
    4028             :       return graph()->NewNode(jsgraph()->machine()->I16x8ReplaceLane(lane),
    4029         360 :                               inputs[0], inputs[1]);
    4030             :     case wasm::kExprI8x16ExtractLane:
    4031             :       return graph()->NewNode(jsgraph()->machine()->I8x16ExtractLane(lane),
    4032       21744 :                               inputs[0]);
    4033             :     case wasm::kExprI8x16ReplaceLane:
    4034             :       return graph()->NewNode(jsgraph()->machine()->I8x16ReplaceLane(lane),
    4035         648 :                               inputs[0], inputs[1]);
    4036             :     default:
    4037           0 :       FATAL_UNSUPPORTED_OPCODE(opcode);
    4038             :   }
    4039             : }
    4040             : 
    4041          72 : Node* WasmGraphBuilder::SimdShiftOp(wasm::WasmOpcode opcode, uint8_t shift,
    4042          72 :                                     Node* const* inputs) {
    4043          72 :   has_simd_ = true;
    4044          72 :   switch (opcode) {
    4045             :     case wasm::kExprI32x4Shl:
    4046          36 :       return graph()->NewNode(jsgraph()->machine()->I32x4Shl(shift), inputs[0]);
    4047             :     case wasm::kExprI32x4ShrS:
    4048             :       return graph()->NewNode(jsgraph()->machine()->I32x4ShrS(shift),
    4049          36 :                               inputs[0]);
    4050             :     case wasm::kExprI32x4ShrU:
    4051             :       return graph()->NewNode(jsgraph()->machine()->I32x4ShrU(shift),
    4052          36 :                               inputs[0]);
    4053             :     case wasm::kExprI16x8Shl:
    4054          36 :       return graph()->NewNode(jsgraph()->machine()->I16x8Shl(shift), inputs[0]);
    4055             :     case wasm::kExprI16x8ShrS:
    4056             :       return graph()->NewNode(jsgraph()->machine()->I16x8ShrS(shift),
    4057          36 :                               inputs[0]);
    4058             :     case wasm::kExprI16x8ShrU:
    4059             :       return graph()->NewNode(jsgraph()->machine()->I16x8ShrU(shift),
    4060          36 :                               inputs[0]);
    4061             :     case wasm::kExprI8x16Shl:
    4062           0 :       return graph()->NewNode(jsgraph()->machine()->I8x16Shl(shift), inputs[0]);
    4063             :     case wasm::kExprI8x16ShrS:
    4064             :       return graph()->NewNode(jsgraph()->machine()->I8x16ShrS(shift),
    4065           0 :                               inputs[0]);
    4066             :     case wasm::kExprI8x16ShrU:
    4067             :       return graph()->NewNode(jsgraph()->machine()->I8x16ShrU(shift),
    4068           0 :                               inputs[0]);
    4069             :     default:
    4070           0 :       FATAL_UNSUPPORTED_OPCODE(opcode);
    4071             :   }
    4072             : }
    4073             : 
    4074           0 : Node* WasmGraphBuilder::Simd8x16ShuffleOp(const uint8_t shuffle[16],
    4075           0 :                                           Node* const* inputs) {
    4076           0 :   has_simd_ = true;
    4077             :   return graph()->NewNode(jsgraph()->machine()->S8x16Shuffle(shuffle),
    4078           0 :                           inputs[0], inputs[1]);
    4079             : }
    4080             : 
    4081             : #define ATOMIC_BINOP_LIST(V)              \
    4082             :   V(I32AtomicAdd, Add, Uint32)            \
    4083             :   V(I32AtomicSub, Sub, Uint32)            \
    4084             :   V(I32AtomicAnd, And, Uint32)            \
    4085             :   V(I32AtomicOr, Or, Uint32)              \
    4086             :   V(I32AtomicXor, Xor, Uint32)            \
    4087             :   V(I32AtomicExchange, Exchange, Uint32)  \
    4088             :   V(I32AtomicAdd8U, Add, Uint8)           \
    4089             :   V(I32AtomicSub8U, Sub, Uint8)           \
    4090             :   V(I32AtomicAnd8U, And, Uint8)           \
    4091             :   V(I32AtomicOr8U, Or, Uint8)             \
    4092             :   V(I32AtomicXor8U, Xor, Uint8)           \
    4093             :   V(I32AtomicExchange8U, Exchange, Uint8) \
    4094             :   V(I32AtomicAdd16U, Add, Uint16)         \
    4095             :   V(I32AtomicSub16U, Sub, Uint16)         \
    4096             :   V(I32AtomicAnd16U, And, Uint16)         \
    4097             :   V(I32AtomicOr16U, Or, Uint16)           \
    4098             :   V(I32AtomicXor16U, Xor, Uint16)         \
    4099             :   V(I32AtomicExchange16U, Exchange, Uint16)
    4100             : 
    4101             : #define ATOMIC_TERNARY_LIST(V)                          \
    4102             :   V(I32AtomicCompareExchange, CompareExchange, Uint32)  \
    4103             :   V(I32AtomicCompareExchange8U, CompareExchange, Uint8) \
    4104             :   V(I32AtomicCompareExchange16U, CompareExchange, Uint16)
    4105             : 
    4106             : #define ATOMIC_LOAD_LIST(V) \
    4107             :   V(I32AtomicLoad, Uint32)  \
    4108             :   V(I32AtomicLoad8U, Uint8) \
    4109             :   V(I32AtomicLoad16U, Uint16)
    4110             : 
    4111             : #define ATOMIC_STORE_LIST(V)         \
    4112             :   V(I32AtomicStore, Uint32, kWord32) \
    4113             :   V(I32AtomicStore8U, Uint8, kWord8) \
    4114             :   V(I32AtomicStore16U, Uint16, kWord16)
    4115             : 
    4116         512 : Node* WasmGraphBuilder::AtomicOp(wasm::WasmOpcode opcode, Node* const* inputs,
    4117             :                                  uint32_t alignment, uint32_t offset,
    4118         512 :                                  wasm::WasmCodePosition position) {
    4119             :   // TODO(gdeepti): Add alignment validation, traps on misalignment
    4120             :   Node* node;
    4121         512 :   switch (opcode) {
    4122             : #define BUILD_ATOMIC_BINOP(Name, Operation, Type)                      \
    4123             :   case wasm::kExpr##Name: {                                            \
    4124             :     BoundsCheckMem(MachineType::Type(), inputs[0], offset, position);  \
    4125             :     node = graph()->NewNode(                                           \
    4126             :         jsgraph()->machine()->Atomic##Operation(MachineType::Type()),  \
    4127             :         MemBuffer(offset), inputs[0], inputs[1], *effect_, *control_); \
    4128             :     break;                                                             \
    4129             :   }
    4130         592 :     ATOMIC_BINOP_LIST(BUILD_ATOMIC_BINOP)
    4131             : #undef BUILD_ATOMIC_BINOP
    4132             : 
    4133             : #define BUILD_ATOMIC_TERNARY_OP(Name, Operation, Type)                \
    4134             :   case wasm::kExpr##Name: {                                           \
    4135             :     BoundsCheckMem(MachineType::Type(), inputs[0], offset, position); \
    4136             :     node = graph()->NewNode(                                          \
    4137             :         jsgraph()->machine()->Atomic##Operation(MachineType::Type()), \
    4138             :         MemBuffer(offset), inputs[0], inputs[1], inputs[2], *effect_, \
    4139             :         *control_);                                                   \
    4140             :     break;                                                            \
    4141             :   }
    4142         112 :     ATOMIC_TERNARY_LIST(BUILD_ATOMIC_TERNARY_OP)
    4143             : #undef BUILD_ATOMIC_TERNARY_OP
    4144             : 
    4145             : #define BUILD_ATOMIC_LOAD_OP(Name, Type)                              \
    4146             :   case wasm::kExpr##Name: {                                           \
    4147             :     BoundsCheckMem(MachineType::Type(), inputs[0], offset, position); \
    4148             :     node = graph()->NewNode(                                          \
    4149             :         jsgraph()->machine()->AtomicLoad(MachineType::Type()),        \
    4150             :         MemBuffer(offset), inputs[0], *effect_, *control_);           \
    4151             :     break;                                                            \
    4152             :   }
    4153         232 :     ATOMIC_LOAD_LIST(BUILD_ATOMIC_LOAD_OP)
    4154             : #undef BUILD_ATOMIC_LOAD_OP
    4155             : 
    4156             : #define BUILD_ATOMIC_STORE_OP(Name, Type, Rep)                         \
    4157             :   case wasm::kExpr##Name: {                                            \
    4158             :     BoundsCheckMem(MachineType::Type(), inputs[0], offset, position);  \
    4159             :     node = graph()->NewNode(                                           \
    4160             :         jsgraph()->machine()->AtomicStore(MachineRepresentation::Rep), \
    4161             :         MemBuffer(offset), inputs[0], inputs[1], *effect_, *control_); \
    4162             :     break;                                                             \
    4163             :   }
    4164         220 :     ATOMIC_STORE_LIST(BUILD_ATOMIC_STORE_OP)
    4165             : #undef BUILD_ATOMIC_STORE_OP
    4166             :     default:
    4167           0 :       FATAL_UNSUPPORTED_OPCODE(opcode);
    4168             :   }
    4169         512 :   *effect_ = node;
    4170         512 :   return node;
    4171             : }
    4172             : 
    4173             : #undef ATOMIC_BINOP_LIST
    4174             : #undef ATOMIC_TERNARY_LIST
    4175             : #undef ATOMIC_LOAD_LIST
    4176             : #undef ATOMIC_STORE_LIST
    4177             : 
    4178             : namespace {
    4179      805094 : bool must_record_function_compilation(Isolate* isolate) {
    4180      805094 :   return isolate->logger()->is_logging_code_events() || isolate->is_profiling();
    4181             : }
    4182             : 
    4183             : PRINTF_FORMAT(4, 5)
    4184           0 : void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
    4185             :                                Isolate* isolate, Handle<Code> code,
    4186             :                                const char* format, ...) {
    4187             :   DCHECK(must_record_function_compilation(isolate));
    4188             : 
    4189             :   ScopedVector<char> buffer(128);
    4190             :   va_list arguments;
    4191           0 :   va_start(arguments, format);
    4192           0 :   int len = VSNPrintF(buffer, format, arguments);
    4193           0 :   CHECK_LT(0, len);
    4194           0 :   va_end(arguments);
    4195             :   Handle<String> name_str =
    4196           0 :       isolate->factory()->NewStringFromAsciiChecked(buffer.start());
    4197             :   Handle<String> script_str =
    4198           0 :       isolate->factory()->NewStringFromAsciiChecked("(wasm)");
    4199             :   Handle<SharedFunctionInfo> shared =
    4200           0 :       isolate->factory()->NewSharedFunctionInfo(name_str, code, false);
    4201           0 :   PROFILE(isolate, CodeCreateEvent(tag, AbstractCode::cast(*code), *shared,
    4202             :                                    *script_str, 0, 0));
    4203           0 : }
    4204             : }  // namespace
    4205             : 
    4206      320352 : Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
    4207             :                                     Handle<Code> wasm_code, uint32_t index,
    4208             :                                     Address wasm_context_address) {
    4209      320352 :   const wasm::WasmFunction* func = &module->functions[index];
    4210             : 
    4211             :   //----------------------------------------------------------------------------
    4212             :   // Create the Graph
    4213             :   //----------------------------------------------------------------------------
    4214      160176 :   Zone zone(isolate->allocator(), ZONE_NAME);
    4215      160176 :   Graph graph(&zone);
    4216      160176 :   CommonOperatorBuilder common(&zone);
    4217             :   MachineOperatorBuilder machine(
    4218             :       &zone, MachineType::PointerRepresentation(),
    4219             :       InstructionSelector::SupportedMachineOperatorFlags(),
    4220      160176 :       InstructionSelector::AlignmentRequirements());
    4221             :   JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
    4222             : 
    4223      160176 :   Node* control = nullptr;
    4224      160176 :   Node* effect = nullptr;
    4225             : 
    4226             :   // TODO(titzer): compile JS to WASM wrappers without a {ModuleEnv}.
    4227             :   ModuleEnv env = {
    4228             :       module,
    4229             :       std::vector<Address>(),         // function_tables
    4230             :       std::vector<Address>(),         // signature_tables
    4231             :       std::vector<Handle<Code>>(),    // function_code
    4232      160176 :       BUILTIN_CODE(isolate, Illegal)  // default_function_code
    4233      480528 :   };
    4234             : 
    4235             :   WasmGraphBuilder builder(&env, &zone, &jsgraph,
    4236      480528 :                            CEntryStub(isolate, 1).GetCode(), func->sig);
    4237             :   builder.set_control_ptr(&control);
    4238             :   builder.set_effect_ptr(&effect);
    4239      160176 :   builder.BuildJSToWasmWrapper(wasm_code, wasm_context_address);
    4240             : 
    4241             :   //----------------------------------------------------------------------------
    4242             :   // Run the compilation pipeline.
    4243             :   //----------------------------------------------------------------------------
    4244      160176 :   if (FLAG_trace_turbo_graph) {  // Simple textual RPO.
    4245           0 :     OFStream os(stdout);
    4246           0 :     os << "-- Graph after change lowering -- " << std::endl;
    4247           0 :     os << AsRPO(graph);
    4248             :   }
    4249             : 
    4250             :   // Schedule and compile to machine code.
    4251             :   int params =
    4252      160176 :       static_cast<int>(module->functions[index].sig->parameter_count());
    4253             :   CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
    4254      160176 :       &zone, false, params + 1, CallDescriptor::kNoFlags);
    4255             : 
    4256             : #ifdef DEBUG
    4257             :   EmbeddedVector<char, 32> func_name;
    4258             :   static unsigned id = 0;
    4259             :   func_name.Truncate(SNPrintF(func_name, "js-to-wasm#%d", id++));
    4260             : #else
    4261             :   Vector<const char> func_name = CStrVector("js-to-wasm");
    4262             : #endif
    4263             : 
    4264      320352 :   CompilationInfo info(func_name, isolate, &zone, Code::JS_TO_WASM_FUNCTION);
    4265      160176 :   Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph);
    4266             : #ifdef ENABLE_DISASSEMBLER
    4267             :   if (FLAG_print_opt_code && !code.is_null()) {
    4268             :     OFStream os(stdout);
    4269             :     code->Disassemble(func_name.start(), os);
    4270             :   }
    4271             : #endif
    4272             : 
    4273      160176 :   if (must_record_function_compilation(isolate)) {
    4274             :     RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate, code,
    4275           0 :                               "%.*s", func_name.length(), func_name.start());
    4276             :   }
    4277             : 
    4278      320352 :   return code;
    4279             : }
    4280             : 
    4281           0 : void ValidateImportWrapperReferencesImmovables(Handle<Code> wrapper) {
    4282             : #if !DEBUG
    4283             :   return;
    4284             : #endif
    4285             :   // We expect the only embedded objects to be those originating from
    4286             :   // a snapshot, which are immovable.
    4287             :   DisallowHeapAllocation no_gc;
    4288             :   if (wrapper.is_null()) return;
    4289             :   static constexpr int kAllGCRefs = (1 << (RelocInfo::LAST_GCED_ENUM + 1)) - 1;
    4290             :   for (RelocIterator it(*wrapper, kAllGCRefs); !it.done(); it.next()) {
    4291             :     RelocInfo::Mode mode = it.rinfo()->rmode();
    4292             :     Object* target = nullptr;
    4293             :     switch (mode) {
    4294             :       case RelocInfo::CODE_TARGET:
    4295             :         // this would be either one of the stubs or builtins, because
    4296             :         // we didn't link yet.
    4297             :         target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
    4298             :         break;
    4299             :       case RelocInfo::EMBEDDED_OBJECT:
    4300             :         target = it.rinfo()->target_object();
    4301             :         break;
    4302             :       default:
    4303             :         UNREACHABLE();
    4304             :     }
    4305             :     CHECK_NOT_NULL(target);
    4306             :     bool is_immovable =
    4307             :         target->IsSmi() || Heap::IsImmovable(HeapObject::cast(target));
    4308             :     bool is_allowed_stub = false;
    4309             :     if (target->IsCode()) {
    4310             :       Code* code = Code::cast(target);
    4311             :       is_allowed_stub =
    4312             :           code->kind() == Code::STUB &&
    4313             :           CodeStub::MajorKeyFromKey(code->stub_key()) == CodeStub::DoubleToI;
    4314             :     }
    4315             :     CHECK(is_immovable || is_allowed_stub);
    4316             :   }
    4317             : }
    4318             : 
    4319       13492 : Handle<Code> CompileWasmToJSWrapper(
    4320       13492 :     Isolate* isolate, Handle<JSReceiver> target, wasm::FunctionSig* sig,
    4321             :     uint32_t index, wasm::ModuleOrigin origin,
    4322             :     Handle<FixedArray> global_js_imports_table) {
    4323             :   //----------------------------------------------------------------------------
    4324             :   // Create the Graph
    4325             :   //----------------------------------------------------------------------------
    4326       13492 :   Zone zone(isolate->allocator(), ZONE_NAME);
    4327       13492 :   Graph graph(&zone);
    4328       13492 :   CommonOperatorBuilder common(&zone);
    4329             :   MachineOperatorBuilder machine(
    4330             :       &zone, MachineType::PointerRepresentation(),
    4331             :       InstructionSelector::SupportedMachineOperatorFlags(),
    4332       13492 :       InstructionSelector::AlignmentRequirements());
    4333             :   JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
    4334             : 
    4335       13492 :   Node* control = nullptr;
    4336       13492 :   Node* effect = nullptr;
    4337             : 
    4338             :   SourcePositionTable* source_position_table =
    4339        4311 :       origin == wasm::kAsmJsOrigin ? new (&zone) SourcePositionTable(&graph)
    4340       13492 :                                    : nullptr;
    4341             : 
    4342             :   WasmGraphBuilder builder(nullptr, &zone, &jsgraph,
    4343             :                            CEntryStub(isolate, 1).GetCode(), sig,
    4344       26984 :                            source_position_table);
    4345             :   builder.set_control_ptr(&control);
    4346             :   builder.set_effect_ptr(&effect);
    4347       13492 :   if (builder.BuildWasmToJSWrapper(target, global_js_imports_table, index)) {
    4348             :     global_js_imports_table->set(
    4349       13442 :         OffsetForImportData(index, WasmGraphBuilder::kFunction), *target);
    4350       13442 :     if (target->IsJSFunction()) {
    4351             :       Handle<JSFunction> function = Handle<JSFunction>::cast(target);
    4352             :       global_js_imports_table->set(
    4353             :           OffsetForImportData(index, WasmGraphBuilder::kFunctionContext),
    4354       11492 :           function->context());
    4355             :       global_js_imports_table->set(
    4356             :           OffsetForImportData(index, WasmGraphBuilder::kGlobalProxy),
    4357       22984 :           function->context()->global_proxy());
    4358             :     }
    4359             :   }
    4360             : 
    4361       13492 :     if (FLAG_trace_turbo_graph) {  // Simple textual RPO.
    4362           0 :       OFStream os(stdout);
    4363           0 :       os << "-- Graph after change lowering -- " << std::endl;
    4364           0 :       os << AsRPO(graph);
    4365             :     }
    4366             : 
    4367             :     // Schedule and compile to machine code.
    4368       13492 :     CallDescriptor* incoming = GetWasmCallDescriptor(&zone, sig);
    4369       13492 :     if (machine.Is32()) {
    4370           0 :       incoming = GetI32WasmCallDescriptor(&zone, incoming);
    4371             :     }
    4372             : 
    4373             : #ifdef DEBUG
    4374             :     EmbeddedVector<char, 32> func_name;
    4375             :     static unsigned id = 0;
    4376             :     func_name.Truncate(SNPrintF(func_name, "wasm-to-js#%d", id++));
    4377             : #else
    4378             :     Vector<const char> func_name = CStrVector("wasm-to-js");
    4379             : #endif
    4380             : 
    4381       26984 :     CompilationInfo info(func_name, isolate, &zone, Code::WASM_TO_JS_FUNCTION);
    4382             :     Handle<Code> code = Pipeline::GenerateCodeForTesting(
    4383       13492 :         &info, incoming, &graph, nullptr, source_position_table);
    4384             :     ValidateImportWrapperReferencesImmovables(code);
    4385             :     Handle<FixedArray> deopt_data =
    4386       13492 :         isolate->factory()->NewFixedArray(2, TENURED);
    4387             :     intptr_t loc =
    4388             :         reinterpret_cast<intptr_t>(global_js_imports_table.location());
    4389       13492 :     Handle<Object> loc_handle = isolate->factory()->NewHeapNumberFromBits(loc);
    4390       13492 :     deopt_data->set(0, *loc_handle);
    4391             :     Handle<Object> index_handle = isolate->factory()->NewNumberFromInt(
    4392       13492 :         OffsetForImportData(index, WasmGraphBuilder::kFunction));
    4393       13492 :     deopt_data->set(1, *index_handle);
    4394       13492 :     code->set_deoptimization_data(*deopt_data);
    4395             : #ifdef ENABLE_DISASSEMBLER
    4396             :     if (FLAG_print_opt_code && !code.is_null()) {
    4397             :       OFStream os(stdout);
    4398             :       code->Disassemble(func_name.start(), os);
    4399             :     }
    4400             : #endif
    4401             : 
    4402       13492 :   if (must_record_function_compilation(isolate)) {
    4403             :     RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate, code,
    4404           0 :                               "%.*s", func_name.length(), func_name.start());
    4405             :   }
    4406             : 
    4407       26984 :   return code;
    4408             : }
    4409             : 
    4410      407685 : Handle<Code> CompileWasmToWasmWrapper(Isolate* isolate, Handle<Code> target,
    4411             :                                       wasm::FunctionSig* sig,
    4412             :                                       uint32_t func_index,
    4413             :                                       Address new_wasm_context_address) {
    4414             :   //----------------------------------------------------------------------------
    4415             :   // Create the Graph
    4416             :   //----------------------------------------------------------------------------
    4417      135895 :   Zone zone(isolate->allocator(), ZONE_NAME);
    4418      135895 :   Graph graph(&zone);
    4419      135895 :   CommonOperatorBuilder common(&zone);
    4420             :   MachineOperatorBuilder machine(
    4421             :       &zone, MachineType::PointerRepresentation(),
    4422             :       InstructionSelector::SupportedMachineOperatorFlags(),
    4423      135895 :       InstructionSelector::AlignmentRequirements());
    4424             :   JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
    4425             : 
    4426      135895 :   Node* control = nullptr;
    4427      135895 :   Node* effect = nullptr;
    4428             : 
    4429      135895 :   WasmGraphBuilder builder(nullptr, &zone, &jsgraph, Handle<Code>(), sig);
    4430             :   builder.set_control_ptr(&control);
    4431             :   builder.set_effect_ptr(&effect);
    4432      135895 :   builder.BuildWasmToWasmWrapper(target, new_wasm_context_address);
    4433      135895 :   if (HasInt64ParamOrReturn(sig)) builder.LowerInt64();
    4434             : 
    4435      135895 :   if (FLAG_trace_turbo_graph) {  // Simple textual RPO.
    4436           0 :     OFStream os(stdout);
    4437           0 :     os << "-- Graph after change lowering -- " << std::endl;
    4438           0 :     os << AsRPO(graph);
    4439             :   }
    4440             : 
    4441             :   // Schedule and compile to machine code.
    4442      135895 :   CallDescriptor* incoming = GetWasmCallDescriptor(&zone, sig);
    4443      135895 :   if (machine.Is32()) {
    4444           0 :     incoming = GetI32WasmCallDescriptor(&zone, incoming);
    4445             :   }
    4446             :   bool debugging =
    4447             : #if DEBUG
    4448             :       true;
    4449             : #else
    4450      135895 :       FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph;
    4451             : #endif
    4452      135895 :   Vector<const char> func_name = ArrayVector("wasm-to-wasm");
    4453             :   static unsigned id = 0;
    4454      135895 :   Vector<char> buffer;
    4455      135895 :   if (debugging) {
    4456           0 :     buffer = Vector<char>::New(128);
    4457           0 :     int chars = SNPrintF(buffer, "wasm-to-wasm#%d", id);
    4458           0 :     func_name = Vector<const char>::cast(buffer.SubVector(0, chars));
    4459             :   }
    4460             : 
    4461      271790 :   CompilationInfo info(func_name, isolate, &zone, Code::WASM_FUNCTION);
    4462      135895 :   Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph);
    4463             : #ifdef ENABLE_DISASSEMBLER
    4464             :   if (FLAG_print_opt_code && !code.is_null()) {
    4465             :     OFStream os(stdout);
    4466             :     code->Disassemble(buffer.start(), os);
    4467             :   }
    4468             : #endif
    4469      135895 :   if (debugging) {
    4470             :     buffer.Dispose();
    4471             :   }
    4472      271790 :   if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
    4473             :     RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate, code,
    4474           0 :                               "wasm-to-wasm");
    4475             :   }
    4476             : 
    4477      271790 :   return code;
    4478             : }
    4479             : 
    4480        1125 : Handle<Code> CompileWasmInterpreterEntry(Isolate* isolate, uint32_t func_index,
    4481             :                                          wasm::FunctionSig* sig,
    4482             :                                          Handle<WasmInstanceObject> instance) {
    4483             :   //----------------------------------------------------------------------------
    4484             :   // Create the Graph
    4485             :   //----------------------------------------------------------------------------
    4486        1125 :   Zone zone(isolate->allocator(), ZONE_NAME);
    4487        1125 :   Graph graph(&zone);
    4488        1125 :   CommonOperatorBuilder common(&zone);
    4489             :   MachineOperatorBuilder machine(
    4490             :       &zone, MachineType::PointerRepresentation(),
    4491             :       InstructionSelector::SupportedMachineOperatorFlags(),
    4492        1125 :       InstructionSelector::AlignmentRequirements());
    4493             :   JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
    4494             : 
    4495        1125 :   Node* control = nullptr;
    4496        1125 :   Node* effect = nullptr;
    4497             : 
    4498             :   WasmGraphBuilder builder(nullptr, &zone, &jsgraph,
    4499        2250 :                            CEntryStub(isolate, 1).GetCode(), sig);
    4500             :   builder.set_control_ptr(&control);
    4501             :   builder.set_effect_ptr(&effect);
    4502        1125 :   builder.BuildWasmInterpreterEntry(func_index, instance);
    4503             : 
    4504             :   Handle<Code> code = Handle<Code>::null();
    4505             :   {
    4506        1125 :     if (FLAG_trace_turbo_graph) {  // Simple textual RPO.
    4507           0 :       OFStream os(stdout);
    4508           0 :       os << "-- Wasm interpreter entry graph -- " << std::endl;
    4509           0 :       os << AsRPO(graph);
    4510             :     }
    4511             : 
    4512             :     // Schedule and compile to machine code.
    4513        1125 :     CallDescriptor* incoming = GetWasmCallDescriptor(&zone, sig);
    4514        1125 :     if (machine.Is32()) {
    4515           0 :       incoming = GetI32WasmCallDescriptor(&zone, incoming);
    4516             :     }
    4517             : #ifdef DEBUG
    4518             :     EmbeddedVector<char, 32> func_name;
    4519             :     func_name.Truncate(
    4520             :         SNPrintF(func_name, "wasm-interpreter-entry#%d", func_index));
    4521             : #else
    4522             :     Vector<const char> func_name = CStrVector("wasm-interpreter-entry");
    4523             : #endif
    4524             : 
    4525             :     CompilationInfo info(func_name, isolate, &zone,
    4526        1125 :                          Code::WASM_INTERPRETER_ENTRY);
    4527        1125 :     code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr);
    4528             : #ifdef ENABLE_DISASSEMBLER
    4529             :     if (FLAG_print_opt_code && !code.is_null()) {
    4530             :       OFStream os(stdout);
    4531             :       code->Disassemble(func_name.start(), os);
    4532             :     }
    4533             : #endif
    4534             : 
    4535        1125 :     if (must_record_function_compilation(isolate)) {
    4536             :       RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate, code,
    4537           0 :                                 "%.*s", func_name.length(), func_name.start());
    4538        1125 :     }
    4539             :   }
    4540             : 
    4541        1125 :   Handle<FixedArray> deopt_data = isolate->factory()->NewFixedArray(1, TENURED);
    4542        1125 :   Handle<WeakCell> weak_instance = isolate->factory()->NewWeakCell(instance);
    4543        1125 :   deopt_data->set(0, *weak_instance);
    4544        1125 :   code->set_deoptimization_data(*deopt_data);
    4545             : 
    4546        1125 :   return code;
    4547             : }
    4548             : 
    4549          96 : Handle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig,
    4550             :                                Address wasm_context_address) {
    4551          96 :   Zone zone(isolate->allocator(), ZONE_NAME);
    4552          96 :   Graph graph(&zone);
    4553          96 :   CommonOperatorBuilder common(&zone);
    4554             :   MachineOperatorBuilder machine(
    4555             :       &zone, MachineType::PointerRepresentation(),
    4556             :       InstructionSelector::SupportedMachineOperatorFlags(),
    4557          96 :       InstructionSelector::AlignmentRequirements());
    4558             :   JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
    4559             : 
    4560          96 :   Node* control = nullptr;
    4561          96 :   Node* effect = nullptr;
    4562             : 
    4563             :   WasmGraphBuilder builder(nullptr, &zone, &jsgraph,
    4564         192 :                            CEntryStub(isolate, 1).GetCode(), sig);
    4565             :   builder.set_control_ptr(&control);
    4566             :   builder.set_effect_ptr(&effect);
    4567          96 :   builder.BuildCWasmEntry(wasm_context_address);
    4568             : 
    4569          96 :   if (FLAG_trace_turbo_graph) {  // Simple textual RPO.
    4570           0 :     OFStream os(stdout);
    4571           0 :     os << "-- C Wasm entry graph -- " << std::endl;
    4572           0 :     os << AsRPO(graph);
    4573             :   }
    4574             : 
    4575             :   // Schedule and compile to machine code.
    4576             :   CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
    4577             :       &zone, false, CWasmEntryParameters::kNumParameters + 1,
    4578          96 :       CallDescriptor::kNoFlags);
    4579             : 
    4580             :   // Build a name in the form "c-wasm-entry:<params>:<returns>".
    4581             :   static constexpr size_t kMaxNameLen = 128;
    4582          96 :   char debug_name[kMaxNameLen] = "c-wasm-entry:";
    4583          96 :   size_t name_len = strlen(debug_name);
    4584             :   auto append_name_char = [&](char c) {
    4585         312 :     if (name_len + 1 < kMaxNameLen) debug_name[name_len++] = c;
    4586             :   };
    4587         216 :   for (wasm::ValueType t : sig->parameters()) {
    4588             :     append_name_char(wasm::WasmOpcodes::ShortNameOf(t));
    4589             :   }
    4590             :   append_name_char(':');
    4591         192 :   for (wasm::ValueType t : sig->returns()) {
    4592             :     append_name_char(wasm::WasmOpcodes::ShortNameOf(t));
    4593             :   }
    4594          96 :   debug_name[name_len] = '\0';
    4595             :   Vector<const char> debug_name_vec(debug_name, name_len);
    4596             : 
    4597         192 :   CompilationInfo info(debug_name_vec, isolate, &zone, Code::C_WASM_ENTRY);
    4598          96 :   Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph);
    4599             : #ifdef ENABLE_DISASSEMBLER
    4600             :   if (FLAG_print_opt_code && !code.is_null()) {
    4601             :     OFStream os(stdout);
    4602             :     code->Disassemble(debug_name, os);
    4603             :   }
    4604             : #endif
    4605             : 
    4606         192 :   return code;
    4607             : }
    4608             : 
    4609      233699 : SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
    4610             :     double* decode_ms) {
    4611             : #if DEBUG
    4612             :   if (env_) {
    4613             :     size_t tables_size = env_->module->function_tables.size();
    4614             :     DCHECK_EQ(tables_size, env_->function_tables.size());
    4615             :     DCHECK_EQ(tables_size, env_->signature_tables.size());
    4616             :   }
    4617             : #endif
    4618             : 
    4619             :   base::ElapsedTimer decode_timer;
    4620      233699 :   if (FLAG_trace_wasm_decode_time) {
    4621             :     decode_timer.Start();
    4622             :   }
    4623             :   // Create a TF graph during decoding.
    4624             : 
    4625             :   SourcePositionTable* source_position_table =
    4626      467388 :       new (jsgraph_->zone()) SourcePositionTable(jsgraph_->graph());
    4627             :   WasmGraphBuilder builder(env_, jsgraph_->zone(), jsgraph_, centry_stub_,
    4628             :                            func_body_.sig, source_position_table,
    4629      467346 :                            runtime_exception_support_);
    4630      701128 :   graph_construction_result_ =
    4631             :       wasm::BuildTFGraph(isolate_->allocator(), &builder, func_body_);
    4632             : 
    4633      233719 :   if (graph_construction_result_.failed()) {
    4634        5743 :     if (FLAG_trace_wasm_compiler) {
    4635           0 :       OFStream os(stdout);
    4636           0 :       os << "Compilation failed: " << graph_construction_result_.error_msg()
    4637           0 :          << std::endl;
    4638             :     }
    4639             :     return nullptr;
    4640             :   }
    4641             : 
    4642      227976 :   builder.LowerInt64();
    4643             : 
    4644      456914 :   if (builder.has_simd() &&
    4645        1038 :       (!CpuFeatures::SupportsWasmSimd128() || lower_simd_)) {
    4646         984 :     SimdScalarLowering(jsgraph_, func_body_.sig).LowerGraph();
    4647             :   }
    4648             : 
    4649      455882 :   if (func_index_ >= FLAG_trace_wasm_ast_start &&
    4650      227944 :       func_index_ < FLAG_trace_wasm_ast_end) {
    4651           0 :     PrintRawWasmCode(isolate_->allocator(), func_body_, env_->module);
    4652             :   }
    4653      227943 :   if (FLAG_trace_wasm_decode_time) {
    4654           0 :     *decode_ms = decode_timer.Elapsed().InMillisecondsF();
    4655             :   }
    4656      227943 :   return source_position_table;
    4657             : }
    4658             : 
    4659             : namespace {
    4660             : Vector<const char> GetDebugName(Zone* zone, wasm::WasmName name, int index) {
    4661      227966 :   if (!name.is_empty()) {
    4662             :     return name;
    4663             :   }
    4664             : #ifndef DEBUG
    4665             :   return {};
    4666             : #endif
    4667             :   constexpr int kBufferLength = 15;
    4668             : 
    4669             :   EmbeddedVector<char, kBufferLength> name_vector;
    4670             :   int name_len = SNPrintF(name_vector, "wasm#%d", index);
    4671             :   DCHECK(name_len > 0 && name_len < name_vector.length());
    4672             : 
    4673             :   char* index_name = zone->NewArray<char>(name_len);
    4674             :   memcpy(index_name, name_vector.start(), name_len);
    4675             :   return Vector<const char>(index_name, name_len);
    4676             : }
    4677             : }  // namespace
    4678             : 
    4679       90265 : WasmCompilationUnit::WasmCompilationUnit(
    4680             :     Isolate* isolate, ModuleEnv* env, wasm::FunctionBody body,
    4681             :     wasm::WasmName name, int index, Handle<Code> centry_stub,
    4682             :     Counters* counters, RuntimeExceptionSupport exception_support,
    4683             :     bool lower_simd)
    4684             :     : isolate_(isolate),
    4685             :       env_(env),
    4686             :       func_body_(body),
    4687             :       func_name_(name),
    4688             :       counters_(counters ? counters : isolate->counters()),
    4689             :       centry_stub_(centry_stub),
    4690             :       func_index_(index),
    4691             :       runtime_exception_support_(exception_support),
    4692      701400 :       lower_simd_(lower_simd) {}
    4693             : 
    4694      695249 : void WasmCompilationUnit::ExecuteCompilation() {
    4695      461644 :   auto timed_histogram = env_->module->is_wasm()
    4696             :                              ? counters()->wasm_compile_wasm_function_time()
    4697      467418 :                              : counters()->wasm_compile_asm_function_time();
    4698             :   TimedHistogramScope wasm_compile_function_time_scope(timed_histogram);
    4699             : 
    4700      233698 :   if (FLAG_trace_wasm_compiler) {
    4701           0 :     if (func_name_.start() != nullptr) {
    4702             :       PrintF("Compiling wasm function %d:'%.*s'\n\n", func_index(),
    4703           0 :              func_name_.length(), func_name_.start());
    4704             :     } else {
    4705           0 :       PrintF("Compiling wasm function %d:<unnamed>\n\n", func_index());
    4706             :     }
    4707             :   }
    4708             : 
    4709      233698 :   double decode_ms = 0;
    4710             :   size_t node_count = 0;
    4711             : 
    4712             :   // Scope for the {graph_zone}.
    4713             :   {
    4714      461647 :     Zone graph_zone(isolate_->allocator(), ZONE_NAME);
    4715             :     jsgraph_ = new (&graph_zone) JSGraph(
    4716      233723 :         isolate_, new (&graph_zone) Graph(&graph_zone),
    4717      233711 :         new (&graph_zone) CommonOperatorBuilder(&graph_zone), nullptr, nullptr,
    4718             :         new (&graph_zone) MachineOperatorBuilder(
    4719             :             &graph_zone, MachineType::PointerRepresentation(),
    4720             :             InstructionSelector::SupportedMachineOperatorFlags(),
    4721      934855 :             InstructionSelector::AlignmentRequirements()));
    4722             :     SourcePositionTable* source_positions =
    4723      233708 :         BuildGraphForWasmFunction(&decode_ms);
    4724             : 
    4725      233692 :     if (graph_construction_result_.failed()) {
    4726        5743 :       ok_ = false;
    4727      239424 :       return;
    4728             :     }
    4729             : 
    4730             :     base::ElapsedTimer pipeline_timer;
    4731      227949 :     if (FLAG_trace_wasm_decode_time) {
    4732      455797 :       node_count = jsgraph_->graph()->NodeCount();
    4733             :       pipeline_timer.Start();
    4734             :     }
    4735             : 
    4736      455898 :     compilation_zone_.reset(new Zone(isolate_->allocator(), ZONE_NAME));
    4737             : 
    4738             :     // Run the compiler pipeline to generate machine code.
    4739             :     CallDescriptor* descriptor =
    4740      455920 :         GetWasmCallDescriptor(compilation_zone_.get(), func_body_.sig);
    4741      455932 :     if (jsgraph_->machine()->Is32()) {
    4742             :       descriptor =
    4743           0 :           GetI32WasmCallDescriptor(compilation_zone_.get(), descriptor);
    4744             :     }
    4745             :     info_.reset(new CompilationInfo(
    4746             :         GetDebugName(compilation_zone_.get(), func_name_, func_index_),
    4747      683867 :         isolate_, compilation_zone_.get(), Code::WASM_FUNCTION));
    4748             :     ZoneVector<trap_handler::ProtectedInstructionData> protected_instructions(
    4749             :         compilation_zone_.get());
    4750             : 
    4751             :     job_.reset(Pipeline::NewWasmCompilationJob(
    4752             :         info_.get(), jsgraph_, descriptor, source_positions,
    4753      683805 :         &protected_instructions, env_->module->origin()));
    4754      227966 :     ok_ = job_->ExecuteJob() == CompilationJob::SUCCEEDED;
    4755             :     // TODO(bradnelson): Improve histogram handling of size_t.
    4756             :     counters()->wasm_compile_function_peak_memory_bytes()->AddSample(
    4757      683493 :         static_cast<int>(jsgraph_->graph()->zone()->allocation_size()));
    4758             : 
    4759      227922 :     if (FLAG_trace_wasm_decode_time) {
    4760           0 :       double pipeline_ms = pipeline_timer.Elapsed().InMillisecondsF();
    4761             :       PrintF(
    4762             :           "wasm-compilation phase 1 ok: %u bytes, %0.3f ms decode, %zu nodes, "
    4763             :           "%0.3f ms pipeline\n",
    4764           0 :           static_cast<unsigned>(func_body_.end - func_body_.start), decode_ms,
    4765           0 :           node_count, pipeline_ms);
    4766             :     }
    4767             :     // The graph zone is about to get out of scope. Avoid invalid references.
    4768      227922 :     jsgraph_ = nullptr;
    4769             :   }
    4770             : 
    4771             :   // Record the memory cost this unit places on the system until
    4772             :   // it is finalized.
    4773      227977 :   size_t cost = job_->AllocatedMemory();
    4774             :   set_memory_cost(cost);
    4775             : }
    4776             : 
    4777      233497 : MaybeHandle<Code> WasmCompilationUnit::FinishCompilation(
    4778             :     wasm::ErrorThrower* thrower) {
    4779      233497 :   if (!ok_) {
    4780        5743 :     if (graph_construction_result_.failed()) {
    4781             :       // Add the function as another context for the exception.
    4782             :       EmbeddedVector<char, 128> message;
    4783        5743 :       if (func_name_.start() == nullptr) {
    4784        5483 :         SNPrintF(message, "Compiling wasm function #%d failed", func_index_);
    4785             :       } else {
    4786             :         wasm::TruncatedUserString<> trunc_name(func_name_);
    4787             :         SNPrintF(message, "Compiling wasm function #%d:%.*s failed",
    4788         260 :                  func_index_, trunc_name.length(), trunc_name.start());
    4789             :       }
    4790        5743 :       thrower->CompileFailed(message.start(), graph_construction_result_);
    4791             :     }
    4792             : 
    4793        5743 :     return {};
    4794             :   }
    4795             :   base::ElapsedTimer codegen_timer;
    4796      227754 :   if (FLAG_trace_wasm_decode_time) {
    4797             :     codegen_timer.Start();
    4798             :   }
    4799      227754 :   if (job_->FinalizeJob() != CompilationJob::SUCCEEDED) {
    4800           0 :     return Handle<Code>::null();
    4801             :   }
    4802             :   Handle<Code> code = info_->code();
    4803             :   DCHECK(!code.is_null());
    4804             : 
    4805      455508 :   if (must_record_function_compilation(isolate_)) {
    4806             :     wasm::TruncatedUserString<> trunc_name(func_name_);
    4807             :     RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate_, code,
    4808             :                               "wasm_function#%d:%.*s", func_index_,
    4809           0 :                               trunc_name.length(), trunc_name.start());
    4810             :   }
    4811             : 
    4812      227754 :   if (FLAG_trace_wasm_decode_time) {
    4813           0 :     double codegen_ms = codegen_timer.Elapsed().InMillisecondsF();
    4814             :     PrintF("wasm-code-generation ok: %u bytes, %0.3f ms code generation\n",
    4815           0 :            static_cast<unsigned>(func_body_.end - func_body_.start),
    4816           0 :            codegen_ms);
    4817             :   }
    4818             : 
    4819      227754 :   return code;
    4820             : }
    4821             : 
    4822             : // static
    4823      143535 : MaybeHandle<Code> WasmCompilationUnit::CompileWasmFunction(
    4824             :     wasm::ErrorThrower* thrower, Isolate* isolate,
    4825             :     const wasm::ModuleWireBytes& wire_bytes, ModuleEnv* env,
    4826             :     const wasm::WasmFunction* function) {
    4827             :   wasm::FunctionBody function_body{
    4828      143535 :       function->sig, function->code.offset(),
    4829      143535 :       wire_bytes.start() + function->code.offset(),
    4830      287070 :       wire_bytes.start() + function->code.end_offset()};
    4831             :   WasmCompilationUnit unit(
    4832             :       isolate, env, function_body, wire_bytes.GetNameOrNull(function),
    4833      287070 :       function->func_index, CEntryStub(isolate, 1).GetCode());
    4834      143535 :   unit.ExecuteCompilation();
    4835      143535 :   return unit.FinishCompilation(thrower);
    4836             : }
    4837             : 
    4838             : #undef WASM_64
    4839             : #undef FATAL_UNSUPPORTED_OPCODE
    4840             : 
    4841             : }  // namespace compiler
    4842             : }  // namespace internal
    4843             : }  // namespace v8

Generated by: LCOV version 1.10