LCOV - code coverage report
Current view: top level - src/compiler - wasm-compiler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1328 1759 75.5 %
Date: 2017-04-26 Functions: 124 168 73.8 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/wasm-compiler.h"
       6             : 
       7             : #include <memory>
       8             : 
       9             : #include "src/assembler-inl.h"
      10             : #include "src/base/platform/elapsed-timer.h"
      11             : #include "src/base/platform/platform.h"
      12             : #include "src/builtins/builtins.h"
      13             : #include "src/code-factory.h"
      14             : #include "src/code-stubs.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.h"
      38             : #include "src/wasm/wasm-opcodes.h"
      39             : #include "src/wasm/wasm-text.h"
      40             : 
      41             : // TODO(titzer): pull WASM_64 up to a common header.
      42             : #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64
      43             : #define WASM_64 1
      44             : #else
      45             : #define WASM_64 0
      46             : #endif
      47             : 
      48             : namespace v8 {
      49             : namespace internal {
      50             : namespace compiler {
      51             : 
      52             : namespace {
      53           0 : const Operator* UnsupportedOpcode(wasm::WasmOpcode opcode) {
      54             :   V8_Fatal(__FILE__, __LINE__, "Unsupported opcode #%d:%s", opcode,
      55           0 :            wasm::WasmOpcodes::OpcodeName(opcode));
      56             :   return nullptr;
      57             : }
      58             : 
      59      405540 : void MergeControlToEnd(JSGraph* jsgraph, Node* node) {
      60      202770 :   Graph* g = jsgraph->graph();
      61      202770 :   if (g->end()) {
      62       63713 :     NodeProperties::MergeControlToEnd(g, jsgraph->common(), node);
      63             :   } else {
      64      139057 :     g->SetEnd(g->NewNode(jsgraph->common()->End(1), node));
      65             :   }
      66      202775 : }
      67             : 
      68      170689 : Node* BuildModifyThreadInWasmFlag(bool new_value, JSGraph* jsgraph,
      69             :                                   Node** effect_ptr, Node* control) {
      70             :   // TODO(eholk): generate code to modify the thread-local storage directly,
      71             :   // rather than calling the runtime.
      72      138865 :   if (!trap_handler::UseTrapHandler()) {
      73             :     return control;
      74             :   }
      75             : 
      76             :   const Runtime::FunctionId f =
      77       10608 :       new_value ? Runtime::kSetThreadInWasm : Runtime::kClearThreadInWasm;
      78       10608 :   const Runtime::Function* fun = Runtime::FunctionForId(f);
      79             :   DCHECK_EQ(0, fun->nargs);
      80             :   const CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
      81             :       jsgraph->zone(), f, fun->nargs, Operator::kNoProperties,
      82       21216 :       CallDescriptor::kNoFlags);
      83             :   // CEntryStubConstant nodes have to be created and cached in the main
      84             :   // thread. At the moment this is only done for CEntryStubConstant(1).
      85             :   DCHECK_EQ(1, fun->result_size);
      86       10608 :   Node* inputs[] = {jsgraph->CEntryStubConstant(fun->result_size),
      87             :                     jsgraph->ExternalConstant(
      88       21216 :                         ExternalReference(f, jsgraph->isolate())),  // ref
      89       10608 :                     jsgraph->Int32Constant(fun->nargs),             // arity
      90             :                     jsgraph->NoContextConstant(),
      91             :                     *effect_ptr,
      92       42432 :                     control};
      93             : 
      94             :   Node* node = jsgraph->graph()->NewNode(jsgraph->common()->Call(desc),
      95       21216 :                                          arraysize(inputs), inputs);
      96       10607 :   *effect_ptr = node;
      97       10607 :   return node;
      98             : }
      99             : 
     100             : // Only call this function for code which is not reused across instantiations,
     101             : // as we do not patch the embedded context.
     102       13128 : Node* BuildCallToRuntimeWithContext(Runtime::FunctionId f, JSGraph* jsgraph,
     103             :                                     Node* context, Node** parameters,
     104             :                                     int parameter_count, Node** effect_ptr,
     105             :                                     Node** control) {
     106             :   // Setting and clearing the thread-in-wasm flag should not be done as a normal
     107             :   // runtime call.
     108             :   DCHECK_NE(f, Runtime::kSetThreadInWasm);
     109             :   DCHECK_NE(f, Runtime::kClearThreadInWasm);
     110             :   // We're leaving Wasm code, so clear the flag.
     111        3282 :   *control = BuildModifyThreadInWasmFlag(false, jsgraph, effect_ptr, *control);
     112             : 
     113        3282 :   const Runtime::Function* fun = Runtime::FunctionForId(f);
     114             :   CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
     115             :       jsgraph->zone(), f, fun->nargs, Operator::kNoProperties,
     116        6564 :       CallDescriptor::kNoFlags);
     117             :   // CEntryStubConstant nodes have to be created and cached in the main
     118             :   // thread. At the moment this is only done for CEntryStubConstant(1).
     119             :   DCHECK_EQ(1, fun->result_size);
     120             :   // At the moment we only allow 3 parameters. If more parameters are needed,
     121             :   // increase this constant accordingly.
     122             :   static const int kMaxParams = 3;
     123             :   DCHECK_GE(kMaxParams, parameter_count);
     124             :   Node* inputs[kMaxParams + 6];
     125             :   int count = 0;
     126        3282 :   inputs[count++] = jsgraph->CEntryStubConstant(fun->result_size);
     127        8745 :   for (int i = 0; i < parameter_count; i++) {
     128        5463 :     inputs[count++] = parameters[i];
     129             :   }
     130        3282 :   inputs[count++] = jsgraph->ExternalConstant(
     131        3282 :       ExternalReference(f, jsgraph->isolate()));         // ref
     132        3282 :   inputs[count++] = jsgraph->Int32Constant(fun->nargs);  // arity
     133        3282 :   inputs[count++] = context;                             // context
     134        3282 :   inputs[count++] = *effect_ptr;
     135        3282 :   inputs[count++] = *control;
     136             : 
     137             :   Node* node =
     138        6564 :       jsgraph->graph()->NewNode(jsgraph->common()->Call(desc), count, inputs);
     139        3282 :   *effect_ptr = node;
     140             : 
     141             :   // Restore the thread-in-wasm flag, since we have returned to Wasm.
     142        3282 :   *control = BuildModifyThreadInWasmFlag(true, jsgraph, effect_ptr, *control);
     143             : 
     144        3282 :   return node;
     145             : }
     146             : 
     147        3114 : Node* BuildCallToRuntime(Runtime::FunctionId f, JSGraph* jsgraph,
     148             :                          Node** parameters, int parameter_count,
     149             :                          Node** effect_ptr, Node** control) {
     150             :   return BuildCallToRuntimeWithContext(f, jsgraph, jsgraph->NoContextConstant(),
     151             :                                        parameters, parameter_count, effect_ptr,
     152        3114 :                                        control);
     153             : }
     154             : 
     155             : }  // namespace
     156             : 
     157      139360 : WasmGraphBuilder::WasmGraphBuilder(
     158             :     wasm::ModuleEnv* module_env, Zone* zone, JSGraph* jsgraph,
     159      598306 :     wasm::FunctionSig* sig,
     160             :     compiler::SourcePositionTable* source_position_table)
     161             :     : zone_(zone),
     162             :       jsgraph_(jsgraph),
     163             :       module_(module_env),
     164             :       signature_tables_(zone),
     165             :       function_tables_(zone),
     166             :       function_table_sizes_(zone),
     167             :       cur_buffer_(def_buffer_),
     168             :       cur_bufsize_(kDefaultBufferSize),
     169             :       sig_(sig),
     170      418080 :       source_position_table_(source_position_table) {
     171      483386 :   for (size_t i = sig->parameter_count(); i > 0 && !has_simd_; --i) {
     172      409332 :     if (sig->GetParam(i - 1) == wasm::kWasmS128) has_simd_ = true;
     173             :   }
     174      393640 :   for (size_t i = sig->return_count(); i > 0 && !has_simd_; --i) {
     175      229840 :     if (sig->GetReturn(i - 1) == wasm::kWasmS128) has_simd_ = true;
     176             :   }
     177             :   DCHECK_NOT_NULL(jsgraph_);
     178      139360 : }
     179             : 
     180           0 : Node* WasmGraphBuilder::Error() { return jsgraph()->Dead(); }
     181             : 
     182      278844 : Node* WasmGraphBuilder::Start(unsigned params) {
     183      278844 :   Node* start = graph()->NewNode(jsgraph()->common()->Start(params));
     184             :   graph()->SetStart(start);
     185      139418 :   return start;
     186             : }
     187             : 
     188      204584 : Node* WasmGraphBuilder::Param(unsigned index) {
     189             :   return graph()->NewNode(jsgraph()->common()->Parameter(index),
     190      409166 :                           graph()->start());
     191             : }
     192             : 
     193        8767 : Node* WasmGraphBuilder::Loop(Node* entry) {
     194       17534 :   return graph()->NewNode(jsgraph()->common()->Loop(1), entry);
     195             : }
     196             : 
     197       17534 : Node* WasmGraphBuilder::Terminate(Node* effect, Node* control) {
     198             :   Node* terminate =
     199        8767 :       graph()->NewNode(jsgraph()->common()->Terminate(), effect, control);
     200        8767 :   MergeControlToEnd(jsgraph(), terminate);
     201        8767 :   return terminate;
     202             : }
     203             : 
     204       14199 : unsigned WasmGraphBuilder::InputCount(Node* node) {
     205       14199 :   return static_cast<unsigned>(node->InputCount());
     206             : }
     207             : 
     208      940258 : bool WasmGraphBuilder::IsPhiWithMerge(Node* phi, Node* merge) {
     209     1180148 :   return phi && IrOpcode::IsPhiOpcode(phi->opcode()) &&
     210      710019 :          NodeProperties::GetControlInput(phi) == merge;
     211             : }
     212             : 
     213         644 : bool WasmGraphBuilder::ThrowsException(Node* node, Node** if_success,
     214         300 :                                        Node** if_exception) {
     215         644 :   if (node->op()->HasProperty(compiler::Operator::kNoThrow)) {
     216             :     return false;
     217             :   }
     218             : 
     219         300 :   *if_success = graph()->NewNode(jsgraph()->common()->IfSuccess(), node);
     220             :   *if_exception =
     221         300 :       graph()->NewNode(jsgraph()->common()->IfException(), node, node);
     222             : 
     223         150 :   return true;
     224             : }
     225             : 
     226       48082 : void WasmGraphBuilder::AppendToMerge(Node* merge, Node* from) {
     227             :   DCHECK(IrOpcode::IsMergeOpcode(merge->opcode()));
     228       24041 :   merge->AppendInput(jsgraph()->zone(), from);
     229             :   int new_size = merge->InputCount();
     230             :   NodeProperties::ChangeOp(
     231       24041 :       merge, jsgraph()->common()->ResizeMergeOrPhi(merge->op(), new_size));
     232       24041 : }
     233             : 
     234      325083 : void WasmGraphBuilder::AppendToPhi(Node* phi, Node* from) {
     235             :   DCHECK(IrOpcode::IsPhiOpcode(phi->opcode()));
     236             :   int new_size = phi->InputCount();
     237      216722 :   phi->InsertInput(jsgraph()->zone(), phi->InputCount() - 1, from);
     238             :   NodeProperties::ChangeOp(
     239      108361 :       phi, jsgraph()->common()->ResizeMergeOrPhi(phi->op(), new_size));
     240      108361 : }
     241             : 
     242      100732 : Node* WasmGraphBuilder::Merge(unsigned count, Node** controls) {
     243      151098 :   return graph()->NewNode(jsgraph()->common()->Merge(count), count, controls);
     244             : }
     245             : 
     246      130271 : Node* WasmGraphBuilder::Phi(wasm::ValueType type, unsigned count, Node** vals,
     247      130271 :                             Node* control) {
     248             :   DCHECK(IrOpcode::IsMergeOpcode(control->opcode()));
     249      130271 :   Node** buf = Realloc(vals, count, count + 1);
     250      130271 :   buf[count] = control;
     251             :   return graph()->NewNode(jsgraph()->common()->Phi(type, count), count + 1,
     252      390813 :                           buf);
     253             : }
     254             : 
     255       33778 : Node* WasmGraphBuilder::EffectPhi(unsigned count, Node** effects,
     256       33778 :                                   Node* control) {
     257             :   DCHECK(IrOpcode::IsMergeOpcode(control->opcode()));
     258       33778 :   Node** buf = Realloc(effects, count, count + 1);
     259       33778 :   buf[count] = control;
     260             :   return graph()->NewNode(jsgraph()->common()->EffectPhi(count), count + 1,
     261      101334 :                           buf);
     262             : }
     263             : 
     264           0 : Node* WasmGraphBuilder::NumberConstant(int32_t value) {
     265           0 :   return jsgraph()->Constant(value);
     266             : }
     267             : 
     268        2364 : Node* WasmGraphBuilder::Uint32Constant(uint32_t value) {
     269           0 :   return jsgraph()->Uint32Constant(value);
     270             : }
     271             : 
     272      466397 : Node* WasmGraphBuilder::Int32Constant(int32_t value) {
     273      466562 :   return jsgraph()->Int32Constant(value);
     274             : }
     275             : 
     276        5201 : Node* WasmGraphBuilder::Int64Constant(int64_t value) {
     277        5201 :   return jsgraph()->Int64Constant(value);
     278             : }
     279             : 
     280       80551 : void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position,
     281      785129 :                                   Node** effect, Node** control) {
     282      105004 :   if (FLAG_wasm_no_stack_checks) return;
     283             :   // We do not generate stack checks for cctests.
     284      139429 :   if (!module_ || (module_->instance && module_->instance->context.is_null()))
     285             :     return;
     286       56098 :   if (effect == nullptr) effect = effect_;
     287       56098 :   if (control == nullptr) control = control_;
     288             : 
     289             :   Node* limit = graph()->NewNode(
     290             :       jsgraph()->machine()->Load(MachineType::Pointer()),
     291             :       jsgraph()->ExternalConstant(
     292             :           ExternalReference::address_of_stack_limit(jsgraph()->isolate())),
     293      280452 :       jsgraph()->IntPtrConstant(0), *effect, *control);
     294       56095 :   Node* pointer = graph()->NewNode(jsgraph()->machine()->LoadStackPointer());
     295             : 
     296             :   Node* check =
     297       56074 :       graph()->NewNode(jsgraph()->machine()->UintLessThan(), limit, pointer);
     298             : 
     299      112144 :   Diamond stack_check(graph(), jsgraph()->common(), check, BranchHint::kTrue);
     300       56058 :   stack_check.Chain(*control);
     301       56076 :   Node* effect_true = *effect;
     302             : 
     303       56076 :   Handle<Code> code = jsgraph()->isolate()->builtins()->WasmStackGuard();
     304             :   CallInterfaceDescriptor idesc =
     305      112152 :       WasmRuntimeCallDescriptor(jsgraph()->isolate());
     306             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
     307             :       jsgraph()->isolate(), jsgraph()->zone(), idesc, 0,
     308       56079 :       CallDescriptor::kNoFlags, Operator::kNoProperties);
     309       56067 :   Node* stub_code = jsgraph()->HeapConstant(code);
     310             : 
     311             :   Node* context = jsgraph()->NoContextConstant();
     312             :   Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), stub_code,
     313      112170 :                                 context, *effect, stack_check.if_false);
     314             : 
     315       56083 :   SetSourcePosition(call, position);
     316             : 
     317             :   Node* ephi = graph()->NewNode(jsgraph()->common()->EffectPhi(2), effect_true,
     318      112150 :                                 call, stack_check.merge);
     319             : 
     320       56082 :   *control = stack_check.merge;
     321       56082 :   *effect = ephi;
     322             : }
     323             : 
     324      428824 : Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
     325      428824 :                               wasm::WasmCodePosition position) {
     326             :   const Operator* op;
     327      428824 :   MachineOperatorBuilder* m = jsgraph()->machine();
     328      428824 :   switch (opcode) {
     329             :     case wasm::kExprI32Add:
     330      106817 :       op = m->Int32Add();
     331      106817 :       break;
     332             :     case wasm::kExprI32Sub:
     333       20639 :       op = m->Int32Sub();
     334       20643 :       break;
     335             :     case wasm::kExprI32Mul:
     336        4818 :       op = m->Int32Mul();
     337        4818 :       break;
     338             :     case wasm::kExprI32DivS:
     339         151 :       return BuildI32DivS(left, right, position);
     340             :     case wasm::kExprI32DivU:
     341         105 :       return BuildI32DivU(left, right, position);
     342             :     case wasm::kExprI32RemS:
     343          58 :       return BuildI32RemS(left, right, position);
     344             :     case wasm::kExprI32RemU:
     345          74 :       return BuildI32RemU(left, right, position);
     346             :     case wasm::kExprI32And:
     347      112220 :       op = m->Word32And();
     348      112220 :       break;
     349             :     case wasm::kExprI32Ior:
     350        7033 :       op = m->Word32Or();
     351        7033 :       break;
     352             :     case wasm::kExprI32Xor:
     353        1169 :       op = m->Word32Xor();
     354        1169 :       break;
     355             :     case wasm::kExprI32Shl:
     356       14756 :       op = m->Word32Shl();
     357       14756 :       right = MaskShiftCount32(right);
     358       14756 :       break;
     359             :     case wasm::kExprI32ShrU:
     360        7472 :       op = m->Word32Shr();
     361        7472 :       right = MaskShiftCount32(right);
     362        7472 :       break;
     363             :     case wasm::kExprI32ShrS:
     364        1765 :       op = m->Word32Sar();
     365        1765 :       right = MaskShiftCount32(right);
     366        1765 :       break;
     367             :     case wasm::kExprI32Ror:
     368          70 :       op = m->Word32Ror();
     369          70 :       right = MaskShiftCount32(right);
     370          70 :       break;
     371             :     case wasm::kExprI32Rol:
     372          35 :       right = MaskShiftCount32(right);
     373          35 :       return BuildI32Rol(left, right);
     374             :     case wasm::kExprI32Eq:
     375       46591 :       op = m->Word32Equal();
     376       46591 :       break;
     377             :     case wasm::kExprI32Ne:
     378        6387 :       return Invert(Binop(wasm::kExprI32Eq, left, right));
     379             :     case wasm::kExprI32LtS:
     380        6253 :       op = m->Int32LessThan();
     381        6253 :       break;
     382             :     case wasm::kExprI32LeS:
     383        1068 :       op = m->Int32LessThanOrEqual();
     384        1068 :       break;
     385             :     case wasm::kExprI32LtU:
     386        5692 :       op = m->Uint32LessThan();
     387        5692 :       break;
     388             :     case wasm::kExprI32LeU:
     389         130 :       op = m->Uint32LessThanOrEqual();
     390         130 :       break;
     391             :     case wasm::kExprI32GtS:
     392        9022 :       op = m->Int32LessThan();
     393             :       std::swap(left, right);
     394             :       break;
     395             :     case wasm::kExprI32GeS:
     396         653 :       op = m->Int32LessThanOrEqual();
     397             :       std::swap(left, right);
     398             :       break;
     399             :     case wasm::kExprI32GtU:
     400        2255 :       op = m->Uint32LessThan();
     401             :       std::swap(left, right);
     402             :       break;
     403             :     case wasm::kExprI32GeU:
     404          88 :       op = m->Uint32LessThanOrEqual();
     405             :       std::swap(left, right);
     406             :       break;
     407             :     case wasm::kExprI64And:
     408          63 :       op = m->Word64And();
     409          63 :       break;
     410             :     case wasm::kExprI64Add:
     411          86 :       op = m->Int64Add();
     412          86 :       break;
     413             :     case wasm::kExprI64Sub:
     414         138 :       op = m->Int64Sub();
     415         138 :       break;
     416             :     case wasm::kExprI64Mul:
     417         146 :       op = m->Int64Mul();
     418         146 :       break;
     419             :     case wasm::kExprI64DivS:
     420         105 :       return BuildI64DivS(left, right, position);
     421             :     case wasm::kExprI64DivU:
     422          35 :       return BuildI64DivU(left, right, position);
     423             :     case wasm::kExprI64RemS:
     424          35 :       return BuildI64RemS(left, right, position);
     425             :     case wasm::kExprI64RemU:
     426          50 :       return BuildI64RemU(left, right, position);
     427             :     case wasm::kExprI64Ior:
     428          71 :       op = m->Word64Or();
     429          71 :       break;
     430             :     case wasm::kExprI64Xor:
     431          70 :       op = m->Word64Xor();
     432          70 :       break;
     433             :     case wasm::kExprI64Shl:
     434         212 :       op = m->Word64Shl();
     435         212 :       right = MaskShiftCount64(right);
     436         212 :       break;
     437             :     case wasm::kExprI64ShrU:
     438         286 :       op = m->Word64Shr();
     439         286 :       right = MaskShiftCount64(right);
     440         286 :       break;
     441             :     case wasm::kExprI64ShrS:
     442          63 :       op = m->Word64Sar();
     443          63 :       right = MaskShiftCount64(right);
     444          63 :       break;
     445             :     case wasm::kExprI64Eq:
     446          56 :       op = m->Word64Equal();
     447          56 :       break;
     448             :     case wasm::kExprI64Ne:
     449          28 :       return Invert(Binop(wasm::kExprI64Eq, left, right));
     450             :     case wasm::kExprI64LtS:
     451          43 :       op = m->Int64LessThan();
     452          43 :       break;
     453             :     case wasm::kExprI64LeS:
     454          28 :       op = m->Int64LessThanOrEqual();
     455          28 :       break;
     456             :     case wasm::kExprI64LtU:
     457          28 :       op = m->Uint64LessThan();
     458          28 :       break;
     459             :     case wasm::kExprI64LeU:
     460          28 :       op = m->Uint64LessThanOrEqual();
     461          28 :       break;
     462             :     case wasm::kExprI64GtS:
     463          28 :       op = m->Int64LessThan();
     464             :       std::swap(left, right);
     465             :       break;
     466             :     case wasm::kExprI64GeS:
     467          28 :       op = m->Int64LessThanOrEqual();
     468             :       std::swap(left, right);
     469             :       break;
     470             :     case wasm::kExprI64GtU:
     471          28 :       op = m->Uint64LessThan();
     472             :       std::swap(left, right);
     473             :       break;
     474             :     case wasm::kExprI64GeU:
     475          28 :       op = m->Uint64LessThanOrEqual();
     476             :       std::swap(left, right);
     477             :       break;
     478             :     case wasm::kExprI64Ror:
     479          84 :       op = m->Word64Ror();
     480          84 :       right = MaskShiftCount64(right);
     481          84 :       break;
     482             :     case wasm::kExprI64Rol:
     483          42 :       return BuildI64Rol(left, right);
     484             :     case wasm::kExprF32CopySign:
     485          14 :       return BuildF32CopySign(left, right);
     486             :     case wasm::kExprF64CopySign:
     487          14 :       return BuildF64CopySign(left, right);
     488             :     case wasm::kExprF32Add:
     489         109 :       op = m->Float32Add();
     490         109 :       break;
     491             :     case wasm::kExprF32Sub:
     492         110 :       op = m->Float32Sub();
     493         110 :       break;
     494             :     case wasm::kExprF32Mul:
     495          42 :       op = m->Float32Mul();
     496          42 :       break;
     497             :     case wasm::kExprF32Div:
     498          39 :       op = m->Float32Div();
     499          39 :       break;
     500             :     case wasm::kExprF32Eq:
     501         265 :       op = m->Float32Equal();
     502         265 :       break;
     503             :     case wasm::kExprF32Ne:
     504         175 :       return Invert(Binop(wasm::kExprF32Eq, left, right));
     505             :     case wasm::kExprF32Lt:
     506          32 :       op = m->Float32LessThan();
     507          32 :       break;
     508             :     case wasm::kExprF32Ge:
     509          32 :       op = m->Float32LessThanOrEqual();
     510             :       std::swap(left, right);
     511             :       break;
     512             :     case wasm::kExprF32Gt:
     513          32 :       op = m->Float32LessThan();
     514             :       std::swap(left, right);
     515             :       break;
     516             :     case wasm::kExprF32Le:
     517          32 :       op = m->Float32LessThanOrEqual();
     518          32 :       break;
     519             :     case wasm::kExprF64Add:
     520        4355 :       op = m->Float64Add();
     521        4355 :       break;
     522             :     case wasm::kExprF64Sub:
     523        3682 :       op = m->Float64Sub();
     524        3682 :       break;
     525             :     case wasm::kExprF64Mul:
     526        8697 :       op = m->Float64Mul();
     527        8697 :       break;
     528             :     case wasm::kExprF64Div:
     529         464 :       op = m->Float64Div();
     530         464 :       break;
     531             :     case wasm::kExprF64Eq:
     532         874 :       op = m->Float64Equal();
     533         874 :       break;
     534             :     case wasm::kExprF64Ne:
     535         332 :       return Invert(Binop(wasm::kExprF64Eq, left, right));
     536             :     case wasm::kExprF64Lt:
     537         854 :       op = m->Float64LessThan();
     538         854 :       break;
     539             :     case wasm::kExprF64Le:
     540         228 :       op = m->Float64LessThanOrEqual();
     541         228 :       break;
     542             :     case wasm::kExprF64Gt:
     543         841 :       op = m->Float64LessThan();
     544             :       std::swap(left, right);
     545             :       break;
     546             :     case wasm::kExprF64Ge:
     547         312 :       op = m->Float64LessThanOrEqual();
     548             :       std::swap(left, right);
     549             :       break;
     550             :     case wasm::kExprF32Min:
     551          32 :       op = m->Float32Min();
     552          32 :       break;
     553             :     case wasm::kExprF64Min:
     554          48 :       op = m->Float64Min();
     555          48 :       break;
     556             :     case wasm::kExprF32Max:
     557          32 :       op = m->Float32Max();
     558          32 :       break;
     559             :     case wasm::kExprF64Max:
     560          32 :       op = m->Float64Max();
     561          32 :       break;
     562             :     case wasm::kExprF64Pow:
     563          14 :       return BuildF64Pow(left, right);
     564             :     case wasm::kExprF64Atan2:
     565          16 :       op = m->Float64Atan2();
     566          16 :       break;
     567             :     case wasm::kExprF64Mod:
     568          28 :       return BuildF64Mod(left, right);
     569             :     case wasm::kExprI32AsmjsDivS:
     570         262 :       return BuildI32AsmjsDivS(left, right);
     571             :     case wasm::kExprI32AsmjsDivU:
     572          88 :       return BuildI32AsmjsDivU(left, right);
     573             :     case wasm::kExprI32AsmjsRemS:
     574         394 :       return BuildI32AsmjsRemS(left, right);
     575             :     case wasm::kExprI32AsmjsRemU:
     576         158 :       return BuildI32AsmjsRemU(left, right);
     577             :     case wasm::kExprI32AsmjsStoreMem8:
     578        3675 :       return BuildAsmjsStoreMem(MachineType::Int8(), left, right);
     579             :     case wasm::kExprI32AsmjsStoreMem16:
     580        1778 :       return BuildAsmjsStoreMem(MachineType::Int16(), left, right);
     581             :     case wasm::kExprI32AsmjsStoreMem:
     582       38534 :       return BuildAsmjsStoreMem(MachineType::Int32(), left, right);
     583             :     case wasm::kExprF32AsmjsStoreMem:
     584        4610 :       return BuildAsmjsStoreMem(MachineType::Float32(), left, right);
     585             :     case wasm::kExprF64AsmjsStoreMem:
     586         458 :       return BuildAsmjsStoreMem(MachineType::Float64(), left, right);
     587             :     default:
     588           0 :       op = UnsupportedOpcode(opcode);
     589             :   }
     590      371227 :   return graph()->NewNode(op, left, right);
     591             : }
     592             : 
     593      108196 : Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input,
     594      127484 :                              wasm::WasmCodePosition position) {
     595             :   const Operator* op;
     596      108196 :   MachineOperatorBuilder* m = jsgraph()->machine();
     597      108196 :   switch (opcode) {
     598             :     case wasm::kExprI32Eqz:
     599       19230 :       op = m->Word32Equal();
     600       38460 :       return graph()->NewNode(op, input, jsgraph()->Int32Constant(0));
     601             :     case wasm::kExprF32Abs:
     602          53 :       op = m->Float32Abs();
     603          53 :       break;
     604             :     case wasm::kExprF32Neg: {
     605          29 :       op = m->Float32Neg();
     606          29 :       break;
     607             :     }
     608             :     case wasm::kExprF32Sqrt:
     609          39 :       op = m->Float32Sqrt();
     610          39 :       break;
     611             :     case wasm::kExprF64Abs:
     612          74 :       op = m->Float64Abs();
     613          74 :       break;
     614             :     case wasm::kExprF64Neg: {
     615         194 :       op = m->Float64Neg();
     616         194 :       break;
     617             :     }
     618             :     case wasm::kExprF64Sqrt:
     619         165 :       op = m->Float64Sqrt();
     620         165 :       break;
     621             :     case wasm::kExprI32SConvertF64:
     622         149 :       return BuildI32SConvertF64(input, position);
     623             :     case wasm::kExprI32UConvertF64:
     624          14 :       return BuildI32UConvertF64(input, position);
     625             :     case wasm::kExprI32AsmjsSConvertF64:
     626          70 :       return BuildI32AsmjsSConvertF64(input);
     627             :     case wasm::kExprI32AsmjsUConvertF64:
     628           7 :       return BuildI32AsmjsUConvertF64(input);
     629             :     case wasm::kExprF32ConvertF64:
     630        4682 :       op = m->TruncateFloat64ToFloat32();
     631        4682 :       break;
     632             :     case wasm::kExprF64SConvertI32:
     633         686 :       op = m->ChangeInt32ToFloat64();
     634         686 :       break;
     635             :     case wasm::kExprF64UConvertI32:
     636         237 :       op = m->ChangeUint32ToFloat64();
     637         237 :       break;
     638             :     case wasm::kExprF32SConvertI32:
     639         172 :       op = m->RoundInt32ToFloat32();
     640         172 :       break;
     641             :     case wasm::kExprF32UConvertI32:
     642          47 :       op = m->RoundUint32ToFloat32();
     643          47 :       break;
     644             :     case wasm::kExprI32SConvertF32:
     645         133 :       return BuildI32SConvertF32(input, position);
     646             :     case wasm::kExprI32UConvertF32:
     647          14 :       return BuildI32UConvertF32(input, position);
     648             :     case wasm::kExprI32AsmjsSConvertF32:
     649           7 :       return BuildI32AsmjsSConvertF32(input);
     650             :     case wasm::kExprI32AsmjsUConvertF32:
     651           7 :       return BuildI32AsmjsUConvertF32(input);
     652             :     case wasm::kExprF64ConvertF32:
     653        7643 :       op = m->ChangeFloat32ToFloat64();
     654        7643 :       break;
     655             :     case wasm::kExprF32ReinterpretI32:
     656          60 :       op = m->BitcastInt32ToFloat32();
     657          60 :       break;
     658             :     case wasm::kExprI32ReinterpretF32:
     659         129 :       op = m->BitcastFloat32ToInt32();
     660         129 :       break;
     661             :     case wasm::kExprI32Clz:
     662        2084 :       op = m->Word32Clz();
     663        2084 :       break;
     664             :     case wasm::kExprI32Ctz: {
     665         469 :       if (m->Word32Ctz().IsSupported()) {
     666         469 :         op = m->Word32Ctz().op();
     667         469 :         break;
     668           0 :       } else if (m->Word32ReverseBits().IsSupported()) {
     669           0 :         Node* reversed = graph()->NewNode(m->Word32ReverseBits().op(), input);
     670           0 :         Node* result = graph()->NewNode(m->Word32Clz(), reversed);
     671           0 :         return result;
     672             :       } else {
     673           0 :         return BuildI32Ctz(input);
     674             :       }
     675             :     }
     676             :     case wasm::kExprI32Popcnt: {
     677          99 :       if (m->Word32Popcnt().IsSupported()) {
     678          99 :         op = m->Word32Popcnt().op();
     679          99 :         break;
     680             :       } else {
     681           0 :         return BuildI32Popcnt(input);
     682             :       }
     683             :     }
     684             :     case wasm::kExprF32Floor: {
     685          43 :       if (!m->Float32RoundDown().IsSupported()) return BuildF32Floor(input);
     686          43 :       op = m->Float32RoundDown().op();
     687          43 :       break;
     688             :     }
     689             :     case wasm::kExprF32Ceil: {
     690          43 :       if (!m->Float32RoundUp().IsSupported()) return BuildF32Ceil(input);
     691          43 :       op = m->Float32RoundUp().op();
     692          43 :       break;
     693             :     }
     694             :     case wasm::kExprF32Trunc: {
     695         161 :       if (!m->Float32RoundTruncate().IsSupported()) return BuildF32Trunc(input);
     696         161 :       op = m->Float32RoundTruncate().op();
     697         161 :       break;
     698             :     }
     699             :     case wasm::kExprF32NearestInt: {
     700          14 :       if (!m->Float32RoundTiesEven().IsSupported())
     701           0 :         return BuildF32NearestInt(input);
     702          14 :       op = m->Float32RoundTiesEven().op();
     703          14 :       break;
     704             :     }
     705             :     case wasm::kExprF64Floor: {
     706          65 :       if (!m->Float64RoundDown().IsSupported()) return BuildF64Floor(input);
     707          65 :       op = m->Float64RoundDown().op();
     708          65 :       break;
     709             :     }
     710             :     case wasm::kExprF64Ceil: {
     711          44 :       if (!m->Float64RoundUp().IsSupported()) return BuildF64Ceil(input);
     712          44 :       op = m->Float64RoundUp().op();
     713          44 :       break;
     714             :     }
     715             :     case wasm::kExprF64Trunc: {
     716         297 :       if (!m->Float64RoundTruncate().IsSupported()) return BuildF64Trunc(input);
     717         297 :       op = m->Float64RoundTruncate().op();
     718         297 :       break;
     719             :     }
     720             :     case wasm::kExprF64NearestInt: {
     721          14 :       if (!m->Float64RoundTiesEven().IsSupported())
     722           0 :         return BuildF64NearestInt(input);
     723          14 :       op = m->Float64RoundTiesEven().op();
     724          14 :       break;
     725             :     }
     726             :     case wasm::kExprF64Acos: {
     727          23 :       return BuildF64Acos(input);
     728             :     }
     729             :     case wasm::kExprF64Asin: {
     730          23 :       return BuildF64Asin(input);
     731             :     }
     732             :     case wasm::kExprF64Atan:
     733          23 :       op = m->Float64Atan();
     734          23 :       break;
     735             :     case wasm::kExprF64Cos: {
     736         198 :       op = m->Float64Cos();
     737         198 :       break;
     738             :     }
     739             :     case wasm::kExprF64Sin: {
     740         198 :       op = m->Float64Sin();
     741         198 :       break;
     742             :     }
     743             :     case wasm::kExprF64Tan: {
     744          23 :       op = m->Float64Tan();
     745          23 :       break;
     746             :     }
     747             :     case wasm::kExprF64Exp: {
     748          23 :       op = m->Float64Exp();
     749          23 :       break;
     750             :     }
     751             :     case wasm::kExprF64Log:
     752          23 :       op = m->Float64Log();
     753          23 :       break;
     754             :     case wasm::kExprI32ConvertI64:
     755        1117 :       op = m->TruncateInt64ToInt32();
     756        1117 :       break;
     757             :     case wasm::kExprI64SConvertI32:
     758          51 :       op = m->ChangeInt32ToInt64();
     759          51 :       break;
     760             :     case wasm::kExprI64UConvertI32:
     761          42 :       op = m->ChangeUint32ToUint64();
     762          42 :       break;
     763             :     case wasm::kExprF64ReinterpretI64:
     764         139 :       op = m->BitcastInt64ToFloat64();
     765         139 :       break;
     766             :     case wasm::kExprI64ReinterpretF64:
     767         272 :       op = m->BitcastFloat64ToInt64();
     768         272 :       break;
     769             :     case wasm::kExprI64Clz:
     770          29 :       op = m->Word64Clz();
     771          29 :       break;
     772             :     case wasm::kExprI64Ctz: {
     773         254 :       OptionalOperator ctz64 = m->Word64Ctz();
     774         254 :       if (ctz64.IsSupported()) {
     775             :         op = ctz64.op();
     776         254 :         break;
     777           0 :       } else if (m->Is32() && m->Word32Ctz().IsSupported()) {
     778             :         op = ctz64.placeholder();
     779             :         break;
     780           0 :       } else if (m->Word64ReverseBits().IsSupported()) {
     781           0 :         Node* reversed = graph()->NewNode(m->Word64ReverseBits().op(), input);
     782           0 :         Node* result = graph()->NewNode(m->Word64Clz(), reversed);
     783           0 :         return result;
     784             :       } else {
     785           0 :         return BuildI64Ctz(input);
     786             :       }
     787             :     }
     788             :     case wasm::kExprI64Popcnt: {
     789          36 :       OptionalOperator popcnt64 = m->Word64Popcnt();
     790          36 :       if (popcnt64.IsSupported()) {
     791             :         op = popcnt64.op();
     792           0 :       } else if (m->Is32() && m->Word32Popcnt().IsSupported()) {
     793             :         op = popcnt64.placeholder();
     794             :       } else {
     795           0 :         return BuildI64Popcnt(input);
     796             :       }
     797          36 :       break;
     798             :     }
     799             :     case wasm::kExprI64Eqz:
     800          58 :       op = m->Word64Equal();
     801         116 :       return graph()->NewNode(op, input, jsgraph()->Int64Constant(0));
     802             :     case wasm::kExprF32SConvertI64:
     803          74 :       if (m->Is32()) {
     804           0 :         return BuildF32SConvertI64(input);
     805             :       }
     806          74 :       op = m->RoundInt64ToFloat32();
     807          74 :       break;
     808             :     case wasm::kExprF32UConvertI64:
     809          14 :       if (m->Is32()) {
     810           0 :         return BuildF32UConvertI64(input);
     811             :       }
     812          14 :       op = m->RoundUint64ToFloat32();
     813          14 :       break;
     814             :     case wasm::kExprF64SConvertI64:
     815          58 :       if (m->Is32()) {
     816           0 :         return BuildF64SConvertI64(input);
     817             :       }
     818          58 :       op = m->RoundInt64ToFloat64();
     819          58 :       break;
     820             :     case wasm::kExprF64UConvertI64:
     821          14 :       if (m->Is32()) {
     822           0 :         return BuildF64UConvertI64(input);
     823             :       }
     824          14 :       op = m->RoundUint64ToFloat64();
     825          14 :       break;
     826             :     case wasm::kExprI64SConvertF32:
     827          21 :       return BuildI64SConvertF32(input, position);
     828             :     case wasm::kExprI64SConvertF64:
     829          44 :       return BuildI64SConvertF64(input, position);
     830             :     case wasm::kExprI64UConvertF32:
     831          21 :       return BuildI64UConvertF32(input, position);
     832             :     case wasm::kExprI64UConvertF64:
     833          21 :       return BuildI64UConvertF64(input, position);
     834             :     case wasm::kExprI32AsmjsLoadMem8S:
     835        3392 :       return BuildAsmjsLoadMem(MachineType::Int8(), input);
     836             :     case wasm::kExprI32AsmjsLoadMem8U:
     837        2693 :       return BuildAsmjsLoadMem(MachineType::Uint8(), input);
     838             :     case wasm::kExprI32AsmjsLoadMem16S:
     839        1087 :       return BuildAsmjsLoadMem(MachineType::Int16(), input);
     840             :     case wasm::kExprI32AsmjsLoadMem16U:
     841         664 :       return BuildAsmjsLoadMem(MachineType::Uint16(), input);
     842             :     case wasm::kExprI32AsmjsLoadMem:
     843       52399 :       return BuildAsmjsLoadMem(MachineType::Int32(), input);
     844             :     case wasm::kExprF32AsmjsLoadMem:
     845        7544 :       return BuildAsmjsLoadMem(MachineType::Float32(), input);
     846             :     case wasm::kExprF64AsmjsLoadMem:
     847         444 :       return BuildAsmjsLoadMem(MachineType::Float64(), input);
     848             :     default:
     849           0 :       op = UnsupportedOpcode(opcode);
     850             :   }
     851       20131 :   return graph()->NewNode(op, input);
     852             : }
     853             : 
     854         877 : Node* WasmGraphBuilder::Float32Constant(float value) {
     855         877 :   return jsgraph()->Float32Constant(value);
     856             : }
     857             : 
     858       12191 : Node* WasmGraphBuilder::Float64Constant(double value) {
     859       12191 :   return jsgraph()->Float64Constant(value);
     860             : }
     861             : 
     862      176299 : Node* WasmGraphBuilder::HeapConstant(Handle<HeapObject> value) {
     863      176299 :   return jsgraph()->HeapConstant(value);
     864             : }
     865             : 
     866             : namespace {
     867      487070 : Node* Branch(JSGraph* jsgraph, Node* cond, Node** true_node, Node** false_node,
     868             :              Node* control, BranchHint hint) {
     869             :   DCHECK_NOT_NULL(cond);
     870             :   DCHECK_NOT_NULL(control);
     871             :   Node* branch =
     872       81178 :       jsgraph->graph()->NewNode(jsgraph->common()->Branch(hint), cond, control);
     873      162357 :   *true_node = jsgraph->graph()->NewNode(jsgraph->common()->IfTrue(), branch);
     874      162358 :   *false_node = jsgraph->graph()->NewNode(jsgraph->common()->IfFalse(), branch);
     875       81179 :   return branch;
     876             : }
     877             : }  // namespace
     878             : 
     879       80803 : Node* WasmGraphBuilder::BranchNoHint(Node* cond, Node** true_node,
     880       80803 :                                      Node** false_node) {
     881             :   return Branch(jsgraph(), cond, true_node, false_node, *control_,
     882      161606 :                 BranchHint::kNone);
     883             : }
     884             : 
     885           0 : Node* WasmGraphBuilder::BranchExpectTrue(Node* cond, Node** true_node,
     886           0 :                                          Node** false_node) {
     887             :   return Branch(jsgraph(), cond, true_node, false_node, *control_,
     888           0 :                 BranchHint::kTrue);
     889             : }
     890             : 
     891           0 : Node* WasmGraphBuilder::BranchExpectFalse(Node* cond, Node** true_node,
     892         376 :                                           Node** false_node) {
     893             :   return Branch(jsgraph(), cond, true_node, false_node, *control_,
     894         752 :                 BranchHint::kFalse);
     895             : }
     896             : 
     897             : namespace {
     898       16600 : Builtins::Name GetBuiltinIdForTrap(bool in_cctest, wasm::TrapReason reason) {
     899       16600 :   if (in_cctest) {
     900             :     // We use Builtins::builtin_count as a marker to tell the code generator
     901             :     // to generate a call to a testing c-function instead of a runtime
     902             :     // function. This code should only be called from a cctest.
     903             :     return Builtins::builtin_count;
     904             :   }
     905             : 
     906       10502 :   switch (reason) {
     907             : #define TRAPREASON_TO_MESSAGE(name) \
     908             :   case wasm::k##name:               \
     909             :     return Builtins::kThrowWasm##name;
     910        7377 :     FOREACH_WASM_TRAPREASON(TRAPREASON_TO_MESSAGE)
     911             : #undef TRAPREASON_TO_MESSAGE
     912             :     default:
     913           0 :       UNREACHABLE();
     914             :       return Builtins::builtin_count;
     915             :   }
     916             : }
     917             : }  // namespace
     918             : 
     919         882 : Node* WasmGraphBuilder::TrapIfTrue(wasm::TrapReason reason, Node* cond,
     920        2646 :                                    wasm::WasmCodePosition position) {
     921             :   // TODO(wasm): Introduce a testing flag instead of trying to infer it here.
     922             :   bool in_cctest =
     923        1666 :       !module_ || (module_->instance && module_->instance->context.is_null());
     924         882 :   int32_t trap_id = GetBuiltinIdForTrap(in_cctest, reason);
     925             :   Node* node = graph()->NewNode(jsgraph()->common()->TrapIf(trap_id), cond,
     926         882 :                                 Effect(), Control());
     927         882 :   *control_ = node;
     928         882 :   SetSourcePosition(node, position);
     929         882 :   return node;
     930             : }
     931             : 
     932       15717 : Node* WasmGraphBuilder::TrapIfFalse(wasm::TrapReason reason, Node* cond,
     933       47154 :                                     wasm::WasmCodePosition position) {
     934             :   // TODO(wasm): Introduce a testing flag instead of trying to infer it here.
     935             :   bool in_cctest =
     936       29852 :       !module_ || (module_->instance && module_->instance->context.is_null());
     937       15717 :   int32_t trap_id = GetBuiltinIdForTrap(in_cctest, reason);
     938             : 
     939             :   Node* node = graph()->NewNode(jsgraph()->common()->TrapUnless(trap_id), cond,
     940       15718 :                                 Effect(), Control());
     941       15716 :   *control_ = node;
     942       15716 :   SetSourcePosition(node, position);
     943       15716 :   return node;
     944             : }
     945             : 
     946             : // Add a check that traps if {node} is equal to {val}.
     947         545 : Node* WasmGraphBuilder::TrapIfEq32(wasm::TrapReason reason, Node* node,
     948             :                                    int32_t val,
     949         256 :                                    wasm::WasmCodePosition position) {
     950             :   Int32Matcher m(node);
     951         862 :   if (m.HasValue() && !m.Is(val)) return graph()->start();
     952         416 :   if (val == 0) {
     953         288 :     return TrapIfFalse(reason, node, position);
     954             :   } else {
     955             :     return TrapIfTrue(reason,
     956             :                       graph()->NewNode(jsgraph()->machine()->Word32Equal(),
     957             :                                        node, jsgraph()->Int32Constant(val)),
     958         384 :                       position);
     959             :   }
     960             : }
     961             : 
     962             : // Add a check that traps if {node} is zero.
     963           0 : Node* WasmGraphBuilder::ZeroCheck32(wasm::TrapReason reason, Node* node,
     964             :                                     wasm::WasmCodePosition position) {
     965         388 :   return TrapIfEq32(reason, node, 0, position);
     966             : }
     967             : 
     968             : // Add a check that traps if {node} is equal to {val}.
     969         437 : Node* WasmGraphBuilder::TrapIfEq64(wasm::TrapReason reason, Node* node,
     970             :                                    int64_t val,
     971         648 :                                    wasm::WasmCodePosition position) {
     972             :   Int64Matcher m(node);
     973         670 :   if (m.HasValue() && !m.Is(val)) return graph()->start();
     974             :   return TrapIfTrue(reason,
     975             :                     graph()->NewNode(jsgraph()->machine()->Word64Equal(), node,
     976             :                                      jsgraph()->Int64Constant(val)),
     977         972 :                     position);
     978             : }
     979             : 
     980             : // Add a check that traps if {node} is zero.
     981           0 : Node* WasmGraphBuilder::ZeroCheck64(wasm::TrapReason reason, Node* node,
     982             :                                     wasm::WasmCodePosition position) {
     983         332 :   return TrapIfEq64(reason, node, 0, position);
     984             : }
     985             : 
     986       15278 : Node* WasmGraphBuilder::Switch(unsigned count, Node* key) {
     987       22917 :   return graph()->NewNode(jsgraph()->common()->Switch(count), key, *control_);
     988             : }
     989             : 
     990       48425 : Node* WasmGraphBuilder::IfValue(int32_t value, Node* sw) {
     991             :   DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
     992       96850 :   return graph()->NewNode(jsgraph()->common()->IfValue(value), sw);
     993             : }
     994             : 
     995        7624 : Node* WasmGraphBuilder::IfDefault(Node* sw) {
     996             :   DCHECK_EQ(IrOpcode::kSwitch, sw->opcode());
     997       15248 :   return graph()->NewNode(jsgraph()->common()->IfDefault(), sw);
     998             : }
     999             : 
    1000      775879 : Node* WasmGraphBuilder::Return(unsigned count, Node** vals) {
    1001             :   DCHECK_NOT_NULL(*control_);
    1002             :   DCHECK_NOT_NULL(*effect_);
    1003             : 
    1004             :   static const int kStackAllocatedNodeBufferSize = 8;
    1005             :   Node* stack_buffer[kStackAllocatedNodeBufferSize];
    1006             :   std::vector<Node*> heap_buffer;
    1007             : 
    1008             :   Node** buf = stack_buffer;
    1009      193904 :   if (count + 3 > kStackAllocatedNodeBufferSize) {
    1010           0 :     heap_buffer.resize(count + 3);
    1011             :     buf = heap_buffer.data();
    1012             :   }
    1013             : 
    1014      193904 :   buf[0] = jsgraph()->Int32Constant(0);
    1015      194024 :   memcpy(buf + 1, vals, sizeof(void*) * count);
    1016      194024 :   buf[count + 1] = *effect_;
    1017      194024 :   buf[count + 2] = *control_;
    1018             :   Node* ret =
    1019      581984 :       graph()->NewNode(jsgraph()->common()->Return(count), count + 3, buf);
    1020             : 
    1021      194047 :   MergeControlToEnd(jsgraph(), ret);
    1022      193987 :   return ret;
    1023             : }
    1024             : 
    1025         514 : Node* WasmGraphBuilder::ReturnVoid() { return Return(0, nullptr); }
    1026             : 
    1027         439 : Node* WasmGraphBuilder::Unreachable(wasm::WasmCodePosition position) {
    1028         439 :   TrapIfFalse(wasm::TrapReason::kTrapUnreachable, Int32Constant(0), position);
    1029             :   ReturnVoid();
    1030         439 :   return nullptr;
    1031             : }
    1032             : 
    1033       24140 : Node* WasmGraphBuilder::MaskShiftCount32(Node* node) {
    1034             :   static const int32_t kMask32 = 0x1f;
    1035       48196 :   if (!jsgraph()->machine()->Word32ShiftIsSafe()) {
    1036             :     // Shifts by constants are so common we pattern-match them here.
    1037             :     Int32Matcher match(node);
    1038          42 :     if (match.HasValue()) {
    1039           0 :       int32_t masked = (match.Value() & kMask32);
    1040           0 :       if (match.Value() != masked) node = jsgraph()->Int32Constant(masked);
    1041             :     } else {
    1042             :       node = graph()->NewNode(jsgraph()->machine()->Word32And(), node,
    1043          84 :                               jsgraph()->Int32Constant(kMask32));
    1044             :     }
    1045             :   }
    1046       24098 :   return node;
    1047             : }
    1048             : 
    1049         680 : Node* WasmGraphBuilder::MaskShiftCount64(Node* node) {
    1050             :   static const int64_t kMask64 = 0x3f;
    1051        1290 :   if (!jsgraph()->machine()->Word32ShiftIsSafe()) {
    1052             :     // Shifts by constants are so common we pattern-match them here.
    1053             :     Int64Matcher match(node);
    1054          35 :     if (match.HasValue()) {
    1055           0 :       int64_t masked = (match.Value() & kMask64);
    1056           0 :       if (match.Value() != masked) node = jsgraph()->Int64Constant(masked);
    1057             :     } else {
    1058             :       node = graph()->NewNode(jsgraph()->machine()->Word64And(), node,
    1059          70 :                               jsgraph()->Int64Constant(kMask64));
    1060             :     }
    1061             :   }
    1062         645 :   return node;
    1063             : }
    1064             : 
    1065           0 : static bool ReverseBytesSupported(MachineOperatorBuilder* m,
    1066             :                                   size_t size_in_bytes) {
    1067           0 :   switch (size_in_bytes) {
    1068             :     case 4:
    1069           0 :       return m->Word32ReverseBytes().IsSupported();
    1070             :     case 8:
    1071           0 :       return m->Word64ReverseBytes().IsSupported();
    1072             :     default:
    1073             :       break;
    1074             :   }
    1075             :   return false;
    1076             : }
    1077             : 
    1078           0 : Node* WasmGraphBuilder::BuildChangeEndianness(Node* node, MachineType memtype,
    1079           0 :                                               wasm::ValueType wasmtype) {
    1080             :   Node* result;
    1081             :   Node* value = node;
    1082           0 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1083           0 :   int valueSizeInBytes = 1 << ElementSizeLog2Of(memtype.representation());
    1084           0 :   int valueSizeInBits = 8 * valueSizeInBytes;
    1085             :   bool isFloat = false;
    1086             : 
    1087           0 :   switch (memtype.representation()) {
    1088             :     case MachineRepresentation::kFloat64:
    1089           0 :       value = graph()->NewNode(m->BitcastFloat64ToInt64(), node);
    1090             :       isFloat = true;
    1091             :     case MachineRepresentation::kWord64:
    1092           0 :       result = jsgraph()->Int64Constant(0);
    1093           0 :       break;
    1094             :     case MachineRepresentation::kFloat32:
    1095           0 :       value = graph()->NewNode(m->BitcastFloat32ToInt32(), node);
    1096             :       isFloat = true;
    1097             :     case MachineRepresentation::kWord32:
    1098             :     case MachineRepresentation::kWord16:
    1099           0 :       result = jsgraph()->Int32Constant(0);
    1100           0 :       break;
    1101             :     case MachineRepresentation::kWord8:
    1102             :       // No need to change endianness for byte size, return original node
    1103             :       return node;
    1104             :       break;
    1105             :     default:
    1106           0 :       UNREACHABLE();
    1107             :       break;
    1108             :   }
    1109             : 
    1110             :   int i;
    1111             :   uint32_t shiftCount;
    1112             : 
    1113           0 :   if (ReverseBytesSupported(m, valueSizeInBytes < 4 ? 4 : valueSizeInBytes)) {
    1114           0 :     switch (valueSizeInBytes) {
    1115             :       case 2:
    1116             :         result =
    1117             :             graph()->NewNode(m->Word32ReverseBytes().op(),
    1118             :                              graph()->NewNode(m->Word32Shl(), value,
    1119           0 :                                               jsgraph()->Int32Constant(16)));
    1120           0 :         break;
    1121             :       case 4:
    1122           0 :         result = graph()->NewNode(m->Word32ReverseBytes().op(), value);
    1123           0 :         break;
    1124             :       case 8:
    1125           0 :         result = graph()->NewNode(m->Word64ReverseBytes().op(), value);
    1126           0 :         break;
    1127             :       default:
    1128           0 :         UNREACHABLE();
    1129             :     }
    1130             :   } else {
    1131           0 :     for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2;
    1132             :          i += 8, shiftCount -= 16) {
    1133             :       Node* shiftLower;
    1134             :       Node* shiftHigher;
    1135             :       Node* lowerByte;
    1136             :       Node* higherByte;
    1137             : 
    1138             :       DCHECK(shiftCount > 0);
    1139             :       DCHECK((shiftCount + 8) % 16 == 0);
    1140             : 
    1141           0 :       if (valueSizeInBits > 32) {
    1142             :         shiftLower = graph()->NewNode(m->Word64Shl(), value,
    1143           0 :                                       jsgraph()->Int64Constant(shiftCount));
    1144             :         shiftHigher = graph()->NewNode(m->Word64Shr(), value,
    1145           0 :                                        jsgraph()->Int64Constant(shiftCount));
    1146             :         lowerByte = graph()->NewNode(
    1147             :             m->Word64And(), shiftLower,
    1148             :             jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF)
    1149           0 :                                      << (valueSizeInBits - 8 - i)));
    1150             :         higherByte = graph()->NewNode(
    1151             :             m->Word64And(), shiftHigher,
    1152           0 :             jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i));
    1153           0 :         result = graph()->NewNode(m->Word64Or(), result, lowerByte);
    1154           0 :         result = graph()->NewNode(m->Word64Or(), result, higherByte);
    1155             :       } else {
    1156             :         shiftLower = graph()->NewNode(m->Word32Shl(), value,
    1157           0 :                                       jsgraph()->Int32Constant(shiftCount));
    1158             :         shiftHigher = graph()->NewNode(m->Word32Shr(), value,
    1159           0 :                                        jsgraph()->Int32Constant(shiftCount));
    1160             :         lowerByte = graph()->NewNode(
    1161             :             m->Word32And(), shiftLower,
    1162             :             jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF)
    1163           0 :                                      << (valueSizeInBits - 8 - i)));
    1164             :         higherByte = graph()->NewNode(
    1165             :             m->Word32And(), shiftHigher,
    1166           0 :             jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i));
    1167           0 :         result = graph()->NewNode(m->Word32Or(), result, lowerByte);
    1168           0 :         result = graph()->NewNode(m->Word32Or(), result, higherByte);
    1169             :       }
    1170             :     }
    1171             :   }
    1172             : 
    1173           0 :   if (isFloat) {
    1174           0 :     switch (memtype.representation()) {
    1175             :       case MachineRepresentation::kFloat64:
    1176           0 :         result = graph()->NewNode(m->BitcastInt64ToFloat64(), result);
    1177           0 :         break;
    1178             :       case MachineRepresentation::kFloat32:
    1179           0 :         result = graph()->NewNode(m->BitcastInt32ToFloat32(), result);
    1180           0 :         break;
    1181             :       default:
    1182           0 :         UNREACHABLE();
    1183             :         break;
    1184             :     }
    1185             :   }
    1186             : 
    1187             :   // We need to sign extend the value
    1188           0 :   if (memtype.IsSigned()) {
    1189             :     DCHECK(!isFloat);
    1190           0 :     if (valueSizeInBits < 32) {
    1191             :       Node* shiftBitCount;
    1192             :       // Perform sign extension using following trick
    1193             :       // result = (x << machine_width - type_width) >> (machine_width -
    1194             :       // type_width)
    1195           0 :       if (wasmtype == wasm::kWasmI64) {
    1196           0 :         shiftBitCount = jsgraph()->Int32Constant(64 - valueSizeInBits);
    1197             :         result = graph()->NewNode(
    1198             :             m->Word64Sar(),
    1199             :             graph()->NewNode(m->Word64Shl(),
    1200             :                              graph()->NewNode(m->ChangeInt32ToInt64(), result),
    1201             :                              shiftBitCount),
    1202           0 :             shiftBitCount);
    1203           0 :       } else if (wasmtype == wasm::kWasmI32) {
    1204           0 :         shiftBitCount = jsgraph()->Int32Constant(32 - valueSizeInBits);
    1205             :         result = graph()->NewNode(
    1206             :             m->Word32Sar(),
    1207             :             graph()->NewNode(m->Word32Shl(), result, shiftBitCount),
    1208           0 :             shiftBitCount);
    1209             :       }
    1210             :     }
    1211             :   }
    1212             : 
    1213           0 :   return result;
    1214             : }
    1215             : 
    1216          28 : Node* WasmGraphBuilder::BuildF32CopySign(Node* left, Node* right) {
    1217             :   Node* result = Unop(
    1218             :       wasm::kExprF32ReinterpretI32,
    1219             :       Binop(wasm::kExprI32Ior,
    1220             :             Binop(wasm::kExprI32And, Unop(wasm::kExprI32ReinterpretF32, left),
    1221             :                   jsgraph()->Int32Constant(0x7fffffff)),
    1222             :             Binop(wasm::kExprI32And, Unop(wasm::kExprI32ReinterpretF32, right),
    1223          28 :                   jsgraph()->Int32Constant(0x80000000))));
    1224             : 
    1225          14 :   return result;
    1226             : }
    1227             : 
    1228          28 : Node* WasmGraphBuilder::BuildF64CopySign(Node* left, Node* right) {
    1229             : #if WASM_64
    1230             :   Node* result = Unop(
    1231             :       wasm::kExprF64ReinterpretI64,
    1232             :       Binop(wasm::kExprI64Ior,
    1233             :             Binop(wasm::kExprI64And, Unop(wasm::kExprI64ReinterpretF64, left),
    1234             :                   jsgraph()->Int64Constant(0x7fffffffffffffff)),
    1235             :             Binop(wasm::kExprI64And, Unop(wasm::kExprI64ReinterpretF64, right),
    1236          28 :                   jsgraph()->Int64Constant(0x8000000000000000))));
    1237             : 
    1238          14 :   return result;
    1239             : #else
    1240             :   MachineOperatorBuilder* m = jsgraph()->machine();
    1241             : 
    1242             :   Node* high_word_left = graph()->NewNode(m->Float64ExtractHighWord32(), left);
    1243             :   Node* high_word_right =
    1244             :       graph()->NewNode(m->Float64ExtractHighWord32(), right);
    1245             : 
    1246             :   Node* new_high_word =
    1247             :       Binop(wasm::kExprI32Ior, Binop(wasm::kExprI32And, high_word_left,
    1248             :                                      jsgraph()->Int32Constant(0x7fffffff)),
    1249             :             Binop(wasm::kExprI32And, high_word_right,
    1250             :                   jsgraph()->Int32Constant(0x80000000)));
    1251             : 
    1252             :   return graph()->NewNode(m->Float64InsertHighWord32(), left, new_high_word);
    1253             : #endif
    1254             : }
    1255             : 
    1256         133 : Node* WasmGraphBuilder::BuildI32SConvertF32(Node* input,
    1257         133 :                                             wasm::WasmCodePosition position) {
    1258         133 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1259             :   // Truncation of the input value is needed for the overflow check later.
    1260         133 :   Node* trunc = Unop(wasm::kExprF32Trunc, input);
    1261         133 :   Node* result = graph()->NewNode(m->TruncateFloat32ToInt32(), trunc);
    1262             : 
    1263             :   // Convert the result back to f64. If we end up at a different value than the
    1264             :   // truncated input value, then there has been an overflow and we trap.
    1265         133 :   Node* check = Unop(wasm::kExprF32SConvertI32, result);
    1266         133 :   Node* overflow = Binop(wasm::kExprF32Ne, trunc, check);
    1267         133 :   TrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position);
    1268             : 
    1269         133 :   return result;
    1270             : }
    1271             : 
    1272         269 : Node* WasmGraphBuilder::BuildI32SConvertF64(Node* input,
    1273         269 :                                             wasm::WasmCodePosition position) {
    1274         269 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1275             :   // Truncation of the input value is needed for the overflow check later.
    1276         269 :   Node* trunc = Unop(wasm::kExprF64Trunc, input);
    1277         269 :   Node* result = graph()->NewNode(m->ChangeFloat64ToInt32(), trunc);
    1278             : 
    1279             :   // Convert the result back to f64. If we end up at a different value than the
    1280             :   // truncated input value, then there has been an overflow and we trap.
    1281         269 :   Node* check = Unop(wasm::kExprF64SConvertI32, result);
    1282         269 :   Node* overflow = Binop(wasm::kExprF64Ne, trunc, check);
    1283         269 :   TrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position);
    1284             : 
    1285         269 :   return result;
    1286             : }
    1287             : 
    1288          14 : Node* WasmGraphBuilder::BuildI32UConvertF32(Node* input,
    1289          14 :                                             wasm::WasmCodePosition position) {
    1290          14 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1291             :   // Truncation of the input value is needed for the overflow check later.
    1292          14 :   Node* trunc = Unop(wasm::kExprF32Trunc, input);
    1293          14 :   Node* result = graph()->NewNode(m->TruncateFloat32ToUint32(), trunc);
    1294             : 
    1295             :   // Convert the result back to f32. If we end up at a different value than the
    1296             :   // truncated input value, then there has been an overflow and we trap.
    1297          14 :   Node* check = Unop(wasm::kExprF32UConvertI32, result);
    1298          14 :   Node* overflow = Binop(wasm::kExprF32Ne, trunc, check);
    1299          14 :   TrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position);
    1300             : 
    1301          14 :   return result;
    1302             : }
    1303             : 
    1304          14 : Node* WasmGraphBuilder::BuildI32UConvertF64(Node* input,
    1305          14 :                                             wasm::WasmCodePosition position) {
    1306          14 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1307             :   // Truncation of the input value is needed for the overflow check later.
    1308          14 :   Node* trunc = Unop(wasm::kExprF64Trunc, input);
    1309          14 :   Node* result = graph()->NewNode(m->TruncateFloat64ToUint32(), trunc);
    1310             : 
    1311             :   // Convert the result back to f64. If we end up at a different value than the
    1312             :   // truncated input value, then there has been an overflow and we trap.
    1313          14 :   Node* check = Unop(wasm::kExprF64UConvertI32, result);
    1314          14 :   Node* overflow = Binop(wasm::kExprF64Ne, trunc, check);
    1315          14 :   TrapIfTrue(wasm::kTrapFloatUnrepresentable, overflow, position);
    1316             : 
    1317          14 :   return result;
    1318             : }
    1319             : 
    1320           7 : Node* WasmGraphBuilder::BuildI32AsmjsSConvertF32(Node* input) {
    1321           7 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1322             :   // asm.js must use the wacky JS semantics.
    1323           7 :   input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
    1324          14 :   return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
    1325             : }
    1326             : 
    1327          70 : Node* WasmGraphBuilder::BuildI32AsmjsSConvertF64(Node* input) {
    1328          70 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1329             :   // asm.js must use the wacky JS semantics.
    1330         140 :   return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
    1331             : }
    1332             : 
    1333           7 : Node* WasmGraphBuilder::BuildI32AsmjsUConvertF32(Node* input) {
    1334           7 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1335             :   // asm.js must use the wacky JS semantics.
    1336           7 :   input = graph()->NewNode(m->ChangeFloat32ToFloat64(), input);
    1337          14 :   return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
    1338             : }
    1339             : 
    1340           7 : Node* WasmGraphBuilder::BuildI32AsmjsUConvertF64(Node* input) {
    1341           7 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1342             :   // asm.js must use the wacky JS semantics.
    1343          14 :   return graph()->NewNode(m->TruncateFloat64ToWord32(), input);
    1344             : }
    1345             : 
    1346           0 : Node* WasmGraphBuilder::BuildBitCountingCall(Node* input, ExternalReference ref,
    1347           0 :                                              MachineRepresentation input_type) {
    1348             :   Node* stack_slot_param =
    1349           0 :       graph()->NewNode(jsgraph()->machine()->StackSlot(input_type));
    1350             : 
    1351             :   const Operator* store_op = jsgraph()->machine()->Store(
    1352           0 :       StoreRepresentation(input_type, kNoWriteBarrier));
    1353             :   *effect_ =
    1354             :       graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0),
    1355           0 :                        input, *effect_, *control_);
    1356             : 
    1357             :   MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 1);
    1358             :   sig_builder.AddReturn(MachineType::Int32());
    1359             :   sig_builder.AddParam(MachineType::Pointer());
    1360             : 
    1361           0 :   Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
    1362           0 :   Node* args[] = {function, stack_slot_param};
    1363             : 
    1364           0 :   return BuildCCall(sig_builder.Build(), args);
    1365             : }
    1366             : 
    1367           0 : Node* WasmGraphBuilder::BuildI32Ctz(Node* input) {
    1368             :   return BuildBitCountingCall(
    1369             :       input, ExternalReference::wasm_word32_ctz(jsgraph()->isolate()),
    1370           0 :       MachineRepresentation::kWord32);
    1371             : }
    1372             : 
    1373           0 : Node* WasmGraphBuilder::BuildI64Ctz(Node* input) {
    1374             :   return Unop(wasm::kExprI64UConvertI32,
    1375             :               BuildBitCountingCall(input, ExternalReference::wasm_word64_ctz(
    1376             :                                               jsgraph()->isolate()),
    1377           0 :                                    MachineRepresentation::kWord64));
    1378             : }
    1379             : 
    1380           0 : Node* WasmGraphBuilder::BuildI32Popcnt(Node* input) {
    1381             :   return BuildBitCountingCall(
    1382             :       input, ExternalReference::wasm_word32_popcnt(jsgraph()->isolate()),
    1383           0 :       MachineRepresentation::kWord32);
    1384             : }
    1385             : 
    1386           0 : Node* WasmGraphBuilder::BuildI64Popcnt(Node* input) {
    1387             :   return Unop(wasm::kExprI64UConvertI32,
    1388             :               BuildBitCountingCall(input, ExternalReference::wasm_word64_popcnt(
    1389             :                                               jsgraph()->isolate()),
    1390           0 :                                    MachineRepresentation::kWord64));
    1391             : }
    1392             : 
    1393           0 : Node* WasmGraphBuilder::BuildF32Trunc(Node* input) {
    1394           0 :   MachineType type = MachineType::Float32();
    1395             :   ExternalReference ref =
    1396           0 :       ExternalReference::wasm_f32_trunc(jsgraph()->isolate());
    1397             : 
    1398           0 :   return BuildCFuncInstruction(ref, type, input);
    1399             : }
    1400             : 
    1401           0 : Node* WasmGraphBuilder::BuildF32Floor(Node* input) {
    1402           0 :   MachineType type = MachineType::Float32();
    1403             :   ExternalReference ref =
    1404           0 :       ExternalReference::wasm_f32_floor(jsgraph()->isolate());
    1405           0 :   return BuildCFuncInstruction(ref, type, input);
    1406             : }
    1407             : 
    1408           0 : Node* WasmGraphBuilder::BuildF32Ceil(Node* input) {
    1409           0 :   MachineType type = MachineType::Float32();
    1410             :   ExternalReference ref =
    1411           0 :       ExternalReference::wasm_f32_ceil(jsgraph()->isolate());
    1412           0 :   return BuildCFuncInstruction(ref, type, input);
    1413             : }
    1414             : 
    1415           0 : Node* WasmGraphBuilder::BuildF32NearestInt(Node* input) {
    1416           0 :   MachineType type = MachineType::Float32();
    1417             :   ExternalReference ref =
    1418           0 :       ExternalReference::wasm_f32_nearest_int(jsgraph()->isolate());
    1419           0 :   return BuildCFuncInstruction(ref, type, input);
    1420             : }
    1421             : 
    1422           0 : Node* WasmGraphBuilder::BuildF64Trunc(Node* input) {
    1423           0 :   MachineType type = MachineType::Float64();
    1424             :   ExternalReference ref =
    1425           0 :       ExternalReference::wasm_f64_trunc(jsgraph()->isolate());
    1426           0 :   return BuildCFuncInstruction(ref, type, input);
    1427             : }
    1428             : 
    1429           0 : Node* WasmGraphBuilder::BuildF64Floor(Node* input) {
    1430           0 :   MachineType type = MachineType::Float64();
    1431             :   ExternalReference ref =
    1432           0 :       ExternalReference::wasm_f64_floor(jsgraph()->isolate());
    1433           0 :   return BuildCFuncInstruction(ref, type, input);
    1434             : }
    1435             : 
    1436           0 : Node* WasmGraphBuilder::BuildF64Ceil(Node* input) {
    1437           0 :   MachineType type = MachineType::Float64();
    1438             :   ExternalReference ref =
    1439           0 :       ExternalReference::wasm_f64_ceil(jsgraph()->isolate());
    1440           0 :   return BuildCFuncInstruction(ref, type, input);
    1441             : }
    1442             : 
    1443           0 : Node* WasmGraphBuilder::BuildF64NearestInt(Node* input) {
    1444           0 :   MachineType type = MachineType::Float64();
    1445             :   ExternalReference ref =
    1446           0 :       ExternalReference::wasm_f64_nearest_int(jsgraph()->isolate());
    1447           0 :   return BuildCFuncInstruction(ref, type, input);
    1448             : }
    1449             : 
    1450          46 : Node* WasmGraphBuilder::BuildF64Acos(Node* input) {
    1451          23 :   MachineType type = MachineType::Float64();
    1452             :   ExternalReference ref =
    1453          23 :       ExternalReference::f64_acos_wrapper_function(jsgraph()->isolate());
    1454          23 :   return BuildCFuncInstruction(ref, type, input);
    1455             : }
    1456             : 
    1457          46 : Node* WasmGraphBuilder::BuildF64Asin(Node* input) {
    1458          23 :   MachineType type = MachineType::Float64();
    1459             :   ExternalReference ref =
    1460          23 :       ExternalReference::f64_asin_wrapper_function(jsgraph()->isolate());
    1461          23 :   return BuildCFuncInstruction(ref, type, input);
    1462             : }
    1463             : 
    1464          28 : Node* WasmGraphBuilder::BuildF64Pow(Node* left, Node* right) {
    1465          14 :   MachineType type = MachineType::Float64();
    1466             :   ExternalReference ref =
    1467          14 :       ExternalReference::wasm_float64_pow(jsgraph()->isolate());
    1468          14 :   return BuildCFuncInstruction(ref, type, left, right);
    1469             : }
    1470             : 
    1471          56 : Node* WasmGraphBuilder::BuildF64Mod(Node* left, Node* right) {
    1472          28 :   MachineType type = MachineType::Float64();
    1473             :   ExternalReference ref =
    1474          28 :       ExternalReference::f64_mod_wrapper_function(jsgraph()->isolate());
    1475          28 :   return BuildCFuncInstruction(ref, type, left, right);
    1476             : }
    1477             : 
    1478          88 : Node* WasmGraphBuilder::BuildCFuncInstruction(ExternalReference ref,
    1479             :                                               MachineType type, Node* input0,
    1480         742 :                                               Node* input1) {
    1481             :   // We do truncation by calling a C function which calculates the result.
    1482             :   // The input is passed to the C function as a double*'s to avoid double
    1483             :   // parameters. For this we reserve slots on the stack, store the parameters
    1484             :   // in those slots, pass pointers to the slot to the C function,
    1485             :   // and after calling the C function we collect the return value from
    1486             :   // the stack slot.
    1487             : 
    1488             :   Node* stack_slot_param0 =
    1489          88 :       graph()->NewNode(jsgraph()->machine()->StackSlot(type.representation()));
    1490             : 
    1491             :   const Operator* store_op0 = jsgraph()->machine()->Store(
    1492          88 :       StoreRepresentation(type.representation(), kNoWriteBarrier));
    1493             :   *effect_ = graph()->NewNode(store_op0, stack_slot_param0,
    1494             :                               jsgraph()->Int32Constant(0), input0, *effect_,
    1495         264 :                               *control_);
    1496             : 
    1497          88 :   Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
    1498          88 :   Node** args = Buffer(5);
    1499          88 :   args[0] = function;
    1500          88 :   args[1] = stack_slot_param0;
    1501             :   int input_count = 1;
    1502             : 
    1503          88 :   if (input1 != nullptr) {
    1504             :     Node* stack_slot_param1 = graph()->NewNode(
    1505          42 :         jsgraph()->machine()->StackSlot(type.representation()));
    1506             :     const Operator* store_op1 = jsgraph()->machine()->Store(
    1507          42 :         StoreRepresentation(type.representation(), kNoWriteBarrier));
    1508             :     *effect_ = graph()->NewNode(store_op1, stack_slot_param1,
    1509             :                                 jsgraph()->Int32Constant(0), input1, *effect_,
    1510         126 :                                 *control_);
    1511          42 :     args[2] = stack_slot_param1;
    1512             :     ++input_count;
    1513             :   }
    1514             : 
    1515             :   Signature<MachineType>::Builder sig_builder(jsgraph()->zone(), 0,
    1516          88 :                                               input_count);
    1517             :   sig_builder.AddParam(MachineType::Pointer());
    1518          88 :   if (input1 != nullptr) {
    1519             :     sig_builder.AddParam(MachineType::Pointer());
    1520             :   }
    1521          88 :   BuildCCall(sig_builder.Build(), args);
    1522             : 
    1523          88 :   const Operator* load_op = jsgraph()->machine()->Load(type);
    1524             : 
    1525             :   Node* load =
    1526             :       graph()->NewNode(load_op, stack_slot_param0, jsgraph()->Int32Constant(0),
    1527         176 :                        *effect_, *control_);
    1528          88 :   *effect_ = load;
    1529          88 :   return load;
    1530             : }
    1531             : 
    1532           0 : Node* WasmGraphBuilder::BuildF32SConvertI64(Node* input) {
    1533             :   // TODO(titzer/bradnelson): Check handlng of asm.js case.
    1534             :   return BuildIntToFloatConversionInstruction(
    1535             :       input, ExternalReference::wasm_int64_to_float32(jsgraph()->isolate()),
    1536           0 :       MachineRepresentation::kWord64, MachineType::Float32());
    1537             : }
    1538           0 : Node* WasmGraphBuilder::BuildF32UConvertI64(Node* input) {
    1539             :   // TODO(titzer/bradnelson): Check handlng of asm.js case.
    1540             :   return BuildIntToFloatConversionInstruction(
    1541             :       input, ExternalReference::wasm_uint64_to_float32(jsgraph()->isolate()),
    1542           0 :       MachineRepresentation::kWord64, MachineType::Float32());
    1543             : }
    1544           0 : Node* WasmGraphBuilder::BuildF64SConvertI64(Node* input) {
    1545             :   return BuildIntToFloatConversionInstruction(
    1546             :       input, ExternalReference::wasm_int64_to_float64(jsgraph()->isolate()),
    1547           0 :       MachineRepresentation::kWord64, MachineType::Float64());
    1548             : }
    1549           0 : Node* WasmGraphBuilder::BuildF64UConvertI64(Node* input) {
    1550             :   return BuildIntToFloatConversionInstruction(
    1551             :       input, ExternalReference::wasm_uint64_to_float64(jsgraph()->isolate()),
    1552           0 :       MachineRepresentation::kWord64, MachineType::Float64());
    1553             : }
    1554             : 
    1555           0 : Node* WasmGraphBuilder::BuildIntToFloatConversionInstruction(
    1556             :     Node* input, ExternalReference ref,
    1557             :     MachineRepresentation parameter_representation,
    1558           0 :     const MachineType result_type) {
    1559             :   Node* stack_slot_param = graph()->NewNode(
    1560           0 :       jsgraph()->machine()->StackSlot(parameter_representation));
    1561             :   Node* stack_slot_result = graph()->NewNode(
    1562           0 :       jsgraph()->machine()->StackSlot(result_type.representation()));
    1563             :   const Operator* store_op = jsgraph()->machine()->Store(
    1564           0 :       StoreRepresentation(parameter_representation, kNoWriteBarrier));
    1565             :   *effect_ =
    1566             :       graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0),
    1567           0 :                        input, *effect_, *control_);
    1568             :   MachineSignature::Builder sig_builder(jsgraph()->zone(), 0, 2);
    1569             :   sig_builder.AddParam(MachineType::Pointer());
    1570             :   sig_builder.AddParam(MachineType::Pointer());
    1571           0 :   Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
    1572           0 :   Node* args[] = {function, stack_slot_param, stack_slot_result};
    1573           0 :   BuildCCall(sig_builder.Build(), args);
    1574           0 :   const Operator* load_op = jsgraph()->machine()->Load(result_type);
    1575             :   Node* load =
    1576             :       graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0),
    1577           0 :                        *effect_, *control_);
    1578           0 :   *effect_ = load;
    1579           0 :   return load;
    1580             : }
    1581             : 
    1582          21 : Node* WasmGraphBuilder::BuildI64SConvertF32(Node* input,
    1583          21 :                                             wasm::WasmCodePosition position) {
    1584          42 :   if (jsgraph()->machine()->Is32()) {
    1585             :     return BuildFloatToIntConversionInstruction(
    1586             :         input, ExternalReference::wasm_float32_to_int64(jsgraph()->isolate()),
    1587           0 :         MachineRepresentation::kFloat32, MachineType::Int64(), position);
    1588             :   } else {
    1589             :     Node* trunc = graph()->NewNode(
    1590          21 :         jsgraph()->machine()->TryTruncateFloat32ToInt64(), input);
    1591             :     Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
    1592          21 :                                     graph()->start());
    1593             :     Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
    1594          21 :                                       graph()->start());
    1595             :     ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
    1596          21 :     return result;
    1597             :   }
    1598             : }
    1599             : 
    1600          21 : Node* WasmGraphBuilder::BuildI64UConvertF32(Node* input,
    1601          21 :                                             wasm::WasmCodePosition position) {
    1602          42 :   if (jsgraph()->machine()->Is32()) {
    1603             :     return BuildFloatToIntConversionInstruction(
    1604             :         input, ExternalReference::wasm_float32_to_uint64(jsgraph()->isolate()),
    1605           0 :         MachineRepresentation::kFloat32, MachineType::Int64(), position);
    1606             :   } else {
    1607             :     Node* trunc = graph()->NewNode(
    1608          21 :         jsgraph()->machine()->TryTruncateFloat32ToUint64(), input);
    1609             :     Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
    1610          21 :                                     graph()->start());
    1611             :     Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
    1612          21 :                                       graph()->start());
    1613             :     ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
    1614          21 :     return result;
    1615             :   }
    1616             : }
    1617             : 
    1618          44 : Node* WasmGraphBuilder::BuildI64SConvertF64(Node* input,
    1619          44 :                                             wasm::WasmCodePosition position) {
    1620          88 :   if (jsgraph()->machine()->Is32()) {
    1621             :     return BuildFloatToIntConversionInstruction(
    1622             :         input, ExternalReference::wasm_float64_to_int64(jsgraph()->isolate()),
    1623           0 :         MachineRepresentation::kFloat64, MachineType::Int64(), position);
    1624             :   } else {
    1625             :     Node* trunc = graph()->NewNode(
    1626          44 :         jsgraph()->machine()->TryTruncateFloat64ToInt64(), input);
    1627             :     Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
    1628          44 :                                     graph()->start());
    1629             :     Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
    1630          44 :                                       graph()->start());
    1631             :     ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
    1632          44 :     return result;
    1633             :   }
    1634             : }
    1635             : 
    1636          21 : Node* WasmGraphBuilder::BuildI64UConvertF64(Node* input,
    1637          21 :                                             wasm::WasmCodePosition position) {
    1638          42 :   if (jsgraph()->machine()->Is32()) {
    1639             :     return BuildFloatToIntConversionInstruction(
    1640             :         input, ExternalReference::wasm_float64_to_uint64(jsgraph()->isolate()),
    1641           0 :         MachineRepresentation::kFloat64, MachineType::Int64(), position);
    1642             :   } else {
    1643             :     Node* trunc = graph()->NewNode(
    1644          21 :         jsgraph()->machine()->TryTruncateFloat64ToUint64(), input);
    1645             :     Node* result = graph()->NewNode(jsgraph()->common()->Projection(0), trunc,
    1646          21 :                                     graph()->start());
    1647             :     Node* overflow = graph()->NewNode(jsgraph()->common()->Projection(1), trunc,
    1648          21 :                                       graph()->start());
    1649             :     ZeroCheck64(wasm::kTrapFloatUnrepresentable, overflow, position);
    1650          21 :     return result;
    1651             :   }
    1652             : }
    1653             : 
    1654           0 : Node* WasmGraphBuilder::BuildFloatToIntConversionInstruction(
    1655             :     Node* input, ExternalReference ref,
    1656             :     MachineRepresentation parameter_representation,
    1657           0 :     const MachineType result_type, wasm::WasmCodePosition position) {
    1658             :   Node* stack_slot_param = graph()->NewNode(
    1659           0 :       jsgraph()->machine()->StackSlot(parameter_representation));
    1660             :   Node* stack_slot_result = graph()->NewNode(
    1661           0 :       jsgraph()->machine()->StackSlot(result_type.representation()));
    1662             :   const Operator* store_op = jsgraph()->machine()->Store(
    1663           0 :       StoreRepresentation(parameter_representation, kNoWriteBarrier));
    1664             :   *effect_ =
    1665             :       graph()->NewNode(store_op, stack_slot_param, jsgraph()->Int32Constant(0),
    1666           0 :                        input, *effect_, *control_);
    1667             :   MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2);
    1668             :   sig_builder.AddReturn(MachineType::Int32());
    1669             :   sig_builder.AddParam(MachineType::Pointer());
    1670             :   sig_builder.AddParam(MachineType::Pointer());
    1671           0 :   Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
    1672           0 :   Node* args[] = {function, stack_slot_param, stack_slot_result};
    1673             :   ZeroCheck32(wasm::kTrapFloatUnrepresentable,
    1674           0 :               BuildCCall(sig_builder.Build(), args), position);
    1675           0 :   const Operator* load_op = jsgraph()->machine()->Load(result_type);
    1676             :   Node* load =
    1677             :       graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0),
    1678           0 :                        *effect_, *control_);
    1679           0 :   *effect_ = load;
    1680           0 :   return load;
    1681             : }
    1682             : 
    1683        6342 : Node* WasmGraphBuilder::GrowMemory(Node* input) {
    1684             :   // GrowMemory will not be called from asm.js, hence we cannot be in
    1685             :   // lazy-compilation mode, hence the instance will be set.
    1686             :   DCHECK_NOT_NULL(module_);
    1687             :   DCHECK_NOT_NULL(module_->instance);
    1688             : 
    1689             :   Diamond check_input_range(
    1690             :       graph(), jsgraph()->common(),
    1691             :       graph()->NewNode(jsgraph()->machine()->Uint32LessThanOrEqual(), input,
    1692             :                        jsgraph()->Uint32Constant(FLAG_wasm_max_mem_pages)),
    1693        3624 :       BranchHint::kTrue);
    1694             : 
    1695         906 :   check_input_range.Chain(*control_);
    1696             : 
    1697         906 :   Node* parameters[] = {BuildChangeUint32ToSmi(input)};
    1698         906 :   Node* old_effect = *effect_;
    1699             :   Node* call = BuildCallToRuntime(Runtime::kWasmGrowMemory, jsgraph(),
    1700             :                                   parameters, arraysize(parameters), effect_,
    1701         906 :                                   &check_input_range.if_true);
    1702             : 
    1703         906 :   Node* result = BuildChangeSmiToInt32(call);
    1704             : 
    1705             :   result = check_input_range.Phi(MachineRepresentation::kWord32, result,
    1706         906 :                                  jsgraph()->Int32Constant(-1));
    1707             :   *effect_ = graph()->NewNode(jsgraph()->common()->EffectPhi(2), *effect_,
    1708        2718 :                               old_effect, check_input_range.merge);
    1709         906 :   *control_ = check_input_range.merge;
    1710         906 :   return result;
    1711             : }
    1712             : 
    1713         330 : Node* WasmGraphBuilder::Throw(Node* input) {
    1714         165 :   MachineOperatorBuilder* machine = jsgraph()->machine();
    1715             : 
    1716             :   // Pass the thrown value as two SMIs:
    1717             :   //
    1718             :   // upper = static_cast<uint32_t>(input) >> 16;
    1719             :   // lower = input & 0xFFFF;
    1720             :   //
    1721             :   // This is needed because we can't safely call BuildChangeInt32ToTagged from
    1722             :   // this method.
    1723             :   //
    1724             :   // TODO(wasm): figure out how to properly pass this to the runtime function.
    1725             :   Node* upper = BuildChangeInt32ToSmi(
    1726         330 :       graph()->NewNode(machine->Word32Shr(), input, Int32Constant(16)));
    1727             :   Node* lower = BuildChangeInt32ToSmi(
    1728         330 :       graph()->NewNode(machine->Word32And(), input, Int32Constant(0xFFFFu)));
    1729             : 
    1730         165 :   Node* parameters[] = {lower, upper};  // thrown value
    1731             :   return BuildCallToRuntime(Runtime::kWasmThrow, jsgraph(), parameters,
    1732         330 :                             arraysize(parameters), effect_, control_);
    1733             : }
    1734             : 
    1735         120 : Node* WasmGraphBuilder::Catch(Node* input, wasm::WasmCodePosition position) {
    1736         120 :   CommonOperatorBuilder* common = jsgraph()->common();
    1737             : 
    1738         120 :   Node* parameters[] = {input};  // caught value
    1739             :   Node* value =
    1740             :       BuildCallToRuntime(Runtime::kWasmGetCaughtExceptionValue, jsgraph(),
    1741         120 :                          parameters, arraysize(parameters), effect_, control_);
    1742             : 
    1743             :   Node* is_smi;
    1744             :   Node* is_heap;
    1745         120 :   BranchExpectFalse(BuildTestNotSmi(value), &is_heap, &is_smi);
    1746             : 
    1747             :   // is_smi
    1748         120 :   Node* smi_i32 = BuildChangeSmiToInt32(value);
    1749         120 :   Node* is_smi_effect = *effect_;
    1750             : 
    1751             :   // is_heap
    1752         120 :   *control_ = is_heap;
    1753         120 :   Node* heap_f64 = BuildLoadHeapNumberValue(value, is_heap);
    1754             : 
    1755             :   // *control_ needs to point to the current control dependency (is_heap) in
    1756             :   // case BuildI32SConvertF64 needs to insert nodes that depend on the "current"
    1757             :   // control node.
    1758         120 :   Node* heap_i32 = BuildI32SConvertF64(heap_f64, position);
    1759             :   // *control_ contains the control node that should be used when merging the
    1760             :   // result for the catch clause. It may be different than *control_ because
    1761             :   // BuildI32SConvertF64 may introduce a new control node (used for trapping if
    1762             :   // heap_f64 cannot be converted to an i32.
    1763         120 :   is_heap = *control_;
    1764         120 :   Node* is_heap_effect = *effect_;
    1765             : 
    1766         120 :   Node* merge = graph()->NewNode(common->Merge(2), is_heap, is_smi);
    1767             :   Node* effect_merge = graph()->NewNode(common->EffectPhi(2), is_heap_effect,
    1768         120 :                                         is_smi_effect, merge);
    1769             : 
    1770             :   Node* value_i32 = graph()->NewNode(
    1771         120 :       common->Phi(MachineRepresentation::kWord32, 2), heap_i32, smi_i32, merge);
    1772             : 
    1773         120 :   *control_ = merge;
    1774         120 :   *effect_ = effect_merge;
    1775         120 :   return value_i32;
    1776             : }
    1777             : 
    1778         151 : Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right,
    1779         430 :                                      wasm::WasmCodePosition position) {
    1780         151 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1781             :   ZeroCheck32(wasm::kTrapDivByZero, right, position);
    1782         151 :   Node* before = *control_;
    1783             :   Node* denom_is_m1;
    1784             :   Node* denom_is_not_m1;
    1785             :   BranchExpectFalse(
    1786             :       graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
    1787         151 :       &denom_is_m1, &denom_is_not_m1);
    1788         151 :   *control_ = denom_is_m1;
    1789         151 :   TrapIfEq32(wasm::kTrapDivUnrepresentable, left, kMinInt, position);
    1790         151 :   if (*control_ != denom_is_m1) {
    1791             :     *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1,
    1792         384 :                                  *control_);
    1793             :   } else {
    1794          23 :     *control_ = before;
    1795             :   }
    1796         302 :   return graph()->NewNode(m->Int32Div(), left, right, *control_);
    1797             : }
    1798             : 
    1799          58 : Node* WasmGraphBuilder::BuildI32RemS(Node* left, Node* right,
    1800         232 :                                      wasm::WasmCodePosition position) {
    1801          58 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1802             : 
    1803             :   ZeroCheck32(wasm::kTrapRemByZero, right, position);
    1804             : 
    1805             :   Diamond d(
    1806             :       graph(), jsgraph()->common(),
    1807             :       graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
    1808         174 :       BranchHint::kFalse);
    1809          58 :   d.Chain(*control_);
    1810             : 
    1811             :   return d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
    1812         116 :                graph()->NewNode(m->Int32Mod(), left, right, d.if_false));
    1813             : }
    1814             : 
    1815         105 : Node* WasmGraphBuilder::BuildI32DivU(Node* left, Node* right,
    1816         105 :                                      wasm::WasmCodePosition position) {
    1817         105 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1818             :   return graph()->NewNode(m->Uint32Div(), left, right,
    1819         210 :                           ZeroCheck32(wasm::kTrapDivByZero, right, position));
    1820             : }
    1821             : 
    1822          74 : Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right,
    1823          74 :                                      wasm::WasmCodePosition position) {
    1824          74 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1825             :   return graph()->NewNode(m->Uint32Mod(), left, right,
    1826         148 :                           ZeroCheck32(wasm::kTrapRemByZero, right, position));
    1827             : }
    1828             : 
    1829         587 : Node* WasmGraphBuilder::BuildI32AsmjsDivS(Node* left, Node* right) {
    1830         262 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1831             : 
    1832             :   Int32Matcher mr(right);
    1833         262 :   if (mr.HasValue()) {
    1834         197 :     if (mr.Value() == 0) {
    1835           8 :       return jsgraph()->Int32Constant(0);
    1836         189 :     } else if (mr.Value() == -1) {
    1837             :       // The result is the negation of the left input.
    1838          16 :       return graph()->NewNode(m->Int32Sub(), jsgraph()->Int32Constant(0), left);
    1839             :     }
    1840         362 :     return graph()->NewNode(m->Int32Div(), left, right, *control_);
    1841             :   }
    1842             : 
    1843             :   // asm.js semantics return 0 on divide or mod by zero.
    1844          65 :   if (m->Int32DivIsSafe()) {
    1845             :     // The hardware instruction does the right thing (e.g. arm).
    1846           0 :     return graph()->NewNode(m->Int32Div(), left, right, graph()->start());
    1847             :   }
    1848             : 
    1849             :   // Check denominator for zero.
    1850             :   Diamond z(
    1851             :       graph(), jsgraph()->common(),
    1852             :       graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
    1853         195 :       BranchHint::kFalse);
    1854             : 
    1855             :   // Check numerator for -1. (avoid minint / -1 case).
    1856             :   Diamond n(
    1857             :       graph(), jsgraph()->common(),
    1858             :       graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)),
    1859         195 :       BranchHint::kFalse);
    1860             : 
    1861          65 :   Node* div = graph()->NewNode(m->Int32Div(), left, right, z.if_false);
    1862             :   Node* neg =
    1863          65 :       graph()->NewNode(m->Int32Sub(), jsgraph()->Int32Constant(0), left);
    1864             : 
    1865             :   return n.Phi(
    1866             :       MachineRepresentation::kWord32, neg,
    1867          65 :       z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), div));
    1868             : }
    1869             : 
    1870         468 : Node* WasmGraphBuilder::BuildI32AsmjsRemS(Node* left, Node* right) {
    1871         394 :   CommonOperatorBuilder* c = jsgraph()->common();
    1872         394 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1873         394 :   Node* const zero = jsgraph()->Int32Constant(0);
    1874             : 
    1875             :   Int32Matcher mr(right);
    1876         394 :   if (mr.HasValue()) {
    1877         320 :     if (mr.Value() == 0 || mr.Value() == -1) {
    1878             :       return zero;
    1879             :     }
    1880         608 :     return graph()->NewNode(m->Int32Mod(), left, right, *control_);
    1881             :   }
    1882             : 
    1883             :   // General case for signed integer modulus, with optimization for (unknown)
    1884             :   // power of 2 right hand side.
    1885             :   //
    1886             :   //   if 0 < right then
    1887             :   //     msk = right - 1
    1888             :   //     if right & msk != 0 then
    1889             :   //       left % right
    1890             :   //     else
    1891             :   //       if left < 0 then
    1892             :   //         -(-left & msk)
    1893             :   //       else
    1894             :   //         left & msk
    1895             :   //   else
    1896             :   //     if right < -1 then
    1897             :   //       left % right
    1898             :   //     else
    1899             :   //       zero
    1900             :   //
    1901             :   // Note: We do not use the Diamond helper class here, because it really hurts
    1902             :   // readability with nested diamonds.
    1903          74 :   Node* const minus_one = jsgraph()->Int32Constant(-1);
    1904             : 
    1905          74 :   const Operator* const merge_op = c->Merge(2);
    1906          74 :   const Operator* const phi_op = c->Phi(MachineRepresentation::kWord32, 2);
    1907             : 
    1908          74 :   Node* check0 = graph()->NewNode(m->Int32LessThan(), zero, right);
    1909             :   Node* branch0 =
    1910          74 :       graph()->NewNode(c->Branch(BranchHint::kTrue), check0, graph()->start());
    1911             : 
    1912          74 :   Node* if_true0 = graph()->NewNode(c->IfTrue(), branch0);
    1913             :   Node* true0;
    1914             :   {
    1915          74 :     Node* msk = graph()->NewNode(m->Int32Add(), right, minus_one);
    1916             : 
    1917          74 :     Node* check1 = graph()->NewNode(m->Word32And(), right, msk);
    1918          74 :     Node* branch1 = graph()->NewNode(c->Branch(), check1, if_true0);
    1919             : 
    1920          74 :     Node* if_true1 = graph()->NewNode(c->IfTrue(), branch1);
    1921          74 :     Node* true1 = graph()->NewNode(m->Int32Mod(), left, right, if_true1);
    1922             : 
    1923          74 :     Node* if_false1 = graph()->NewNode(c->IfFalse(), branch1);
    1924             :     Node* false1;
    1925             :     {
    1926          74 :       Node* check2 = graph()->NewNode(m->Int32LessThan(), left, zero);
    1927             :       Node* branch2 =
    1928          74 :           graph()->NewNode(c->Branch(BranchHint::kFalse), check2, if_false1);
    1929             : 
    1930          74 :       Node* if_true2 = graph()->NewNode(c->IfTrue(), branch2);
    1931             :       Node* true2 = graph()->NewNode(
    1932             :           m->Int32Sub(), zero,
    1933             :           graph()->NewNode(m->Word32And(),
    1934         222 :                            graph()->NewNode(m->Int32Sub(), zero, left), msk));
    1935             : 
    1936          74 :       Node* if_false2 = graph()->NewNode(c->IfFalse(), branch2);
    1937          74 :       Node* false2 = graph()->NewNode(m->Word32And(), left, msk);
    1938             : 
    1939             :       if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
    1940             :       false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
    1941             :     }
    1942             : 
    1943             :     if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
    1944             :     true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
    1945             :   }
    1946             : 
    1947          74 :   Node* if_false0 = graph()->NewNode(c->IfFalse(), branch0);
    1948             :   Node* false0;
    1949             :   {
    1950          74 :     Node* check1 = graph()->NewNode(m->Int32LessThan(), right, minus_one);
    1951             :     Node* branch1 =
    1952          74 :         graph()->NewNode(c->Branch(BranchHint::kTrue), check1, if_false0);
    1953             : 
    1954          74 :     Node* if_true1 = graph()->NewNode(c->IfTrue(), branch1);
    1955          74 :     Node* true1 = graph()->NewNode(m->Int32Mod(), left, right, if_true1);
    1956             : 
    1957          74 :     Node* if_false1 = graph()->NewNode(c->IfFalse(), branch1);
    1958             :     Node* false1 = zero;
    1959             : 
    1960             :     if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
    1961             :     false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
    1962             :   }
    1963             : 
    1964             :   Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
    1965          74 :   return graph()->NewNode(phi_op, true0, false0, merge0);
    1966             : }
    1967             : 
    1968         352 : Node* WasmGraphBuilder::BuildI32AsmjsDivU(Node* left, Node* right) {
    1969          88 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1970             :   // asm.js semantics return 0 on divide or mod by zero.
    1971          88 :   if (m->Uint32DivIsSafe()) {
    1972             :     // The hardware instruction does the right thing (e.g. arm).
    1973           0 :     return graph()->NewNode(m->Uint32Div(), left, right, graph()->start());
    1974             :   }
    1975             : 
    1976             :   // Explicit check for x % 0.
    1977             :   Diamond z(
    1978             :       graph(), jsgraph()->common(),
    1979             :       graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
    1980         264 :       BranchHint::kFalse);
    1981             : 
    1982             :   return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
    1983             :                graph()->NewNode(jsgraph()->machine()->Uint32Div(), left, right,
    1984         264 :                                 z.if_false));
    1985             : }
    1986             : 
    1987         632 : Node* WasmGraphBuilder::BuildI32AsmjsRemU(Node* left, Node* right) {
    1988         158 :   MachineOperatorBuilder* m = jsgraph()->machine();
    1989             :   // asm.js semantics return 0 on divide or mod by zero.
    1990             :   // Explicit check for x % 0.
    1991             :   Diamond z(
    1992             :       graph(), jsgraph()->common(),
    1993             :       graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)),
    1994         474 :       BranchHint::kFalse);
    1995             : 
    1996             :   Node* rem = graph()->NewNode(jsgraph()->machine()->Uint32Mod(), left, right,
    1997         316 :                                z.if_false);
    1998             :   return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0),
    1999         158 :                rem);
    2000             : }
    2001             : 
    2002         105 : Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right,
    2003         518 :                                      wasm::WasmCodePosition position) {
    2004         210 :   if (jsgraph()->machine()->Is32()) {
    2005             :     return BuildDiv64Call(
    2006             :         left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()),
    2007           0 :         MachineType::Int64(), wasm::kTrapDivByZero, position);
    2008             :   }
    2009             :   ZeroCheck64(wasm::kTrapDivByZero, right, position);
    2010         105 :   Node* before = *control_;
    2011             :   Node* denom_is_m1;
    2012             :   Node* denom_is_not_m1;
    2013             :   BranchExpectFalse(graph()->NewNode(jsgraph()->machine()->Word64Equal(), right,
    2014             :                                      jsgraph()->Int64Constant(-1)),
    2015         210 :                     &denom_is_m1, &denom_is_not_m1);
    2016         105 :   *control_ = denom_is_m1;
    2017             :   TrapIfEq64(wasm::kTrapDivUnrepresentable, left,
    2018         105 :              std::numeric_limits<int64_t>::min(), position);
    2019         105 :   if (*control_ != denom_is_m1) {
    2020             :     *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1,
    2021         294 :                                  *control_);
    2022             :   } else {
    2023           7 :     *control_ = before;
    2024             :   }
    2025             :   return graph()->NewNode(jsgraph()->machine()->Int64Div(), left, right,
    2026         315 :                           *control_);
    2027             : }
    2028             : 
    2029          35 : Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right,
    2030         210 :                                      wasm::WasmCodePosition position) {
    2031          70 :   if (jsgraph()->machine()->Is32()) {
    2032             :     return BuildDiv64Call(
    2033             :         left, right, ExternalReference::wasm_int64_mod(jsgraph()->isolate()),
    2034           0 :         MachineType::Int64(), wasm::kTrapRemByZero, position);
    2035             :   }
    2036             :   ZeroCheck64(wasm::kTrapRemByZero, right, position);
    2037             :   Diamond d(jsgraph()->graph(), jsgraph()->common(),
    2038             :             graph()->NewNode(jsgraph()->machine()->Word64Equal(), right,
    2039         105 :                              jsgraph()->Int64Constant(-1)));
    2040             : 
    2041          35 :   d.Chain(*control_);
    2042             : 
    2043             :   Node* rem = graph()->NewNode(jsgraph()->machine()->Int64Mod(), left, right,
    2044          70 :                                d.if_false);
    2045             : 
    2046             :   return d.Phi(MachineRepresentation::kWord64, jsgraph()->Int64Constant(0),
    2047          35 :                rem);
    2048             : }
    2049             : 
    2050          35 : Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right,
    2051          70 :                                      wasm::WasmCodePosition position) {
    2052          70 :   if (jsgraph()->machine()->Is32()) {
    2053             :     return BuildDiv64Call(
    2054             :         left, right, ExternalReference::wasm_uint64_div(jsgraph()->isolate()),
    2055           0 :         MachineType::Int64(), wasm::kTrapDivByZero, position);
    2056             :   }
    2057             :   return graph()->NewNode(jsgraph()->machine()->Uint64Div(), left, right,
    2058          70 :                           ZeroCheck64(wasm::kTrapDivByZero, right, position));
    2059             : }
    2060          50 : Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right,
    2061         100 :                                      wasm::WasmCodePosition position) {
    2062         100 :   if (jsgraph()->machine()->Is32()) {
    2063             :     return BuildDiv64Call(
    2064             :         left, right, ExternalReference::wasm_uint64_mod(jsgraph()->isolate()),
    2065           0 :         MachineType::Int64(), wasm::kTrapRemByZero, position);
    2066             :   }
    2067             :   return graph()->NewNode(jsgraph()->machine()->Uint64Mod(), left, right,
    2068         100 :                           ZeroCheck64(wasm::kTrapRemByZero, right, position));
    2069             : }
    2070             : 
    2071           0 : Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right,
    2072             :                                        ExternalReference ref,
    2073             :                                        MachineType result_type, int trap_zero,
    2074           0 :                                        wasm::WasmCodePosition position) {
    2075             :   Node* stack_slot_dst = graph()->NewNode(
    2076           0 :       jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64));
    2077             :   Node* stack_slot_src = graph()->NewNode(
    2078           0 :       jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64));
    2079             : 
    2080             :   const Operator* store_op = jsgraph()->machine()->Store(
    2081           0 :       StoreRepresentation(MachineRepresentation::kWord64, kNoWriteBarrier));
    2082             :   *effect_ =
    2083             :       graph()->NewNode(store_op, stack_slot_dst, jsgraph()->Int32Constant(0),
    2084           0 :                        left, *effect_, *control_);
    2085             :   *effect_ =
    2086             :       graph()->NewNode(store_op, stack_slot_src, jsgraph()->Int32Constant(0),
    2087           0 :                        right, *effect_, *control_);
    2088             : 
    2089             :   MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2);
    2090             :   sig_builder.AddReturn(MachineType::Int32());
    2091             :   sig_builder.AddParam(MachineType::Pointer());
    2092             :   sig_builder.AddParam(MachineType::Pointer());
    2093             : 
    2094           0 :   Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref));
    2095           0 :   Node* args[] = {function, stack_slot_dst, stack_slot_src};
    2096             : 
    2097           0 :   Node* call = BuildCCall(sig_builder.Build(), args);
    2098             : 
    2099             :   // TODO(wasm): This can get simpler if we have a specialized runtime call to
    2100             :   // throw WASM exceptions by trap code instead of by string.
    2101           0 :   ZeroCheck32(static_cast<wasm::TrapReason>(trap_zero), call, position);
    2102           0 :   TrapIfEq32(wasm::kTrapDivUnrepresentable, call, -1, position);
    2103           0 :   const Operator* load_op = jsgraph()->machine()->Load(result_type);
    2104             :   Node* load =
    2105             :       graph()->NewNode(load_op, stack_slot_dst, jsgraph()->Int32Constant(0),
    2106           0 :                        *effect_, *control_);
    2107           0 :   *effect_ = load;
    2108           0 :   return load;
    2109             : }
    2110             : 
    2111         264 : Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) {
    2112             :   const size_t params = sig->parameter_count();
    2113             :   const size_t extra = 2;  // effect and control inputs.
    2114          88 :   const size_t count = 1 + params + extra;
    2115             : 
    2116             :   // Reallocate the buffer to make space for extra inputs.
    2117          88 :   args = Realloc(args, 1 + params, count);
    2118             : 
    2119             :   // Add effect and control inputs.
    2120          88 :   args[params + 1] = *effect_;
    2121          88 :   args[params + 2] = *control_;
    2122             : 
    2123             :   CallDescriptor* desc =
    2124          88 :       Linkage::GetSimplifiedCDescriptor(jsgraph()->zone(), sig);
    2125             : 
    2126          88 :   const Operator* op = jsgraph()->common()->Call(desc);
    2127         176 :   Node* call = graph()->NewNode(op, static_cast<int>(count), args);
    2128          88 :   *effect_ = call;
    2129          88 :   return call;
    2130             : }
    2131             : 
    2132       71119 : Node* WasmGraphBuilder::BuildWasmCall(wasm::FunctionSig* sig, Node** args,
    2133             :                                       Node*** rets,
    2134       71112 :                                       wasm::WasmCodePosition position) {
    2135             :   const size_t params = sig->parameter_count();
    2136             :   const size_t extra = 2;  // effect and control inputs.
    2137       35557 :   const size_t count = 1 + params + extra;
    2138             : 
    2139             :   // Reallocate the buffer to make space for extra inputs.
    2140       35557 :   args = Realloc(args, 1 + params, count);
    2141             : 
    2142             :   // Add effect and control inputs.
    2143       35557 :   args[params + 1] = *effect_;
    2144       35557 :   args[params + 2] = *control_;
    2145             : 
    2146             :   CallDescriptor* descriptor =
    2147       35557 :       wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig);
    2148       35555 :   const Operator* op = jsgraph()->common()->Call(descriptor);
    2149       71110 :   Node* call = graph()->NewNode(op, static_cast<int>(count), args);
    2150       35558 :   SetSourcePosition(call, position);
    2151             : 
    2152       35562 :   *effect_ = call;
    2153             :   size_t ret_count = sig->return_count();
    2154       35562 :   if (ret_count == 0) return call;  // No return value.
    2155             : 
    2156       20646 :   *rets = Buffer(ret_count);
    2157       20646 :   if (ret_count == 1) {
    2158             :     // Only a single return value.
    2159       19743 :     (*rets)[0] = call;
    2160             :   } else {
    2161             :     // Create projections for all return values.
    2162        1806 :     for (size_t i = 0; i < ret_count; i++) {
    2163        1806 :       (*rets)[i] = graph()->NewNode(jsgraph()->common()->Projection(i), call,
    2164        3612 :                                     graph()->start());
    2165             :     }
    2166             :   }
    2167             :   return call;
    2168             : }
    2169             : 
    2170       33175 : Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, Node*** rets,
    2171       20202 :                                    wasm::WasmCodePosition position) {
    2172             :   DCHECK_NULL(args[0]);
    2173             : 
    2174             :   // Add code object as constant.
    2175             :   // TODO(wasm): Always use the illegal builtin, except for testing.
    2176             :   Handle<Code> code = module_->instance
    2177             :                           ? module_->GetFunctionCode(index)
    2178       86570 :                           : jsgraph()->isolate()->builtins()->Illegal();
    2179             :   DCHECK(!code.is_null());
    2180       33193 :   args[0] = HeapConstant(code);
    2181       33193 :   wasm::FunctionSig* sig = module_->GetFunctionSignature(index);
    2182             : 
    2183       33193 :   return BuildWasmCall(sig, args, rets, position);
    2184             : }
    2185             : 
    2186        2364 : Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args,
    2187             :                                      Node*** rets,
    2188        4728 :                                      wasm::WasmCodePosition position) {
    2189             :   DCHECK_NOT_NULL(args[0]);
    2190             :   DCHECK_NOT_NULL(module_);
    2191             : 
    2192             :   // Assume only one table for now.
    2193             :   uint32_t table_index = 0;
    2194        2364 :   wasm::FunctionSig* sig = module_->GetSignature(sig_index);
    2195             : 
    2196             :   DCHECK(module_->IsValidTable(table_index));
    2197             : 
    2198        2364 :   EnsureFunctionTableNodes();
    2199        2364 :   MachineOperatorBuilder* machine = jsgraph()->machine();
    2200        2364 :   Node* key = args[0];
    2201             : 
    2202             :   // Bounds check against the table size.
    2203        2364 :   Node* size = function_table_sizes_[table_index];
    2204        2364 :   Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size);
    2205        2364 :   TrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position);
    2206        2364 :   Node* table = function_tables_[table_index];
    2207        2364 :   Node* signatures = signature_tables_[table_index];
    2208             : 
    2209             :   // Load signature from the table and check.
    2210             :   // The table is a FixedArray; signatures are encoded as SMIs.
    2211             :   // [sig1, sig2, sig3, ...., code1, code2, code3 ...]
    2212        2364 :   ElementAccess access = AccessBuilder::ForFixedArrayElement();
    2213        4728 :   const int fixed_offset = access.header_size - access.tag();
    2214             :   {
    2215             :     Node* load_sig = graph()->NewNode(
    2216             :         machine->Load(MachineType::AnyTagged()), signatures,
    2217             :         graph()->NewNode(machine->Int32Add(),
    2218             :                          graph()->NewNode(machine->Word32Shl(), key,
    2219             :                                           Int32Constant(kPointerSizeLog2)),
    2220             :                          Int32Constant(fixed_offset)),
    2221        9456 :         *effect_, *control_);
    2222             :     auto map = const_cast<wasm::SignatureMap&>(
    2223        2364 :         module_->module->function_tables[0].map);
    2224             :     Node* sig_match = graph()->NewNode(
    2225             :         machine->WordEqual(), load_sig,
    2226        4728 :         jsgraph()->SmiConstant(static_cast<int>(map.FindOrInsert(sig))));
    2227        2364 :     TrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position);
    2228             :   }
    2229             : 
    2230             :   // Load code object from the table.
    2231             :   Node* load_code = graph()->NewNode(
    2232             :       machine->Load(MachineType::AnyTagged()), table,
    2233             :       graph()->NewNode(machine->Int32Add(),
    2234             :                        graph()->NewNode(machine->Word32Shl(), key,
    2235             :                                         Int32Constant(kPointerSizeLog2)),
    2236             :                        Uint32Constant(fixed_offset)),
    2237        9456 :       *effect_, *control_);
    2238             : 
    2239        2364 :   args[0] = load_code;
    2240        2364 :   return BuildWasmCall(sig, args, rets, position);
    2241             : }
    2242             : 
    2243          70 : Node* WasmGraphBuilder::BuildI32Rol(Node* left, Node* right) {
    2244             :   // Implement Rol by Ror since TurboFan does not have Rol opcode.
    2245             :   // TODO(weiliang): support Word32Rol opcode in TurboFan.
    2246             :   Int32Matcher m(right);
    2247          35 :   if (m.HasValue()) {
    2248             :     return Binop(wasm::kExprI32Ror, left,
    2249          28 :                  jsgraph()->Int32Constant(32 - m.Value()));
    2250             :   } else {
    2251             :     return Binop(wasm::kExprI32Ror, left,
    2252          21 :                  Binop(wasm::kExprI32Sub, jsgraph()->Int32Constant(32), right));
    2253             :   }
    2254             : }
    2255             : 
    2256          84 : Node* WasmGraphBuilder::BuildI64Rol(Node* left, Node* right) {
    2257             :   // Implement Rol by Ror since TurboFan does not have Rol opcode.
    2258             :   // TODO(weiliang): support Word64Rol opcode in TurboFan.
    2259             :   Int64Matcher m(right);
    2260          42 :   if (m.HasValue()) {
    2261             :     return Binop(wasm::kExprI64Ror, left,
    2262          28 :                  jsgraph()->Int64Constant(64 - m.Value()));
    2263             :   } else {
    2264             :     return Binop(wasm::kExprI64Ror, left,
    2265          28 :                  Binop(wasm::kExprI64Sub, jsgraph()->Int64Constant(64), right));
    2266             :   }
    2267             : }
    2268             : 
    2269        6922 : Node* WasmGraphBuilder::Invert(Node* node) {
    2270        6922 :   return Unop(wasm::kExprI32Eqz, node);
    2271             : }
    2272             : 
    2273       48043 : Node* WasmGraphBuilder::BuildChangeInt32ToTagged(Node* value) {
    2274       48043 :   MachineOperatorBuilder* machine = jsgraph()->machine();
    2275       48043 :   CommonOperatorBuilder* common = jsgraph()->common();
    2276             : 
    2277       48043 :   if (machine->Is64()) {
    2278       48043 :     return BuildChangeInt32ToSmi(value);
    2279             :   }
    2280             : 
    2281             :   Node* add = graph()->NewNode(machine->Int32AddWithOverflow(), value, value,
    2282           0 :                                graph()->start());
    2283             : 
    2284           0 :   Node* ovf = graph()->NewNode(common->Projection(1), add, graph()->start());
    2285             :   Node* branch = graph()->NewNode(common->Branch(BranchHint::kFalse), ovf,
    2286           0 :                                   graph()->start());
    2287             : 
    2288           0 :   Node* if_true = graph()->NewNode(common->IfTrue(), branch);
    2289             :   Node* vtrue = BuildAllocateHeapNumberWithValue(
    2290           0 :       graph()->NewNode(machine->ChangeInt32ToFloat64(), value), if_true);
    2291             : 
    2292           0 :   Node* if_false = graph()->NewNode(common->IfFalse(), branch);
    2293           0 :   Node* vfalse = graph()->NewNode(common->Projection(0), add, if_false);
    2294             : 
    2295           0 :   Node* merge = graph()->NewNode(common->Merge(2), if_true, if_false);
    2296             :   Node* phi = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2),
    2297           0 :                                vtrue, vfalse, merge);
    2298           0 :   return phi;
    2299             : }
    2300             : 
    2301       38832 : Node* WasmGraphBuilder::BuildChangeFloat64ToTagged(Node* value) {
    2302       12944 :   MachineOperatorBuilder* machine = jsgraph()->machine();
    2303       12944 :   CommonOperatorBuilder* common = jsgraph()->common();
    2304             : 
    2305       12944 :   Node* value32 = graph()->NewNode(machine->RoundFloat64ToInt32(), value);
    2306             :   Node* check_same = graph()->NewNode(
    2307             :       machine->Float64Equal(), value,
    2308       25888 :       graph()->NewNode(machine->ChangeInt32ToFloat64(), value32));
    2309             :   Node* branch_same =
    2310       12944 :       graph()->NewNode(common->Branch(), check_same, graph()->start());
    2311             : 
    2312       12944 :   Node* if_smi = graph()->NewNode(common->IfTrue(), branch_same);
    2313             :   Node* vsmi;
    2314       12944 :   Node* if_box = graph()->NewNode(common->IfFalse(), branch_same);
    2315             :   Node* vbox;
    2316             : 
    2317             :   // We only need to check for -0 if the {value} can potentially contain -0.
    2318             :   Node* check_zero = graph()->NewNode(machine->Word32Equal(), value32,
    2319       12944 :                                       jsgraph()->Int32Constant(0));
    2320             :   Node* branch_zero =
    2321       12944 :       graph()->NewNode(common->Branch(BranchHint::kFalse), check_zero, if_smi);
    2322             : 
    2323       12944 :   Node* if_zero = graph()->NewNode(common->IfTrue(), branch_zero);
    2324       12944 :   Node* if_notzero = graph()->NewNode(common->IfFalse(), branch_zero);
    2325             : 
    2326             :   // In case of 0, we need to check the high bits for the IEEE -0 pattern.
    2327             :   Node* check_negative = graph()->NewNode(
    2328             :       machine->Int32LessThan(),
    2329             :       graph()->NewNode(machine->Float64ExtractHighWord32(), value),
    2330       25888 :       jsgraph()->Int32Constant(0));
    2331             :   Node* branch_negative = graph()->NewNode(common->Branch(BranchHint::kFalse),
    2332       12944 :                                            check_negative, if_zero);
    2333             : 
    2334       12944 :   Node* if_negative = graph()->NewNode(common->IfTrue(), branch_negative);
    2335       12944 :   Node* if_notnegative = graph()->NewNode(common->IfFalse(), branch_negative);
    2336             : 
    2337             :   // We need to create a box for negative 0.
    2338       12944 :   if_smi = graph()->NewNode(common->Merge(2), if_notzero, if_notnegative);
    2339       12944 :   if_box = graph()->NewNode(common->Merge(2), if_box, if_negative);
    2340             : 
    2341             :   // On 64-bit machines we can just wrap the 32-bit integer in a smi, for 32-bit
    2342             :   // machines we need to deal with potential overflow and fallback to boxing.
    2343       12944 :   if (machine->Is64()) {
    2344       12944 :     vsmi = BuildChangeInt32ToSmi(value32);
    2345             :   } else {
    2346             :     Node* smi_tag = graph()->NewNode(machine->Int32AddWithOverflow(), value32,
    2347           0 :                                      value32, if_smi);
    2348             : 
    2349           0 :     Node* check_ovf = graph()->NewNode(common->Projection(1), smi_tag, if_smi);
    2350             :     Node* branch_ovf =
    2351           0 :         graph()->NewNode(common->Branch(BranchHint::kFalse), check_ovf, if_smi);
    2352             : 
    2353           0 :     Node* if_ovf = graph()->NewNode(common->IfTrue(), branch_ovf);
    2354           0 :     if_box = graph()->NewNode(common->Merge(2), if_ovf, if_box);
    2355             : 
    2356           0 :     if_smi = graph()->NewNode(common->IfFalse(), branch_ovf);
    2357           0 :     vsmi = graph()->NewNode(common->Projection(0), smi_tag, if_smi);
    2358             :   }
    2359             : 
    2360             :   // Allocate the box for the {value}.
    2361       12944 :   vbox = BuildAllocateHeapNumberWithValue(value, if_box);
    2362             : 
    2363       12944 :   Node* control = graph()->NewNode(common->Merge(2), if_smi, if_box);
    2364             :   value = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2), vsmi,
    2365       12944 :                            vbox, control);
    2366       12944 :   return value;
    2367             : }
    2368             : 
    2369       85840 : Node* WasmGraphBuilder::ToJS(Node* node, wasm::ValueType type) {
    2370       73019 :   switch (type) {
    2371             :     case wasm::kWasmI32:
    2372       48043 :       return BuildChangeInt32ToTagged(node);
    2373             :     case wasm::kWasmS128:
    2374             :     case wasm::kWasmI64:
    2375           0 :       UNREACHABLE();
    2376             :     case wasm::kWasmF32:
    2377             :       node = graph()->NewNode(jsgraph()->machine()->ChangeFloat32ToFloat64(),
    2378         789 :                               node);
    2379         789 :       return BuildChangeFloat64ToTagged(node);
    2380             :     case wasm::kWasmF64:
    2381       12155 :       return BuildChangeFloat64ToTagged(node);
    2382             :     case wasm::kWasmStmt:
    2383       12032 :       return jsgraph()->UndefinedConstant();
    2384             :     default:
    2385           0 :       UNREACHABLE();
    2386             :       return nullptr;
    2387             :   }
    2388             : }
    2389             : 
    2390      289964 : Node* WasmGraphBuilder::BuildJavaScriptToNumber(Node* node, Node* context) {
    2391       72491 :   Callable callable = CodeFactory::ToNumber(jsgraph()->isolate());
    2392             :   CallDescriptor* desc = Linkage::GetStubCallDescriptor(
    2393             :       jsgraph()->isolate(), jsgraph()->zone(), callable.descriptor(), 0,
    2394      144982 :       CallDescriptor::kNoFlags, Operator::kNoProperties);
    2395       72491 :   Node* stub_code = jsgraph()->HeapConstant(callable.code());
    2396             : 
    2397             :   Node* result = graph()->NewNode(jsgraph()->common()->Call(desc), stub_code,
    2398      144982 :                                   node, context, *effect_, *control_);
    2399             : 
    2400       72491 :   SetSourcePosition(result, 1);
    2401             : 
    2402       72491 :   *effect_ = result;
    2403             : 
    2404       72491 :   return result;
    2405             : }
    2406             : 
    2407           0 : bool CanCover(Node* value, IrOpcode::Value opcode) {
    2408           0 :   if (value->opcode() != opcode) return false;
    2409             :   bool first = true;
    2410           0 :   for (Edge const edge : value->use_edges()) {
    2411           0 :     if (NodeProperties::IsControlEdge(edge)) continue;
    2412           0 :     if (NodeProperties::IsEffectEdge(edge)) continue;
    2413             :     DCHECK(NodeProperties::IsValueEdge(edge));
    2414           0 :     if (!first) return false;
    2415             :     first = false;
    2416             :   }
    2417           0 :   return true;
    2418             : }
    2419             : 
    2420      217473 : Node* WasmGraphBuilder::BuildChangeTaggedToFloat64(Node* value) {
    2421       72491 :   MachineOperatorBuilder* machine = jsgraph()->machine();
    2422       72491 :   CommonOperatorBuilder* common = jsgraph()->common();
    2423             : 
    2424       72491 :   Node* check = BuildTestNotSmi(value);
    2425             :   Node* branch = graph()->NewNode(common->Branch(BranchHint::kFalse), check,
    2426       72491 :                                   graph()->start());
    2427             : 
    2428       72491 :   Node* if_not_smi = graph()->NewNode(common->IfTrue(), branch);
    2429             : 
    2430             :   Node* vnot_smi;
    2431             :   Node* check_undefined = graph()->NewNode(machine->WordEqual(), value,
    2432       72491 :                                            jsgraph()->UndefinedConstant());
    2433             :   Node* branch_undefined = graph()->NewNode(common->Branch(BranchHint::kFalse),
    2434       72491 :                                             check_undefined, if_not_smi);
    2435             : 
    2436       72491 :   Node* if_undefined = graph()->NewNode(common->IfTrue(), branch_undefined);
    2437             :   Node* vundefined =
    2438       72491 :       jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
    2439             : 
    2440             :   Node* if_not_undefined =
    2441       72491 :       graph()->NewNode(common->IfFalse(), branch_undefined);
    2442       72491 :   Node* vheap_number = BuildLoadHeapNumberValue(value, if_not_undefined);
    2443             : 
    2444             :   if_not_smi =
    2445       72491 :       graph()->NewNode(common->Merge(2), if_undefined, if_not_undefined);
    2446             :   vnot_smi = graph()->NewNode(common->Phi(MachineRepresentation::kFloat64, 2),
    2447       72491 :                               vundefined, vheap_number, if_not_smi);
    2448             : 
    2449       72491 :   Node* if_smi = graph()->NewNode(common->IfFalse(), branch);
    2450       72491 :   Node* vfrom_smi = BuildChangeSmiToFloat64(value);
    2451             : 
    2452       72491 :   Node* merge = graph()->NewNode(common->Merge(2), if_not_smi, if_smi);
    2453             :   Node* phi = graph()->NewNode(common->Phi(MachineRepresentation::kFloat64, 2),
    2454       72491 :                                vnot_smi, vfrom_smi, merge);
    2455             : 
    2456       72491 :   return phi;
    2457             : }
    2458             : 
    2459       72491 : Node* WasmGraphBuilder::FromJS(Node* node, Node* context,
    2460      123990 :                                wasm::ValueType type) {
    2461             :   DCHECK_NE(wasm::kWasmStmt, type);
    2462             : 
    2463             :   // Do a JavaScript ToNumber.
    2464       72491 :   Node* num = BuildJavaScriptToNumber(node, context);
    2465             : 
    2466             :   // Change representation.
    2467       72491 :   SimplifiedOperatorBuilder simplified(jsgraph()->zone());
    2468       72491 :   num = BuildChangeTaggedToFloat64(num);
    2469             : 
    2470       72491 :   switch (type) {
    2471             :     case wasm::kWasmI32: {
    2472             :       num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToWord32(),
    2473       48118 :                              num);
    2474       48118 :       break;
    2475             :     }
    2476             :     case wasm::kWasmS128:
    2477             :     case wasm::kWasmI64:
    2478           0 :       UNREACHABLE();
    2479             :     case wasm::kWasmF32:
    2480             :       num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToFloat32(),
    2481        3381 :                              num);
    2482        3381 :       break;
    2483             :     case wasm::kWasmF64:
    2484             :       break;
    2485             :     default:
    2486           0 :       UNREACHABLE();
    2487             :       return nullptr;
    2488             :   }
    2489             :   return num;
    2490             : }
    2491             : 
    2492      122634 : Node* WasmGraphBuilder::BuildChangeInt32ToSmi(Node* value) {
    2493      122634 :   if (jsgraph()->machine()->Is64()) {
    2494       61317 :     value = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), value);
    2495             :   }
    2496             :   return graph()->NewNode(jsgraph()->machine()->WordShl(), value,
    2497      122634 :                           BuildSmiShiftBitsConstant());
    2498             : }
    2499             : 
    2500      222213 : Node* WasmGraphBuilder::BuildChangeSmiToInt32(Node* value) {
    2501             :   value = graph()->NewNode(jsgraph()->machine()->WordSar(), value,
    2502       74071 :                            BuildSmiShiftBitsConstant());
    2503      148142 :   if (jsgraph()->machine()->Is64()) {
    2504             :     value =
    2505       74071 :         graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(), value);
    2506             :   }
    2507       74071 :   return value;
    2508             : }
    2509             : 
    2510        1812 : Node* WasmGraphBuilder::BuildChangeUint32ToSmi(Node* value) {
    2511        1812 :   if (jsgraph()->machine()->Is64()) {
    2512             :     value =
    2513         906 :         graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), value);
    2514             :   }
    2515             :   return graph()->NewNode(jsgraph()->machine()->WordShl(), value,
    2516        1812 :                           BuildSmiShiftBitsConstant());
    2517             : }
    2518             : 
    2519      144982 : Node* WasmGraphBuilder::BuildChangeSmiToFloat64(Node* value) {
    2520             :   return graph()->NewNode(jsgraph()->machine()->ChangeInt32ToFloat64(),
    2521      217473 :                           BuildChangeSmiToInt32(value));
    2522             : }
    2523             : 
    2524      145222 : Node* WasmGraphBuilder::BuildTestNotSmi(Node* value) {
    2525             :   STATIC_ASSERT(kSmiTag == 0);
    2526             :   STATIC_ASSERT(kSmiTagMask == 1);
    2527             :   return graph()->NewNode(jsgraph()->machine()->WordAnd(), value,
    2528      217833 :                           jsgraph()->IntPtrConstant(kSmiTagMask));
    2529             : }
    2530             : 
    2531      136294 : Node* WasmGraphBuilder::BuildSmiShiftBitsConstant() {
    2532      136294 :   return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize);
    2533             : }
    2534             : 
    2535       12944 : Node* WasmGraphBuilder::BuildAllocateHeapNumberWithValue(Node* value,
    2536       44914 :                                                          Node* control) {
    2537       12944 :   MachineOperatorBuilder* machine = jsgraph()->machine();
    2538       12944 :   CommonOperatorBuilder* common = jsgraph()->common();
    2539             :   // The AllocateHeapNumberStub does not use the context, so we can safely pass
    2540             :   // in Smi zero here.
    2541       12944 :   Callable callable = CodeFactory::AllocateHeapNumber(jsgraph()->isolate());
    2542       12944 :   Node* target = jsgraph()->HeapConstant(callable.code());
    2543             :   Node* context = jsgraph()->NoContextConstant();
    2544             :   Node* effect =
    2545             :       graph()->NewNode(common->BeginRegion(RegionObservability::kNotObservable),
    2546       12944 :                        graph()->start());
    2547       12944 :   if (!allocate_heap_number_operator_.is_set()) {
    2548             :     CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
    2549             :         jsgraph()->isolate(), jsgraph()->zone(), callable.descriptor(), 0,
    2550       12164 :         CallDescriptor::kNoFlags, Operator::kNoThrow);
    2551        6082 :     allocate_heap_number_operator_.set(common->Call(descriptor));
    2552             :   }
    2553             :   Node* heap_number = graph()->NewNode(allocate_heap_number_operator_.get(),
    2554             :                                        target, context, effect, control);
    2555             :   Node* store =
    2556             :       graph()->NewNode(machine->Store(StoreRepresentation(
    2557             :                            MachineRepresentation::kFloat64, kNoWriteBarrier)),
    2558             :                        heap_number, BuildHeapNumberValueIndexConstant(), value,
    2559       25888 :                        heap_number, control);
    2560       25888 :   return graph()->NewNode(common->FinishRegion(), heap_number, store);
    2561             : }
    2562             : 
    2563      145222 : Node* WasmGraphBuilder::BuildLoadHeapNumberValue(Node* value, Node* control) {
    2564             :   return graph()->NewNode(jsgraph()->machine()->Load(MachineType::Float64()),
    2565             :                           value, BuildHeapNumberValueIndexConstant(),
    2566      217833 :                           graph()->start(), control);
    2567             : }
    2568             : 
    2569       12944 : Node* WasmGraphBuilder::BuildHeapNumberValueIndexConstant() {
    2570       85555 :   return jsgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag);
    2571             : }
    2572             : 
    2573       28389 : void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code,
    2574      223016 :                                             wasm::FunctionSig* sig) {
    2575       28389 :   int wasm_count = static_cast<int>(sig->parameter_count());
    2576       28389 :   int count = wasm_count + 3;
    2577       28389 :   Node** args = Buffer(count);
    2578             : 
    2579             :   // Build the start and the JS parameter nodes.
    2580       28389 :   Node* start = Start(wasm_count + 5);
    2581       28389 :   *control_ = start;
    2582       28389 :   *effect_ = start;
    2583             : 
    2584             :   // Create the context parameter
    2585             :   Node* context = graph()->NewNode(
    2586             :       jsgraph()->common()->Parameter(
    2587             :           Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"),
    2588       28389 :       graph()->start());
    2589             : 
    2590             :   // Set the ThreadInWasm flag before we do the actual call.
    2591       56778 :   BuildModifyThreadInWasmFlag(true, jsgraph(), effect_, *control_);
    2592             : 
    2593       28389 :   if (!wasm::IsJSCompatibleSignature(sig_)) {
    2594             :     // Throw a TypeError. Use the context of the calling javascript function
    2595             :     // (passed as a parameter), such that the generated code is context
    2596             :     // independent.
    2597             :     BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError, jsgraph(),
    2598         186 :                                   context, nullptr, 0, effect_, control_);
    2599             : 
    2600             :     // Add a dummy call to the wasm function so that the generated wrapper
    2601             :     // contains a reference to the wrapped wasm function. Without this reference
    2602             :     // the wasm function could not be re-imported into another wasm module.
    2603             :     int pos = 0;
    2604          93 :     args[pos++] = HeapConstant(wasm_code);
    2605          93 :     args[pos++] = *effect_;
    2606          93 :     args[pos++] = *control_;
    2607             : 
    2608             :     // We only need a dummy call descriptor.
    2609             :     wasm::FunctionSig::Builder dummy_sig_builder(jsgraph()->zone(), 0, 0);
    2610             :     CallDescriptor* desc = wasm::ModuleEnv::GetWasmCallDescriptor(
    2611         186 :         jsgraph()->zone(), dummy_sig_builder.Build());
    2612         279 :     *effect_ = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args);
    2613          93 :     Return(jsgraph()->UndefinedConstant());
    2614       28389 :     return;
    2615             :   }
    2616             : 
    2617             :   int pos = 0;
    2618       28296 :   args[pos++] = HeapConstant(wasm_code);
    2619             : 
    2620             :   // Convert JS parameters to WASM numbers.
    2621       92917 :   for (int i = 0; i < wasm_count; ++i) {
    2622       36325 :     Node* param = Param(i + 1);
    2623       72650 :     Node* wasm_param = FromJS(param, context, sig->GetParam(i));
    2624       36325 :     args[pos++] = wasm_param;
    2625             :   }
    2626             : 
    2627       28296 :   args[pos++] = *effect_;
    2628       28296 :   args[pos++] = *control_;
    2629             : 
    2630             :   // Call the WASM code.
    2631             :   CallDescriptor* desc =
    2632       28296 :       wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig);
    2633             : 
    2634       56592 :   Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args);
    2635       28296 :   *effect_ = call;
    2636             : 
    2637             :   // Clear the ThreadInWasmFlag
    2638       56592 :   BuildModifyThreadInWasmFlag(false, jsgraph(), effect_, *control_);
    2639             : 
    2640             :   Node* retval = call;
    2641             :   Node* jsval = ToJS(
    2642       56592 :       retval, sig->return_count() == 0 ? wasm::kWasmStmt : sig->GetReturn());
    2643             :   Return(jsval);
    2644             : }
    2645             : 
    2646       37808 : int WasmGraphBuilder::AddParameterNodes(Node** args, int pos, int param_count,
    2647       44723 :                                         wasm::FunctionSig* sig) {
    2648             :   // Convert WASM numbers to JS values.
    2649             :   int param_index = 0;
    2650       82531 :   for (int i = 0; i < param_count; ++i) {
    2651       44723 :     Node* param = Param(param_index++);
    2652       89446 :     args[pos++] = ToJS(param, sig->GetParam(i));
    2653             :   }
    2654       37808 :   return pos;
    2655             : }
    2656             : 
    2657       37883 : void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSReceiver> target,
    2658      379130 :                                             wasm::FunctionSig* sig) {
    2659             :   DCHECK(target->IsCallable());
    2660             : 
    2661       37883 :   int wasm_count = static_cast<int>(sig->parameter_count());
    2662             : 
    2663             :   // Build the start and the parameter nodes.
    2664       37883 :   Isolate* isolate = jsgraph()->isolate();
    2665             :   CallDescriptor* desc;
    2666       37883 :   Node* start = Start(wasm_count + 3);
    2667       37883 :   *effect_ = start;
    2668       37883 :   *control_ = start;
    2669             : 
    2670       37883 :   if (!wasm::IsJSCompatibleSignature(sig_)) {
    2671             :     // Throw a TypeError. Embedding the context is ok here, since this code is
    2672             :     // regenerated at instantiation time.
    2673             :     Node* context =
    2674         150 :         jsgraph()->HeapConstant(jsgraph()->isolate()->native_context());
    2675             :     BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError, jsgraph(),
    2676         150 :                                   context, nullptr, 0, effect_, control_);
    2677             :     // We don't need to return a value here, as the runtime call will not return
    2678             :     // anyway (the c entry stub will trigger stack unwinding).
    2679             :     ReturnVoid();
    2680       37883 :     return;
    2681             :   }
    2682             : 
    2683       37808 :   Node** args = Buffer(wasm_count + 7);
    2684             : 
    2685             :   Node* call = nullptr;
    2686             : 
    2687       75616 :   BuildModifyThreadInWasmFlag(false, jsgraph(), effect_, *control_);
    2688             : 
    2689       37808 :   if (target->IsJSFunction()) {
    2690             :     Handle<JSFunction> function = Handle<JSFunction>::cast(target);
    2691       37763 :     if (function->shared()->internal_formal_parameter_count() == wasm_count) {
    2692             :       int pos = 0;
    2693       37208 :       args[pos++] = jsgraph()->Constant(target);  // target callable.
    2694             :       // Receiver.
    2695       74356 :       if (is_sloppy(function->shared()->language_mode()) &&
    2696             :           !function->shared()->native()) {
    2697             :         args[pos++] =
    2698       74266 :             HeapConstant(handle(function->context()->global_proxy(), isolate));
    2699             :       } else {
    2700             :         args[pos++] = jsgraph()->Constant(
    2701         150 :             handle(isolate->heap()->undefined_value(), isolate));
    2702             :       }
    2703             : 
    2704             :       desc = Linkage::GetJSCallDescriptor(
    2705       74416 :           graph()->zone(), false, wasm_count + 1, CallDescriptor::kNoFlags);
    2706             : 
    2707             :       // Convert WASM numbers to JS values.
    2708       37208 :       pos = AddParameterNodes(args, pos, wasm_count, sig);
    2709             : 
    2710       74416 :       args[pos++] = jsgraph()->UndefinedConstant();        // new target
    2711       74416 :       args[pos++] = jsgraph()->Int32Constant(wasm_count);  // argument count
    2712       74416 :       args[pos++] = HeapConstant(handle(function->context()));
    2713       37208 :       args[pos++] = *effect_;
    2714       37208 :       args[pos++] = *control_;
    2715             : 
    2716       74416 :       call = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args);
    2717             :     }
    2718             :   }
    2719             : 
    2720             :   // We cannot call the target directly, we have to use the Call builtin.
    2721       37808 :   if (!call) {
    2722             :     int pos = 0;
    2723         600 :     Callable callable = CodeFactory::Call(isolate);
    2724         600 :     args[pos++] = jsgraph()->HeapConstant(callable.code());
    2725         600 :     args[pos++] = jsgraph()->Constant(target);           // target callable
    2726         600 :     args[pos++] = jsgraph()->Int32Constant(wasm_count);  // argument count
    2727             :     args[pos++] = jsgraph()->Constant(
    2728        1200 :         handle(isolate->heap()->undefined_value(), isolate));  // receiver
    2729             : 
    2730             :     desc = Linkage::GetStubCallDescriptor(isolate, graph()->zone(),
    2731             :                                           callable.descriptor(), wasm_count + 1,
    2732        1800 :                                           CallDescriptor::kNoFlags);
    2733             : 
    2734             :     // Convert WASM numbers to JS values.
    2735         600 :     pos = AddParameterNodes(args, pos, wasm_count, sig);
    2736             : 
    2737             :     // The native_context is sufficient here, because all kind of callables
    2738             :     // which depend on the context provide their own context. The context here
    2739             :     // is only needed if the target is a constructor to throw a TypeError, if
    2740             :     // the target is a native function, or if the target is a callable JSObject,
    2741             :     // which can only be constructed by the runtime.
    2742        1200 :     args[pos++] = HeapConstant(isolate->native_context());
    2743         600 :     args[pos++] = *effect_;
    2744         600 :     args[pos++] = *control_;
    2745             : 
    2746        1200 :     call = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args);
    2747             :   }
    2748             : 
    2749       37808 :   *effect_ = call;
    2750       37808 :   SetSourcePosition(call, 0);
    2751             : 
    2752       75616 :   BuildModifyThreadInWasmFlag(true, jsgraph(), effect_, *control_);
    2753             : 
    2754             :   // Convert the return value back.
    2755             :   Node* val = sig->return_count() == 0
    2756             :                   ? jsgraph()->Int32Constant(0)
    2757             :                   : FromJS(call, HeapConstant(isolate->native_context()),
    2758      111782 :                            sig->GetReturn());
    2759             :   Return(val);
    2760             : }
    2761             : 
    2762        1369 : void WasmGraphBuilder::BuildWasmInterpreterEntry(
    2763       11247 :     uint32_t function_index, wasm::FunctionSig* sig,
    2764       11605 :     Handle<WasmInstanceObject> instance) {
    2765        1369 :   int wasm_count = static_cast<int>(sig->parameter_count());
    2766        1369 :   int param_count = jsgraph()->machine()->Is64()
    2767             :                         ? wasm_count
    2768        1369 :                         : Int64Lowering::GetParameterCountAfterLowering(sig);
    2769             : 
    2770             :   // Build the start and the parameter nodes.
    2771        1369 :   Node* start = Start(param_count + 3);
    2772        1369 :   *effect_ = start;
    2773        1369 :   *control_ = start;
    2774             : 
    2775             :   // Compute size for the argument buffer.
    2776        1369 :   int args_size_bytes = 0;
    2777        2598 :   for (int i = 0; i < wasm_count; i++) {
    2778        2458 :     args_size_bytes += 1 << ElementSizeLog2Of(sig->GetParam(i));
    2779             :   }
    2780             : 
    2781             :   // The return value is also passed via this buffer:
    2782             :   DCHECK_GE(wasm::kV8MaxWasmFunctionReturns, sig->return_count());
    2783             :   // TODO(wasm): Handle multi-value returns.
    2784             :   DCHECK_EQ(1, wasm::kV8MaxWasmFunctionReturns);
    2785             :   int return_size_bytes =
    2786        2520 :       sig->return_count() == 0 ? 0 : 1 << ElementSizeLog2Of(sig->GetReturn(0));
    2787             : 
    2788             :   // Get a stack slot for the arguments.
    2789        1369 :   Node* arg_buffer = args_size_bytes == 0 && return_size_bytes == 0
    2790             :                          ? jsgraph()->IntPtrConstant(0)
    2791             :                          : graph()->NewNode(jsgraph()->machine()->StackSlot(
    2792        3998 :                                std::max(args_size_bytes, return_size_bytes)));
    2793             : 
    2794             :   // Now store all our arguments to the buffer.
    2795             :   int param_index = 0;
    2796             :   int offset = 0;
    2797             : 
    2798        2598 :   for (int i = 0; i < wasm_count; i++) {
    2799        1229 :     Node* param = Param(param_index++);
    2800        1229 :     if (Int64Lowering::IsI64AsTwoParameters(jsgraph()->machine(),
    2801        2458 :                                             sig->GetParam(i))) {
    2802             :       StoreRepresentation store_rep(wasm::kWasmI32,
    2803             :                                     WriteBarrierKind::kNoWriteBarrier);
    2804             :       *effect_ =
    2805             :           graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer,
    2806             :                            Int32Constant(offset + kInt64LowerHalfMemoryOffset),
    2807           0 :                            param, *effect_, *control_);
    2808             : 
    2809           0 :       param = Param(param_index++);
    2810             :       *effect_ =
    2811             :           graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer,
    2812             :                            Int32Constant(offset + kInt64UpperHalfMemoryOffset),
    2813           0 :                            param, *effect_, *control_);
    2814           0 :       offset += 8;
    2815             : 
    2816             :     } else {
    2817             :       MachineRepresentation param_rep = sig->GetParam(i);
    2818             :       StoreRepresentation store_rep(param_rep,
    2819             :                                     WriteBarrierKind::kNoWriteBarrier);
    2820             :       *effect_ =
    2821             :           graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer,
    2822        3687 :                            Int32Constant(offset), param, *effect_, *control_);
    2823        1229 :       offset += 1 << ElementSizeLog2Of(param_rep);
    2824             :     }
    2825             :   }
    2826             :   DCHECK_EQ(param_count, param_index);
    2827             :   DCHECK_EQ(args_size_bytes, offset);
    2828             : 
    2829             :   // We are passing the raw arg_buffer here. To the GC and other parts, it looks
    2830             :   // like a Smi (lowest bit not set). In the runtime function however, don't
    2831             :   // call Smi::value on it, but just cast it to a byte pointer.
    2832             :   Node* parameters[] = {
    2833        2738 :       jsgraph()->HeapConstant(instance),       // wasm instance
    2834        1369 :       jsgraph()->SmiConstant(function_index),  // function index
    2835             :       arg_buffer,                              // argument buffer
    2836        2738 :   };
    2837             :   BuildCallToRuntime(Runtime::kWasmRunInterpreter, jsgraph(), parameters,
    2838        2738 :                      arraysize(parameters), effect_, control_);
    2839             : 
    2840             :   // Read back the return value.
    2841        1369 :   if (sig->return_count() == 0) {
    2842             :     Return(Int32Constant(0));
    2843        1151 :   } else if (Int64Lowering::IsI64AsTwoParameters(jsgraph()->machine(),
    2844        1151 :                                                  sig->GetReturn())) {
    2845           0 :     MachineType load_rep = wasm::WasmOpcodes::MachineTypeFor(wasm::kWasmI32);
    2846             :     Node* lower =
    2847             :         graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer,
    2848             :                          Int32Constant(kInt64LowerHalfMemoryOffset), *effect_,
    2849           0 :                          *control_);
    2850             :     Node* upper =
    2851             :         graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer,
    2852             :                          Int32Constant(kInt64UpperHalfMemoryOffset), lower,
    2853           0 :                          *control_);
    2854           0 :     *effect_ = upper;
    2855             :     Return(lower, upper);
    2856             :   } else {
    2857        1151 :     MachineType load_rep = wasm::WasmOpcodes::MachineTypeFor(sig->GetReturn());
    2858             :     Node* val =
    2859             :         graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer,
    2860        2302 :                          Int32Constant(0), *effect_, *control_);
    2861             :     Return(val);
    2862             :   }
    2863        1369 : }
    2864             : 
    2865      144086 : Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
    2866             :   DCHECK_NOT_NULL(module_);
    2867             :   uintptr_t mem_start = reinterpret_cast<uintptr_t>(
    2868      135151 :       module_->instance ? module_->instance->mem_start : nullptr);
    2869      135151 :   if (offset == 0) {
    2870      132867 :     if (!mem_buffer_) {
    2871             :       mem_buffer_ = jsgraph()->RelocatableIntPtrConstant(
    2872       13302 :           mem_start, RelocInfo::WASM_MEMORY_REFERENCE);
    2873             :     }
    2874      132865 :     return mem_buffer_;
    2875             :   } else {
    2876             :     return jsgraph()->RelocatableIntPtrConstant(
    2877        4568 :         mem_start + offset, RelocInfo::WASM_MEMORY_REFERENCE);
    2878             :   }
    2879             : }
    2880             : 
    2881        1108 : Node* WasmGraphBuilder::CurrentMemoryPages() {
    2882             :   // CurrentMemoryPages will not be called from asm.js, hence we cannot be in
    2883             :   // lazy-compilation mode, hence the instance will be set.
    2884             :   DCHECK_EQ(wasm::kWasmOrigin, module_->module->get_origin());
    2885             :   DCHECK_NOT_NULL(module_);
    2886             :   DCHECK_NOT_NULL(module_->instance);
    2887             :   Node* call = BuildCallToRuntime(Runtime::kWasmMemorySize, jsgraph(), nullptr,
    2888        1108 :                                   0, effect_, control_);
    2889         554 :   Node* result = BuildChangeSmiToInt32(call);
    2890         554 :   return result;
    2891             : }
    2892             : 
    2893      120368 : Node* WasmGraphBuilder::MemSize() {
    2894             :   DCHECK_NOT_NULL(module_);
    2895      117278 :   if (mem_size_) return mem_size_;
    2896        3090 :   uint32_t size = module_->instance ? module_->instance->mem_size : 0;
    2897             :   mem_size_ = jsgraph()->RelocatableInt32Constant(
    2898        6180 :       size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
    2899        3090 :   return mem_size_;
    2900             : }
    2901             : 
    2902        4178 : void WasmGraphBuilder::EnsureFunctionTableNodes() {
    2903        7092 :   if (function_tables_.size() > 0) return;
    2904        3628 :   size_t tables_size = module_->module->function_tables.size();
    2905             :   if (module_->instance) {
    2906             :     DCHECK_EQ(tables_size, module_->instance->function_tables.size());
    2907             :     DCHECK_EQ(tables_size, module_->instance->signature_tables.size());
    2908             :   }
    2909        3628 :   for (size_t i = 0; i < tables_size; ++i) {
    2910        3628 :     auto function_handle = (*module_->function_tables)[i];
    2911        3628 :     auto signature_handle = (*module_->signature_tables)[i];
    2912        3628 :     function_tables_.push_back(HeapConstant(function_handle));
    2913        3628 :     signature_tables_.push_back(HeapConstant(signature_handle));
    2914        3628 :     uint32_t table_size = module_->module->function_tables[i].min_size;
    2915             :     function_table_sizes_.push_back(jsgraph()->RelocatableInt32Constant(
    2916             :         static_cast<uint32_t>(table_size),
    2917        5442 :         RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE));
    2918             :   }
    2919             : }
    2920             : 
    2921       31315 : Node* WasmGraphBuilder::GetGlobal(uint32_t index) {
    2922             :   MachineType mem_type =
    2923       15658 :       wasm::WasmOpcodes::MachineTypeFor(module_->GetGlobalType(index));
    2924             :   byte* globals_start =
    2925        7828 :       module_->instance ? module_->instance->globals_start : nullptr;
    2926             :   uintptr_t global_addr = reinterpret_cast<uintptr_t>(
    2927       15656 :       globals_start + module_->module->globals[index].offset);
    2928             :   Node* addr = jsgraph()->RelocatableIntPtrConstant(
    2929       15656 :       global_addr, RelocInfo::WASM_GLOBAL_REFERENCE);
    2930        7829 :   const Operator* op = jsgraph()->machine()->Load(mem_type);
    2931             :   Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), *effect_,
    2932       15658 :                                 *control_);
    2933        7829 :   *effect_ = node;
    2934        7829 :   return node;
    2935             : }
    2936             : 
    2937       43800 : Node* WasmGraphBuilder::SetGlobal(uint32_t index, Node* val) {
    2938             :   MachineType mem_type =
    2939       21900 :       wasm::WasmOpcodes::MachineTypeFor(module_->GetGlobalType(index));
    2940             :   byte* globals_start =
    2941       10950 :       module_->instance ? module_->instance->globals_start : 0;
    2942             :   Node* addr = jsgraph()->RelocatableIntPtrConstant(
    2943       10950 :       reinterpret_cast<uintptr_t>(globals_start +
    2944       10950 :                                   module_->module->globals[index].offset),
    2945       21900 :       RelocInfo::WASM_GLOBAL_REFERENCE);
    2946             :   const Operator* op = jsgraph()->machine()->Store(
    2947       21900 :       StoreRepresentation(mem_type.representation(), kNoWriteBarrier));
    2948             :   Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), val,
    2949       21900 :                                 *effect_, *control_);
    2950       10950 :   *effect_ = node;
    2951       10950 :   return node;
    2952             : }
    2953             : 
    2954       32445 : void WasmGraphBuilder::BoundsCheckMem(MachineType memtype, Node* index,
    2955             :                                       uint32_t offset,
    2956       22127 :                                       wasm::WasmCodePosition position) {
    2957       16223 :   if (FLAG_wasm_no_bounds_checks) return;
    2958             :   uint32_t size =
    2959       16222 :       module_ && module_->instance ? module_->instance->mem_size : 0;
    2960             :   byte memsize = wasm::WasmOpcodes::MemSize(memtype);
    2961             : 
    2962             :   size_t effective_size;
    2963       16223 :   if (size <= offset || size < (static_cast<uint64_t>(offset) + memsize)) {
    2964             :     // Two checks are needed in the case where the offset is statically
    2965             :     // out of bounds; one check for the offset being in bounds, and the next for
    2966             :     // the offset + index being out of bounds for code to be patched correctly
    2967             :     // on relocation.
    2968             : 
    2969             :     // Check for overflows.
    2970        1604 :     if ((std::numeric_limits<uint32_t>::max() - memsize) + 1 < offset) {
    2971             :       // Always trap. Do not use TrapAlways because it does not create a valid
    2972             :       // graph here.
    2973             :       TrapIfEq32(wasm::kTrapMemOutOfBounds, jsgraph()->Int32Constant(0), 0,
    2974           6 :                  position);
    2975           6 :       return;
    2976             :     }
    2977        1598 :     size_t effective_offset = (offset - 1) + memsize;
    2978             : 
    2979             :     Node* cond = graph()->NewNode(jsgraph()->machine()->Uint32LessThan(),
    2980             :                                   jsgraph()->IntPtrConstant(effective_offset),
    2981             :                                   jsgraph()->RelocatableInt32Constant(
    2982             :                                       static_cast<uint32_t>(size),
    2983        6391 :                                       RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
    2984        1597 :     TrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position);
    2985             :     // For offset > effective size, this relies on check above to fail and
    2986             :     // effective size can be negative, relies on wrap around.
    2987        1598 :     effective_size = size - offset - memsize + 1;
    2988             :   } else {
    2989       14619 :     effective_size = size - offset - memsize + 1;
    2990       14619 :     CHECK(effective_size <= kMaxUInt32);
    2991             : 
    2992             :     Uint32Matcher m(index);
    2993       14619 :     if (m.HasValue()) {
    2994             :       uint32_t value = m.Value();
    2995        8397 :       if (value < effective_size) {
    2996             :         // The bounds check will always succeed.
    2997             :         return;
    2998             :       }
    2999             :     }
    3000             :   }
    3001             : 
    3002             :   Node* cond = graph()->NewNode(jsgraph()->machine()->Uint32LessThan(), index,
    3003             :                                 jsgraph()->RelocatableInt32Constant(
    3004             :                                     static_cast<uint32_t>(effective_size),
    3005       25993 :                                     RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
    3006        8662 :   TrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position);
    3007             : }
    3008             : 
    3009       15990 : Node* WasmGraphBuilder::LoadMem(wasm::ValueType type, MachineType memtype,
    3010             :                                 Node* index, uint32_t offset,
    3011             :                                 uint32_t alignment,
    3012       28247 :                                 wasm::WasmCodePosition position) {
    3013             :   Node* load;
    3014             : 
    3015             :   // WASM semantics throw on OOB. Introduce explicit bounds check.
    3016       15990 :   if (!FLAG_wasm_trap_handler || !V8_TRAP_HANDLER_SUPPORTED) {
    3017       14520 :     BoundsCheckMem(memtype, index, offset, position);
    3018             :   }
    3019             : 
    3020       26735 :   if (memtype.representation() == MachineRepresentation::kWord8 ||
    3021       10745 :       jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) {
    3022       15990 :     if (FLAG_wasm_trap_handler && V8_TRAP_HANDLER_SUPPORTED) {
    3023             :       DCHECK(FLAG_wasm_guard_pages);
    3024        1470 :       Node* position_node = jsgraph()->Int32Constant(position);
    3025             :       load = graph()->NewNode(jsgraph()->machine()->ProtectedLoad(memtype),
    3026             :                               MemBuffer(offset), index, position_node, *effect_,
    3027        2940 :                               *control_);
    3028             :     } else {
    3029             :       load = graph()->NewNode(jsgraph()->machine()->Load(memtype),
    3030       29040 :                               MemBuffer(offset), index, *effect_, *control_);
    3031             :     }
    3032             :   } else {
    3033             :     // TODO(eholk): Support unaligned loads with trap handlers.
    3034             :     DCHECK(!FLAG_wasm_trap_handler || !V8_TRAP_HANDLER_SUPPORTED);
    3035             :     load = graph()->NewNode(jsgraph()->machine()->UnalignedLoad(memtype),
    3036           0 :                             MemBuffer(offset), index, *effect_, *control_);
    3037             :   }
    3038             : 
    3039       15990 :   *effect_ = load;
    3040             : 
    3041             : #if defined(V8_TARGET_BIG_ENDIAN)
    3042             :   load = BuildChangeEndianness(load, memtype, type);
    3043             : #endif
    3044             : 
    3045       17092 :   if (type == wasm::kWasmI64 &&
    3046        1102 :       ElementSizeLog2Of(memtype.representation()) < 3) {
    3047             :     // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes.
    3048          42 :     if (memtype.IsSigned()) {
    3049             :       // sign extend
    3050          42 :       load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load);
    3051             :     } else {
    3052             :       // zero extend
    3053             :       load =
    3054           0 :           graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), load);
    3055             :     }
    3056             :   }
    3057             : 
    3058       15990 :   return load;
    3059             : }
    3060             : 
    3061             : 
    3062        1883 : Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index,
    3063             :                                  uint32_t offset, uint32_t alignment, Node* val,
    3064        3631 :                                  wasm::WasmCodePosition position) {
    3065             :   Node* store;
    3066             : 
    3067             :   // WASM semantics throw on OOB. Introduce explicit bounds check.
    3068        1883 :   if (!FLAG_wasm_trap_handler || !V8_TRAP_HANDLER_SUPPORTED) {
    3069        1702 :     BoundsCheckMem(memtype, index, offset, position);
    3070             :   }
    3071             : 
    3072             : #if defined(V8_TARGET_BIG_ENDIAN)
    3073             :   val = BuildChangeEndianness(val, memtype);
    3074             : #endif
    3075             : 
    3076        3451 :   if (memtype.representation() == MachineRepresentation::kWord8 ||
    3077        1568 :       jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) {
    3078        1883 :     if (FLAG_wasm_trap_handler && V8_TRAP_HANDLER_SUPPORTED) {
    3079         180 :       Node* position_node = jsgraph()->Int32Constant(position);
    3080             :       store = graph()->NewNode(
    3081             :           jsgraph()->machine()->ProtectedStore(memtype.representation()),
    3082         360 :           MemBuffer(offset), index, val, position_node, *effect_, *control_);
    3083             :     } else {
    3084             :       StoreRepresentation rep(memtype.representation(), kNoWriteBarrier);
    3085             :       store =
    3086             :           graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset),
    3087        3406 :                            index, val, *effect_, *control_);
    3088             :     }
    3089             :   } else {
    3090             :     // TODO(eholk): Support unaligned stores with trap handlers.
    3091             :     DCHECK(!FLAG_wasm_trap_handler || !V8_TRAP_HANDLER_SUPPORTED);
    3092             :     UnalignedStoreRepresentation rep(memtype.representation());
    3093             :     store =
    3094             :         graph()->NewNode(jsgraph()->machine()->UnalignedStore(rep),
    3095           0 :                          MemBuffer(offset), index, val, *effect_, *control_);
    3096             :   }
    3097             : 
    3098        1883 :   *effect_ = store;
    3099             : 
    3100        1883 :   return store;
    3101             : }
    3102             : 
    3103       68223 : Node* WasmGraphBuilder::BuildAsmjsLoadMem(MachineType type, Node* index) {
    3104             :   // TODO(turbofan): fold bounds checks for constant asm.js loads.
    3105             :   // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish).
    3106       68223 :   const Operator* op = jsgraph()->machine()->CheckedLoad(type);
    3107             :   Node* load =
    3108       68223 :       graph()->NewNode(op, MemBuffer(0), index, MemSize(), *effect_, *control_);
    3109       68223 :   *effect_ = load;
    3110       68223 :   return load;
    3111             : }
    3112             : 
    3113       49055 : Node* WasmGraphBuilder::BuildAsmjsStoreMem(MachineType type, Node* index,
    3114       49055 :                                            Node* val) {
    3115             :   // TODO(turbofan): fold bounds checks for constant asm.js stores.
    3116             :   // asm.js semantics use CheckedStore (i.e. ignore OOB writes).
    3117             :   const Operator* op =
    3118       98110 :       jsgraph()->machine()->CheckedStore(type.representation());
    3119             :   Node* store = graph()->NewNode(op, MemBuffer(0), index, MemSize(), val,
    3120       49055 :                                  *effect_, *control_);
    3121       49055 :   *effect_ = store;
    3122       49055 :   return val;
    3123             : }
    3124             : 
    3125           0 : void WasmGraphBuilder::PrintDebugName(Node* node) {
    3126           0 :   PrintF("#%d:%s", node->id(), node->op()->mnemonic());
    3127           0 : }
    3128             : 
    3129           0 : Node* WasmGraphBuilder::String(const char* string) {
    3130             :   return jsgraph()->Constant(
    3131           0 :       jsgraph()->isolate()->factory()->NewStringFromAsciiChecked(string));
    3132             : }
    3133             : 
    3134     4227249 : Graph* WasmGraphBuilder::graph() { return jsgraph()->graph(); }
    3135             : 
    3136       24292 : void WasmGraphBuilder::Int64LoweringForTesting() {
    3137       48584 :   if (jsgraph()->machine()->Is32()) {
    3138             :     Int64Lowering r(jsgraph()->graph(), jsgraph()->machine(),
    3139           0 :                     jsgraph()->common(), jsgraph()->zone(), sig_);
    3140           0 :     r.LowerGraph();
    3141             :   }
    3142       24292 : }
    3143             : 
    3144           0 : void WasmGraphBuilder::SimdScalarLoweringForTesting() {
    3145           0 :   SimdScalarLowering(jsgraph(), sig_).LowerGraph();
    3146           0 : }
    3147             : 
    3148      218525 : void WasmGraphBuilder::SetSourcePosition(Node* node,
    3149             :                                          wasm::WasmCodePosition position) {
    3150             :   DCHECK_NE(position, wasm::kNoCodePosition);
    3151      218525 :   if (source_position_table_)
    3152      112154 :     source_position_table_->SetSourcePosition(node, SourcePosition(position));
    3153      218519 : }
    3154             : 
    3155         686 : Node* WasmGraphBuilder::S128Zero() {
    3156         343 :   has_simd_ = true;
    3157         686 :   return graph()->NewNode(jsgraph()->machine()->S128Zero());
    3158             : }
    3159             : 
    3160           0 : Node* WasmGraphBuilder::S1x4Zero() {
    3161           0 :   has_simd_ = true;
    3162           0 :   return graph()->NewNode(jsgraph()->machine()->S1x4Zero());
    3163             : }
    3164             : 
    3165           0 : Node* WasmGraphBuilder::S1x8Zero() {
    3166           0 :   has_simd_ = true;
    3167           0 :   return graph()->NewNode(jsgraph()->machine()->S1x8Zero());
    3168             : }
    3169             : 
    3170           0 : Node* WasmGraphBuilder::S1x16Zero() {
    3171           0 :   has_simd_ = true;
    3172           0 :   return graph()->NewNode(jsgraph()->machine()->S1x16Zero());
    3173             : }
    3174             : 
    3175        1029 : Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode,
    3176        1029 :                                const NodeVector& inputs) {
    3177        1029 :   has_simd_ = true;
    3178        1029 :   switch (opcode) {
    3179             :     case wasm::kExprF32x4Splat:
    3180        1029 :       return graph()->NewNode(jsgraph()->machine()->F32x4Splat(), inputs[0]);
    3181             :     case wasm::kExprF32x4SConvertI32x4:
    3182             :       return graph()->NewNode(jsgraph()->machine()->F32x4SConvertI32x4(),
    3183           0 :                               inputs[0]);
    3184             :     case wasm::kExprF32x4UConvertI32x4:
    3185             :       return graph()->NewNode(jsgraph()->machine()->F32x4UConvertI32x4(),
    3186           0 :                               inputs[0]);
    3187             :     case wasm::kExprF32x4Abs:
    3188           0 :       return graph()->NewNode(jsgraph()->machine()->F32x4Abs(), inputs[0]);
    3189             :     case wasm::kExprF32x4Neg:
    3190           0 :       return graph()->NewNode(jsgraph()->machine()->F32x4Neg(), inputs[0]);
    3191             :     case wasm::kExprF32x4RecipApprox:
    3192             :       return graph()->NewNode(jsgraph()->machine()->F32x4RecipApprox(),
    3193           0 :                               inputs[0]);
    3194             :     case wasm::kExprF32x4RecipSqrtApprox:
    3195             :       return graph()->NewNode(jsgraph()->machine()->F32x4RecipSqrtApprox(),
    3196           0 :                               inputs[0]);
    3197             :     case wasm::kExprF32x4Add:
    3198             :       return graph()->NewNode(jsgraph()->machine()->F32x4Add(), inputs[0],
    3199           0 :                               inputs[1]);
    3200             :     case wasm::kExprF32x4AddHoriz:
    3201             :       return graph()->NewNode(jsgraph()->machine()->F32x4AddHoriz(), inputs[0],
    3202           0 :                               inputs[1]);
    3203             :     case wasm::kExprF32x4Sub:
    3204             :       return graph()->NewNode(jsgraph()->machine()->F32x4Sub(), inputs[0],
    3205           0 :                               inputs[1]);
    3206             :     case wasm::kExprF32x4Mul:
    3207             :       return graph()->NewNode(jsgraph()->machine()->F32x4Mul(), inputs[0],
    3208           0 :                               inputs[1]);
    3209             :     case wasm::kExprF32x4Min:
    3210             :       return graph()->NewNode(jsgraph()->machine()->F32x4Min(), inputs[0],
    3211           0 :                               inputs[1]);
    3212             :     case wasm::kExprF32x4Max:
    3213             :       return graph()->NewNode(jsgraph()->machine()->F32x4Max(), inputs[0],
    3214           0 :                               inputs[1]);
    3215             :     case wasm::kExprF32x4Eq:
    3216             :       return graph()->NewNode(jsgraph()->machine()->F32x4Eq(), inputs[0],
    3217           0 :                               inputs[1]);
    3218             :     case wasm::kExprF32x4Ne:
    3219             :       return graph()->NewNode(jsgraph()->machine()->F32x4Ne(), inputs[0],
    3220           0 :                               inputs[1]);
    3221             :     case wasm::kExprF32x4Lt:
    3222             :       return graph()->NewNode(jsgraph()->machine()->F32x4Lt(), inputs[0],
    3223           0 :                               inputs[1]);
    3224             :     case wasm::kExprF32x4Le:
    3225             :       return graph()->NewNode(jsgraph()->machine()->F32x4Le(), inputs[0],
    3226           0 :                               inputs[1]);
    3227             :     case wasm::kExprF32x4Gt:
    3228             :       return graph()->NewNode(jsgraph()->machine()->F32x4Lt(), inputs[1],
    3229           0 :                               inputs[0]);
    3230             :     case wasm::kExprF32x4Ge:
    3231             :       return graph()->NewNode(jsgraph()->machine()->F32x4Le(), inputs[1],
    3232           0 :                               inputs[0]);
    3233             :     case wasm::kExprI32x4Splat:
    3234         630 :       return graph()->NewNode(jsgraph()->machine()->I32x4Splat(), inputs[0]);
    3235             :     case wasm::kExprI32x4SConvertF32x4:
    3236             :       return graph()->NewNode(jsgraph()->machine()->I32x4SConvertF32x4(),
    3237           0 :                               inputs[0]);
    3238             :     case wasm::kExprI32x4UConvertF32x4:
    3239             :       return graph()->NewNode(jsgraph()->machine()->I32x4UConvertF32x4(),
    3240           0 :                               inputs[0]);
    3241             :     case wasm::kExprI32x4SConvertI16x8Low:
    3242             :       return graph()->NewNode(jsgraph()->machine()->I32x4SConvertI16x8Low(),
    3243           0 :                               inputs[0]);
    3244             :     case wasm::kExprI32x4SConvertI16x8High:
    3245             :       return graph()->NewNode(jsgraph()->machine()->I32x4SConvertI16x8High(),
    3246           0 :                               inputs[0]);
    3247             :     case wasm::kExprI32x4Neg:
    3248           0 :       return graph()->NewNode(jsgraph()->machine()->I32x4Neg(), inputs[0]);
    3249             :     case wasm::kExprI32x4Add:
    3250             :       return graph()->NewNode(jsgraph()->machine()->I32x4Add(), inputs[0],
    3251          21 :                               inputs[1]);
    3252             :     case wasm::kExprI32x4AddHoriz:
    3253             :       return graph()->NewNode(jsgraph()->machine()->I32x4AddHoriz(), inputs[0],
    3254           0 :                               inputs[1]);
    3255             :     case wasm::kExprI32x4Sub:
    3256             :       return graph()->NewNode(jsgraph()->machine()->I32x4Sub(), inputs[0],
    3257          21 :                               inputs[1]);
    3258             :     case wasm::kExprI32x4Mul:
    3259             :       return graph()->NewNode(jsgraph()->machine()->I32x4Mul(), inputs[0],
    3260          21 :                               inputs[1]);
    3261             :     case wasm::kExprI32x4MinS:
    3262             :       return graph()->NewNode(jsgraph()->machine()->I32x4MinS(), inputs[0],
    3263          21 :                               inputs[1]);
    3264             :     case wasm::kExprI32x4MaxS:
    3265             :       return graph()->NewNode(jsgraph()->machine()->I32x4MaxS(), inputs[0],
    3266          21 :                               inputs[1]);
    3267             :     case wasm::kExprI32x4Eq:
    3268             :       return graph()->NewNode(jsgraph()->machine()->I32x4Eq(), inputs[0],
    3269          21 :                               inputs[1]);
    3270             :     case wasm::kExprI32x4Ne:
    3271             :       return graph()->NewNode(jsgraph()->machine()->I32x4Ne(), inputs[0],
    3272          42 :                               inputs[1]);
    3273             :     case wasm::kExprI32x4LtS:
    3274             :       return graph()->NewNode(jsgraph()->machine()->I32x4LtS(), inputs[0],
    3275           0 :                               inputs[1]);
    3276             :     case wasm::kExprI32x4LeS:
    3277             :       return graph()->NewNode(jsgraph()->machine()->I32x4LeS(), inputs[0],
    3278           0 :                               inputs[1]);
    3279             :     case wasm::kExprI32x4GtS:
    3280             :       return graph()->NewNode(jsgraph()->machine()->I32x4LtS(), inputs[1],
    3281           0 :                               inputs[0]);
    3282             :     case wasm::kExprI32x4GeS:
    3283             :       return graph()->NewNode(jsgraph()->machine()->I32x4LeS(), inputs[1],
    3284           0 :                               inputs[0]);
    3285             :     case wasm::kExprI32x4UConvertI16x8Low:
    3286             :       return graph()->NewNode(jsgraph()->machine()->I32x4UConvertI16x8Low(),
    3287           0 :                               inputs[0]);
    3288             :     case wasm::kExprI32x4UConvertI16x8High:
    3289             :       return graph()->NewNode(jsgraph()->machine()->I32x4UConvertI16x8High(),
    3290           0 :                               inputs[0]);
    3291             :     case wasm::kExprI32x4MinU:
    3292             :       return graph()->NewNode(jsgraph()->machine()->I32x4MinU(), inputs[0],
    3293          21 :                               inputs[1]);
    3294             :     case wasm::kExprI32x4MaxU:
    3295             :       return graph()->NewNode(jsgraph()->machine()->I32x4MaxU(), inputs[0],
    3296          21 :                               inputs[1]);
    3297             :     case wasm::kExprI32x4LtU:
    3298             :       return graph()->NewNode(jsgraph()->machine()->I32x4LtU(), inputs[0],
    3299           0 :                               inputs[1]);
    3300             :     case wasm::kExprI32x4LeU:
    3301             :       return graph()->NewNode(jsgraph()->machine()->I32x4LeU(), inputs[0],
    3302           0 :                               inputs[1]);
    3303             :     case wasm::kExprI32x4GtU:
    3304             :       return graph()->NewNode(jsgraph()->machine()->I32x4LtU(), inputs[1],
    3305           0 :                               inputs[0]);
    3306             :     case wasm::kExprI32x4GeU:
    3307             :       return graph()->NewNode(jsgraph()->machine()->I32x4LeU(), inputs[1],
    3308           0 :                               inputs[0]);
    3309             :     case wasm::kExprI16x8Splat:
    3310         798 :       return graph()->NewNode(jsgraph()->machine()->I16x8Splat(), inputs[0]);
    3311             :     case wasm::kExprI16x8SConvertI8x16Low:
    3312             :       return graph()->NewNode(jsgraph()->machine()->I16x8SConvertI8x16Low(),
    3313           0 :                               inputs[0]);
    3314             :     case wasm::kExprI16x8SConvertI8x16High:
    3315             :       return graph()->NewNode(jsgraph()->machine()->I16x8SConvertI8x16High(),
    3316           0 :                               inputs[0]);
    3317             :     case wasm::kExprI16x8Neg:
    3318           0 :       return graph()->NewNode(jsgraph()->machine()->I16x8Neg(), inputs[0]);
    3319             :     case wasm::kExprI16x8SConvertI32x4:
    3320             :       return graph()->NewNode(jsgraph()->machine()->I16x8SConvertI32x4(),
    3321           0 :                               inputs[0], inputs[1]);
    3322             :     case wasm::kExprI16x8Add:
    3323             :       return graph()->NewNode(jsgraph()->machine()->I16x8Add(), inputs[0],
    3324          21 :                               inputs[1]);
    3325             :     case wasm::kExprI16x8AddSaturateS:
    3326             :       return graph()->NewNode(jsgraph()->machine()->I16x8AddSaturateS(),
    3327          21 :                               inputs[0], inputs[1]);
    3328             :     case wasm::kExprI16x8AddHoriz:
    3329             :       return graph()->NewNode(jsgraph()->machine()->I16x8AddHoriz(), inputs[0],
    3330           0 :                               inputs[1]);
    3331             :     case wasm::kExprI16x8Sub:
    3332             :       return graph()->NewNode(jsgraph()->machine()->I16x8Sub(), inputs[0],
    3333          21 :                               inputs[1]);
    3334             :     case wasm::kExprI16x8SubSaturateS:
    3335             :       return graph()->NewNode(jsgraph()->machine()->I16x8SubSaturateS(),
    3336          21 :                               inputs[0], inputs[1]);
    3337             :     case wasm::kExprI16x8Mul:
    3338             :       return graph()->NewNode(jsgraph()->machine()->I16x8Mul(), inputs[0],
    3339          21 :                               inputs[1]);
    3340             :     case wasm::kExprI16x8MinS:
    3341             :       return graph()->NewNode(jsgraph()->machine()->I16x8MinS(), inputs[0],
    3342          21 :                               inputs[1]);
    3343             :     case wasm::kExprI16x8MaxS:
    3344             :       return graph()->NewNode(jsgraph()->machine()->I16x8MaxS(), inputs[0],
    3345          21 :                               inputs[1]);
    3346             :     case wasm::kExprI16x8Eq:
    3347             :       return graph()->NewNode(jsgraph()->machine()->I16x8Eq(), inputs[0],
    3348          21 :                               inputs[1]);
    3349             :     case wasm::kExprI16x8Ne:
    3350             :       return graph()->NewNode(jsgraph()->machine()->I16x8Ne(), inputs[0],
    3351          42 :                               inputs[1]);
    3352             :     case wasm::kExprI16x8LtS:
    3353             :       return graph()->NewNode(jsgraph()->machine()->I16x8LtS(), inputs[0],
    3354           0 :                               inputs[1]);
    3355             :     case wasm::kExprI16x8LeS:
    3356             :       return graph()->NewNode(jsgraph()->machine()->I16x8LeS(), inputs[0],
    3357           0 :                               inputs[1]);
    3358             :     case wasm::kExprI16x8GtS:
    3359             :       return graph()->NewNode(jsgraph()->machine()->I16x8LtS(), inputs[1],
    3360           0 :                               inputs[0]);
    3361             :     case wasm::kExprI16x8GeS:
    3362             :       return graph()->NewNode(jsgraph()->machine()->I16x8LeS(), inputs[1],
    3363           0 :                               inputs[0]);
    3364             :     case wasm::kExprI16x8UConvertI8x16Low:
    3365             :       return graph()->NewNode(jsgraph()->machine()->I16x8UConvertI8x16Low(),
    3366           0 :                               inputs[0]);
    3367             :     case wasm::kExprI16x8UConvertI8x16High:
    3368             :       return graph()->NewNode(jsgraph()->machine()->I16x8UConvertI8x16High(),
    3369           0 :                               inputs[0]);
    3370             :     case wasm::kExprI16x8UConvertI32x4:
    3371             :       return graph()->NewNode(jsgraph()->machine()->I16x8UConvertI32x4(),
    3372           0 :                               inputs[0], inputs[1]);
    3373             :     case wasm::kExprI16x8AddSaturateU:
    3374             :       return graph()->NewNode(jsgraph()->machine()->I16x8AddSaturateU(),
    3375          21 :                               inputs[0], inputs[1]);
    3376             :     case wasm::kExprI16x8SubSaturateU:
    3377             :       return graph()->NewNode(jsgraph()->machine()->I16x8SubSaturateU(),
    3378          21 :                               inputs[0], inputs[1]);
    3379             :     case wasm::kExprI16x8MinU:
    3380             :       return graph()->NewNode(jsgraph()->machine()->I16x8MinU(), inputs[0],
    3381          21 :                               inputs[1]);
    3382             :     case wasm::kExprI16x8MaxU:
    3383             :       return graph()->NewNode(jsgraph()->machine()->I16x8MaxU(), inputs[0],
    3384          21 :                               inputs[1]);
    3385             :     case wasm::kExprI16x8LtU:
    3386             :       return graph()->NewNode(jsgraph()->machine()->I16x8LtU(), inputs[0],
    3387           0 :                               inputs[1]);
    3388             :     case wasm::kExprI16x8LeU:
    3389             :       return graph()->NewNode(jsgraph()->machine()->I16x8LeU(), inputs[0],
    3390           0 :                               inputs[1]);
    3391             :     case wasm::kExprI16x8GtU:
    3392             :       return graph()->NewNode(jsgraph()->machine()->I16x8LtU(), inputs[1],
    3393           0 :                               inputs[0]);
    3394             :     case wasm::kExprI16x8GeU:
    3395             :       return graph()->NewNode(jsgraph()->machine()->I16x8LeU(), inputs[1],
    3396           0 :                               inputs[0]);
    3397             :     case wasm::kExprI8x16Splat:
    3398         693 :       return graph()->NewNode(jsgraph()->machine()->I8x16Splat(), inputs[0]);
    3399             :     case wasm::kExprI8x16Neg:
    3400           0 :       return graph()->NewNode(jsgraph()->machine()->I8x16Neg(), inputs[0]);
    3401             :     case wasm::kExprI8x16SConvertI16x8:
    3402             :       return graph()->NewNode(jsgraph()->machine()->I8x16SConvertI16x8(),
    3403           0 :                               inputs[0], inputs[1]);
    3404             :     case wasm::kExprI8x16Add:
    3405             :       return graph()->NewNode(jsgraph()->machine()->I8x16Add(), inputs[0],
    3406          21 :                               inputs[1]);
    3407             :     case wasm::kExprI8x16AddSaturateS:
    3408             :       return graph()->NewNode(jsgraph()->machine()->I8x16AddSaturateS(),
    3409          21 :                               inputs[0], inputs[1]);
    3410             :     case wasm::kExprI8x16Sub:
    3411             :       return graph()->NewNode(jsgraph()->machine()->I8x16Sub(), inputs[0],
    3412          21 :                               inputs[1]);
    3413             :     case wasm::kExprI8x16SubSaturateS:
    3414             :       return graph()->NewNode(jsgraph()->machine()->I8x16SubSaturateS(),
    3415          21 :                               inputs[0], inputs[1]);
    3416             :     case wasm::kExprI8x16Mul:
    3417             :       return graph()->NewNode(jsgraph()->machine()->I8x16Mul(), inputs[0],
    3418           0 :                               inputs[1]);
    3419             :     case wasm::kExprI8x16MinS:
    3420             :       return graph()->NewNode(jsgraph()->machine()->I8x16MinS(), inputs[0],
    3421          21 :                               inputs[1]);
    3422             :     case wasm::kExprI8x16MaxS:
    3423             :       return graph()->NewNode(jsgraph()->machine()->I8x16MaxS(), inputs[0],
    3424          21 :                               inputs[1]);
    3425             :     case wasm::kExprI8x16Eq:
    3426             :       return graph()->NewNode(jsgraph()->machine()->I8x16Eq(), inputs[0],
    3427          21 :                               inputs[1]);
    3428             :     case wasm::kExprI8x16Ne:
    3429             :       return graph()->NewNode(jsgraph()->machine()->I8x16Ne(), inputs[0],
    3430          42 :                               inputs[1]);
    3431             :     case wasm::kExprI8x16LtS:
    3432             :       return graph()->NewNode(jsgraph()->machine()->I8x16LtS(), inputs[0],
    3433           0 :                               inputs[1]);
    3434             :     case wasm::kExprI8x16LeS:
    3435             :       return graph()->NewNode(jsgraph()->machine()->I8x16LeS(), inputs[0],
    3436           0 :                               inputs[1]);
    3437             :     case wasm::kExprI8x16GtS:
    3438             :       return graph()->NewNode(jsgraph()->machine()->I8x16LtS(), inputs[1],
    3439           0 :                               inputs[0]);
    3440             :     case wasm::kExprI8x16GeS:
    3441             :       return graph()->NewNode(jsgraph()->machine()->I8x16LeS(), inputs[1],
    3442           0 :                               inputs[0]);
    3443             :     case wasm::kExprI8x16UConvertI16x8:
    3444             :       return graph()->NewNode(jsgraph()->machine()->I8x16UConvertI16x8(),
    3445           0 :                               inputs[0], inputs[1]);
    3446             :     case wasm::kExprI8x16AddSaturateU:
    3447             :       return graph()->NewNode(jsgraph()->machine()->I8x16AddSaturateU(),
    3448          21 :                               inputs[0], inputs[1]);
    3449             :     case wasm::kExprI8x16SubSaturateU:
    3450             :       return graph()->NewNode(jsgraph()->machine()->I8x16SubSaturateU(),
    3451          21 :                               inputs[0], inputs[1]);
    3452             :     case wasm::kExprI8x16MinU:
    3453             :       return graph()->NewNode(jsgraph()->machine()->I8x16MinU(), inputs[0],
    3454          21 :                               inputs[1]);
    3455             :     case wasm::kExprI8x16MaxU:
    3456             :       return graph()->NewNode(jsgraph()->machine()->I8x16MaxU(), inputs[0],
    3457          21 :                               inputs[1]);
    3458             :     case wasm::kExprI8x16LtU:
    3459             :       return graph()->NewNode(jsgraph()->machine()->I8x16LtU(), inputs[0],
    3460           0 :                               inputs[1]);
    3461             :     case wasm::kExprI8x16LeU:
    3462             :       return graph()->NewNode(jsgraph()->machine()->I8x16LeU(), inputs[0],
    3463           0 :                               inputs[1]);
    3464             :     case wasm::kExprI8x16GtU:
    3465             :       return graph()->NewNode(jsgraph()->machine()->I8x16LtU(), inputs[1],
    3466           0 :                               inputs[0]);
    3467             :     case wasm::kExprI8x16GeU:
    3468             :       return graph()->NewNode(jsgraph()->machine()->I8x16LeU(), inputs[1],
    3469           0 :                               inputs[0]);
    3470             :     case wasm::kExprS128And:
    3471             :       return graph()->NewNode(jsgraph()->machine()->S128And(), inputs[0],
    3472           0 :                               inputs[1]);
    3473             :     case wasm::kExprS128Or:
    3474             :       return graph()->NewNode(jsgraph()->machine()->S128Or(), inputs[0],
    3475           0 :                               inputs[1]);
    3476             :     case wasm::kExprS128Xor:
    3477             :       return graph()->NewNode(jsgraph()->machine()->S128Xor(), inputs[0],
    3478           0 :                               inputs[1]);
    3479             :     case wasm::kExprS128Not:
    3480           0 :       return graph()->NewNode(jsgraph()->machine()->S128Not(), inputs[0]);
    3481             :     case wasm::kExprS32x4ZipLeft:
    3482             :       return graph()->NewNode(jsgraph()->machine()->S32x4ZipLeft(), inputs[0],
    3483           0 :                               inputs[1]);
    3484             :     case wasm::kExprS32x4ZipRight:
    3485             :       return graph()->NewNode(jsgraph()->machine()->S32x4ZipRight(), inputs[0],
    3486           0 :                               inputs[1]);
    3487             :     case wasm::kExprS32x4UnzipLeft:
    3488             :       return graph()->NewNode(jsgraph()->machine()->S32x4UnzipLeft(), inputs[0],
    3489           0 :                               inputs[1]);
    3490             :     case wasm::kExprS32x4UnzipRight:
    3491             :       return graph()->NewNode(jsgraph()->machine()->S32x4UnzipRight(),
    3492           0 :                               inputs[0], inputs[1]);
    3493             :     case wasm::kExprS32x4TransposeLeft:
    3494             :       return graph()->NewNode(jsgraph()->machine()->S32x4TransposeLeft(),
    3495           0 :                               inputs[0], inputs[1]);
    3496             :     case wasm::kExprS32x4TransposeRight:
    3497             :       return graph()->NewNode(jsgraph()->machine()->S32x4TransposeRight(),
    3498           0 :                               inputs[0], inputs[1]);
    3499             :     case wasm::kExprS32x4Select:
    3500             :       return graph()->NewNode(jsgraph()->machine()->S32x4Select(), inputs[0],
    3501          63 :                               inputs[1], inputs[2]);
    3502             :     case wasm::kExprS16x8ZipLeft:
    3503             :       return graph()->NewNode(jsgraph()->machine()->S16x8ZipLeft(), inputs[0],
    3504           0 :                               inputs[1]);
    3505             :     case wasm::kExprS16x8ZipRight:
    3506             :       return graph()->NewNode(jsgraph()->machine()->S16x8ZipRight(), inputs[0],
    3507           0 :                               inputs[1]);
    3508             :     case wasm::kExprS16x8UnzipLeft:
    3509             :       return graph()->NewNode(jsgraph()->machine()->S16x8UnzipLeft(), inputs[0],
    3510           0 :                               inputs[1]);
    3511             :     case wasm::kExprS16x8UnzipRight:
    3512             :       return graph()->NewNode(jsgraph()->machine()->S16x8UnzipRight(),
    3513           0 :                               inputs[0], inputs[1]);
    3514             :     case wasm::kExprS16x8TransposeLeft:
    3515             :       return graph()->NewNode(jsgraph()->machine()->S16x8TransposeLeft(),
    3516           0 :                               inputs[0], inputs[1]);
    3517             :     case wasm::kExprS16x8TransposeRight:
    3518             :       return graph()->NewNode(jsgraph()->machine()->S16x8TransposeRight(),
    3519           0 :                               inputs[0], inputs[1]);
    3520             :     case wasm::kExprS16x8Select:
    3521             :       return graph()->NewNode(jsgraph()->machine()->S16x8Select(), inputs[0],
    3522          63 :                               inputs[1], inputs[2]);
    3523             :     case wasm::kExprS8x16ZipLeft:
    3524             :       return graph()->NewNode(jsgraph()->machine()->S8x16ZipLeft(), inputs[0],
    3525           0 :                               inputs[1]);
    3526             :     case wasm::kExprS8x16ZipRight:
    3527             :       return graph()->NewNode(jsgraph()->machine()->S8x16ZipRight(), inputs[0],
    3528           0 :                               inputs[1]);
    3529             :     case wasm::kExprS8x16UnzipLeft:
    3530             :       return graph()->NewNode(jsgraph()->machine()->S8x16UnzipLeft(), inputs[0],
    3531           0 :                               inputs[1]);
    3532             :     case wasm::kExprS8x16UnzipRight:
    3533             :       return graph()->NewNode(jsgraph()->machine()->S8x16UnzipRight(),
    3534           0 :                               inputs[0], inputs[1]);
    3535             :     case wasm::kExprS8x16TransposeLeft:
    3536             :       return graph()->NewNode(jsgraph()->machine()->S8x16TransposeLeft(),
    3537           0 :                               inputs[0], inputs[1]);
    3538             :     case wasm::kExprS8x16TransposeRight:
    3539             :       return graph()->NewNode(jsgraph()->machine()->S8x16TransposeRight(),
    3540           0 :                               inputs[0], inputs[1]);
    3541             :     case wasm::kExprS8x16Select:
    3542             :       return graph()->NewNode(jsgraph()->machine()->S8x16Select(), inputs[0],
    3543          63 :                               inputs[1], inputs[2]);
    3544             :     case wasm::kExprS32x2Reverse:
    3545           0 :       return graph()->NewNode(jsgraph()->machine()->S32x2Reverse(), inputs[0]);
    3546             :     case wasm::kExprS16x4Reverse:
    3547           0 :       return graph()->NewNode(jsgraph()->machine()->S16x4Reverse(), inputs[0]);
    3548             :     case wasm::kExprS16x2Reverse:
    3549           0 :       return graph()->NewNode(jsgraph()->machine()->S16x2Reverse(), inputs[0]);
    3550             :     case wasm::kExprS8x8Reverse:
    3551           0 :       return graph()->NewNode(jsgraph()->machine()->S8x8Reverse(), inputs[0]);
    3552             :     case wasm::kExprS8x4Reverse:
    3553           0 :       return graph()->NewNode(jsgraph()->machine()->S8x4Reverse(), inputs[0]);
    3554             :     case wasm::kExprS8x2Reverse:
    3555           0 :       return graph()->NewNode(jsgraph()->machine()->S8x2Reverse(), inputs[0]);
    3556             :     case wasm::kExprS1x4And:
    3557             :       return graph()->NewNode(jsgraph()->machine()->S1x4And(), inputs[0],
    3558           0 :                               inputs[1]);
    3559             :     case wasm::kExprS1x4Or:
    3560             :       return graph()->NewNode(jsgraph()->machine()->S1x4Or(), inputs[0],
    3561           0 :                               inputs[1]);
    3562             :     case wasm::kExprS1x4Xor:
    3563             :       return graph()->NewNode(jsgraph()->machine()->S1x4Xor(), inputs[0],
    3564           0 :                               inputs[1]);
    3565             :     case wasm::kExprS1x4Not:
    3566           0 :       return graph()->NewNode(jsgraph()->machine()->S1x4Not(), inputs[0]);
    3567             :     case wasm::kExprS1x4AnyTrue:
    3568           0 :       return graph()->NewNode(jsgraph()->machine()->S1x4AnyTrue(), inputs[0]);
    3569             :     case wasm::kExprS1x4AllTrue:
    3570           0 :       return graph()->NewNode(jsgraph()->machine()->S1x4AllTrue(), inputs[0]);
    3571             :     case wasm::kExprS1x8And:
    3572             :       return graph()->NewNode(jsgraph()->machine()->S1x8And(), inputs[0],
    3573           0 :                               inputs[1]);
    3574             :     case wasm::kExprS1x8Or:
    3575             :       return graph()->NewNode(jsgraph()->machine()->S1x8Or(), inputs[0],
    3576           0 :                               inputs[1]);
    3577             :     case wasm::kExprS1x8Xor:
    3578             :       return graph()->NewNode(jsgraph()->machine()->S1x8Xor(), inputs[0],
    3579           0 :                               inputs[1]);
    3580             :     case wasm::kExprS1x8Not:
    3581           0 :       return graph()->NewNode(jsgraph()->machine()->S1x8Not(), inputs[0]);
    3582             :     case wasm::kExprS1x8AnyTrue:
    3583           0 :       return graph()->NewNode(jsgraph()->machine()->S1x8AnyTrue(), inputs[0]);
    3584             :     case wasm::kExprS1x8AllTrue:
    3585           0 :       return graph()->NewNode(jsgraph()->machine()->S1x8AllTrue(), inputs[0]);
    3586             :     case wasm::kExprS1x16And:
    3587             :       return graph()->NewNode(jsgraph()->machine()->S1x16And(), inputs[0],
    3588           0 :                               inputs[1]);
    3589             :     case wasm::kExprS1x16Or:
    3590             :       return graph()->NewNode(jsgraph()->machine()->S1x16Or(), inputs[0],
    3591           0 :                               inputs[1]);
    3592             :     case wasm::kExprS1x16Xor:
    3593             :       return graph()->NewNode(jsgraph()->machine()->S1x16Xor(), inputs[0],
    3594           0 :                               inputs[1]);
    3595             :     case wasm::kExprS1x16Not:
    3596           0 :       return graph()->NewNode(jsgraph()->machine()->S1x16Not(), inputs[0]);
    3597             :     case wasm::kExprS1x16AnyTrue:
    3598           0 :       return graph()->NewNode(jsgraph()->machine()->S1x16AnyTrue(), inputs[0]);
    3599             :     case wasm::kExprS1x16AllTrue:
    3600           0 :       return graph()->NewNode(jsgraph()->machine()->S1x16AllTrue(), inputs[0]);
    3601             :     default:
    3602           0 :       return graph()->NewNode(UnsupportedOpcode(opcode), nullptr);
    3603             :   }
    3604             : }
    3605             : 
    3606        5390 : Node* WasmGraphBuilder::SimdLaneOp(wasm::WasmOpcode opcode, uint8_t lane,
    3607        5390 :                                    const NodeVector& inputs) {
    3608        5390 :   has_simd_ = true;
    3609        5390 :   switch (opcode) {
    3610             :     case wasm::kExprF32x4ExtractLane:
    3611             :       return graph()->NewNode(jsgraph()->machine()->F32x4ExtractLane(lane),
    3612        5390 :                               inputs[0]);
    3613             :     case wasm::kExprF32x4ReplaceLane:
    3614             :       return graph()->NewNode(jsgraph()->machine()->F32x4ReplaceLane(lane),
    3615           0 :                               inputs[0], inputs[1]);
    3616             :     case wasm::kExprI32x4ExtractLane:
    3617             :       return graph()->NewNode(jsgraph()->machine()->I32x4ExtractLane(lane),
    3618        1512 :                               inputs[0]);
    3619             :     case wasm::kExprI32x4ReplaceLane:
    3620             :       return graph()->NewNode(jsgraph()->machine()->I32x4ReplaceLane(lane),
    3621         126 :                               inputs[0], inputs[1]);
    3622             :     case wasm::kExprI16x8ExtractLane:
    3623             :       return graph()->NewNode(jsgraph()->machine()->I16x8ExtractLane(lane),
    3624        4284 :                               inputs[0]);
    3625             :     case wasm::kExprI16x8ReplaceLane:
    3626             :       return graph()->NewNode(jsgraph()->machine()->I16x8ReplaceLane(lane),
    3627         210 :                               inputs[0], inputs[1]);
    3628             :     case wasm::kExprI8x16ExtractLane:
    3629             :       return graph()->NewNode(jsgraph()->machine()->I8x16ExtractLane(lane),
    3630        9660 :                               inputs[0]);
    3631             :     case wasm::kExprI8x16ReplaceLane:
    3632             :       return graph()->NewNode(jsgraph()->machine()->I8x16ReplaceLane(lane),
    3633         378 :                               inputs[0], inputs[1]);
    3634             :     default:
    3635           0 :       return graph()->NewNode(UnsupportedOpcode(opcode), nullptr);
    3636             :   }
    3637             : }
    3638             : 
    3639          42 : Node* WasmGraphBuilder::SimdShiftOp(wasm::WasmOpcode opcode, uint8_t shift,
    3640          42 :                                     const NodeVector& inputs) {
    3641          42 :   has_simd_ = true;
    3642          42 :   switch (opcode) {
    3643             :     case wasm::kExprI32x4Shl:
    3644          56 :       return graph()->NewNode(jsgraph()->machine()->I32x4Shl(shift), inputs[0]);
    3645             :     case wasm::kExprI32x4ShrS:
    3646             :       return graph()->NewNode(jsgraph()->machine()->I32x4ShrS(shift),
    3647          21 :                               inputs[0]);
    3648             :     case wasm::kExprI32x4ShrU:
    3649             :       return graph()->NewNode(jsgraph()->machine()->I32x4ShrU(shift),
    3650          21 :                               inputs[0]);
    3651             :     case wasm::kExprI16x8Shl:
    3652          21 :       return graph()->NewNode(jsgraph()->machine()->I16x8Shl(shift), inputs[0]);
    3653             :     case wasm::kExprI16x8ShrS:
    3654             :       return graph()->NewNode(jsgraph()->machine()->I16x8ShrS(shift),
    3655          21 :                               inputs[0]);
    3656             :     case wasm::kExprI16x8ShrU:
    3657             :       return graph()->NewNode(jsgraph()->machine()->I16x8ShrU(shift),
    3658          21 :                               inputs[0]);
    3659             :     case wasm::kExprI8x16Shl:
    3660           0 :       return graph()->NewNode(jsgraph()->machine()->I8x16Shl(shift), inputs[0]);
    3661             :     case wasm::kExprI8x16ShrS:
    3662             :       return graph()->NewNode(jsgraph()->machine()->I8x16ShrS(shift),
    3663           0 :                               inputs[0]);
    3664             :     case wasm::kExprI8x16ShrU:
    3665             :       return graph()->NewNode(jsgraph()->machine()->I8x16ShrU(shift),
    3666           0 :                               inputs[0]);
    3667             :     default:
    3668           0 :       return graph()->NewNode(UnsupportedOpcode(opcode), nullptr);
    3669             :   }
    3670             : }
    3671             : 
    3672           0 : Node* WasmGraphBuilder::SimdConcatOp(uint8_t bytes, const NodeVector& inputs) {
    3673           0 :   has_simd_ = true;
    3674             :   return graph()->NewNode(jsgraph()->machine()->S8x16Concat(bytes), inputs[0],
    3675           0 :                           inputs[1]);
    3676             : }
    3677             : 
    3678           0 : static void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
    3679             :                                       Isolate* isolate, Handle<Code> code,
    3680             :                                       const char* message, uint32_t index,
    3681           0 :                                       const wasm::WasmName& module_name,
    3682           0 :                                       const wasm::WasmName& func_name) {
    3683             :   DCHECK(isolate->logger()->is_logging_code_events() ||
    3684             :          isolate->is_profiling());
    3685             : 
    3686             :   ScopedVector<char> buffer(128);
    3687             :   SNPrintF(buffer, "%s#%d:%.*s:%.*s", message, index, module_name.length(),
    3688           0 :            module_name.start(), func_name.length(), func_name.start());
    3689             :   Handle<String> name_str =
    3690           0 :       isolate->factory()->NewStringFromAsciiChecked(buffer.start());
    3691             :   Handle<String> script_str =
    3692           0 :       isolate->factory()->NewStringFromAsciiChecked("(WASM)");
    3693             :   Handle<SharedFunctionInfo> shared =
    3694           0 :       isolate->factory()->NewSharedFunctionInfo(name_str, code, false);
    3695           0 :   PROFILE(isolate, CodeCreateEvent(tag, AbstractCode::cast(*code), *shared,
    3696             :                                    *script_str, 0, 0));
    3697           0 : }
    3698             : 
    3699      113556 : Handle<Code> CompileJSToWasmWrapper(Isolate* isolate,
    3700             :                                     const wasm::WasmModule* module,
    3701             :                                     Handle<Code> wasm_code, uint32_t index) {
    3702       28389 :   const wasm::WasmFunction* func = &module->functions[index];
    3703             : 
    3704             :   //----------------------------------------------------------------------------
    3705             :   // Create the Graph
    3706             :   //----------------------------------------------------------------------------
    3707       28389 :   Zone zone(isolate->allocator(), ZONE_NAME);
    3708       28389 :   Graph graph(&zone);
    3709       28389 :   CommonOperatorBuilder common(&zone);
    3710       28389 :   MachineOperatorBuilder machine(&zone);
    3711             :   JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
    3712             : 
    3713       28389 :   Node* control = nullptr;
    3714       28389 :   Node* effect = nullptr;
    3715             : 
    3716             :   wasm::ModuleEnv module_env(module, nullptr);
    3717       28389 :   WasmGraphBuilder builder(&module_env, &zone, &jsgraph, func->sig);
    3718             :   builder.set_control_ptr(&control);
    3719             :   builder.set_effect_ptr(&effect);
    3720       28389 :   builder.BuildJSToWasmWrapper(wasm_code, func->sig);
    3721             : 
    3722             :   //----------------------------------------------------------------------------
    3723             :   // Run the compilation pipeline.
    3724             :   //----------------------------------------------------------------------------
    3725       28389 :   if (FLAG_trace_turbo_graph) {  // Simple textual RPO.
    3726           0 :     OFStream os(stdout);
    3727           0 :     os << "-- Graph after change lowering -- " << std::endl;
    3728           0 :     os << AsRPO(graph);
    3729             :   }
    3730             : 
    3731             :   // Schedule and compile to machine code.
    3732             :   int params = static_cast<int>(
    3733       56778 :       module_env.GetFunctionSignature(index)->parameter_count());
    3734             :   CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
    3735       28389 :       &zone, false, params + 1, CallDescriptor::kNoFlags);
    3736             :   Code::Flags flags = Code::ComputeFlags(Code::JS_TO_WASM_FUNCTION);
    3737             :   bool debugging =
    3738             : #if DEBUG
    3739             :       true;
    3740             : #else
    3741       28389 :       FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph;
    3742             : #endif
    3743       28389 :   Vector<const char> func_name = ArrayVector("js-to-wasm");
    3744             : 
    3745             :   static unsigned id = 0;
    3746             :   Vector<char> buffer;
    3747       28389 :   if (debugging) {
    3748           0 :     buffer = Vector<char>::New(128);
    3749           0 :     int chars = SNPrintF(buffer, "js-to-wasm#%d", id);
    3750           0 :     func_name = Vector<const char>::cast(buffer.SubVector(0, chars));
    3751             :   }
    3752             : 
    3753       56778 :   CompilationInfo info(func_name, isolate, &zone, flags);
    3754       28389 :   Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph);
    3755             : #ifdef ENABLE_DISASSEMBLER
    3756             :   if (FLAG_print_opt_code && !code.is_null()) {
    3757             :     OFStream os(stdout);
    3758             :     code->Disassemble(buffer.start(), os);
    3759             :   }
    3760             : #endif
    3761       28389 :   if (debugging) {
    3762             :     buffer.Dispose();
    3763             :   }
    3764             : 
    3765       56778 :   if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
    3766             :     char func_name[32];
    3767           0 :     SNPrintF(ArrayVector(func_name), "js-to-wasm#%d", func->func_index);
    3768             :     RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate, code,
    3769             :                               "js-to-wasm", index, wasm::WasmName("export"),
    3770           0 :                               CStrVector(func_name));
    3771             :   }
    3772       56778 :   return code;
    3773             : }
    3774             : 
    3775      113649 : Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target,
    3776             :                                     wasm::FunctionSig* sig, uint32_t index,
    3777             :                                     Handle<String> module_name,
    3778             :                                     MaybeHandle<String> import_name,
    3779             :                                     wasm::ModuleOrigin origin) {
    3780             :   //----------------------------------------------------------------------------
    3781             :   // Create the Graph
    3782             :   //----------------------------------------------------------------------------
    3783       37883 :   Zone zone(isolate->allocator(), ZONE_NAME);
    3784       37883 :   Graph graph(&zone);
    3785       37883 :   CommonOperatorBuilder common(&zone);
    3786       37883 :   MachineOperatorBuilder machine(&zone);
    3787             :   JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
    3788             : 
    3789       37883 :   Node* control = nullptr;
    3790       37883 :   Node* effect = nullptr;
    3791             : 
    3792             :   SourcePositionTable* source_position_table =
    3793        2269 :       origin == wasm::kAsmJsOrigin ? new (&zone) SourcePositionTable(&graph)
    3794       37883 :                                    : nullptr;
    3795             : 
    3796             :   WasmGraphBuilder builder(nullptr, &zone, &jsgraph, sig,
    3797       37883 :                            source_position_table);
    3798             :   builder.set_control_ptr(&control);
    3799             :   builder.set_effect_ptr(&effect);
    3800       37883 :   builder.BuildWasmToJSWrapper(target, sig);
    3801             : 
    3802             :   Handle<Code> code = Handle<Code>::null();
    3803             :   {
    3804       37883 :     if (FLAG_trace_turbo_graph) {  // Simple textual RPO.
    3805           0 :       OFStream os(stdout);
    3806           0 :       os << "-- Graph after change lowering -- " << std::endl;
    3807           0 :       os << AsRPO(graph);
    3808             :     }
    3809             : 
    3810             :     // Schedule and compile to machine code.
    3811             :     CallDescriptor* incoming =
    3812       37883 :         wasm::ModuleEnv::GetWasmCallDescriptor(&zone, sig);
    3813       37883 :     if (machine.Is32()) {
    3814           0 :       incoming = wasm::ModuleEnv::GetI32WasmCallDescriptor(&zone, incoming);
    3815             :     }
    3816             :     Code::Flags flags = Code::ComputeFlags(Code::WASM_TO_JS_FUNCTION);
    3817             :     bool debugging =
    3818             : #if DEBUG
    3819             :         true;
    3820             : #else
    3821       37883 :         FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph;
    3822             : #endif
    3823       37883 :     Vector<const char> func_name = ArrayVector("wasm-to-js");
    3824             :     static unsigned id = 0;
    3825             :     Vector<char> buffer;
    3826       37883 :     if (debugging) {
    3827           0 :       buffer = Vector<char>::New(128);
    3828           0 :       int chars = SNPrintF(buffer, "wasm-to-js#%d", id);
    3829           0 :       func_name = Vector<const char>::cast(buffer.SubVector(0, chars));
    3830             :     }
    3831             : 
    3832       37883 :     CompilationInfo info(func_name, isolate, &zone, flags);
    3833             :     code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr,
    3834       37883 :                                             source_position_table);
    3835             : #ifdef ENABLE_DISASSEMBLER
    3836             :     if (FLAG_print_opt_code && !code.is_null()) {
    3837             :       OFStream os(stdout);
    3838             :       code->Disassemble(buffer.start(), os);
    3839             :     }
    3840             : #endif
    3841       37883 :     if (debugging) {
    3842             :       buffer.Dispose();
    3843       37883 :     }
    3844             :   }
    3845       75766 :   if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
    3846             :     const char* function_name = nullptr;
    3847             :     int function_name_size = 0;
    3848           0 :     if (!import_name.is_null()) {
    3849             :       Handle<String> handle = import_name.ToHandleChecked();
    3850           0 :       function_name = handle->ToCString().get();
    3851             :       function_name_size = handle->length();
    3852             :     }
    3853             :     RecordFunctionCompilation(
    3854             :         CodeEventListener::FUNCTION_TAG, isolate, code, "wasm-to-js", index,
    3855           0 :         {module_name->ToCString().get(), module_name->length()},
    3856           0 :         {function_name, function_name_size});
    3857             :   }
    3858             : 
    3859       37883 :   return code;
    3860             : }
    3861             : 
    3862        4107 : Handle<Code> CompileWasmInterpreterEntry(Isolate* isolate, uint32_t func_index,
    3863             :                                          wasm::FunctionSig* sig,
    3864             :                                          Handle<WasmInstanceObject> instance) {
    3865             :   //----------------------------------------------------------------------------
    3866             :   // Create the Graph
    3867             :   //----------------------------------------------------------------------------
    3868        1369 :   Zone zone(isolate->allocator(), ZONE_NAME);
    3869        1369 :   Graph graph(&zone);
    3870        1369 :   CommonOperatorBuilder common(&zone);
    3871        1369 :   MachineOperatorBuilder machine(&zone);
    3872             :   JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
    3873             : 
    3874        1369 :   Node* control = nullptr;
    3875        1369 :   Node* effect = nullptr;
    3876             : 
    3877        1369 :   WasmGraphBuilder builder(nullptr, &zone, &jsgraph, sig);
    3878             :   builder.set_control_ptr(&control);
    3879             :   builder.set_effect_ptr(&effect);
    3880        1369 :   builder.BuildWasmInterpreterEntry(func_index, sig, instance);
    3881             : 
    3882             :   Handle<Code> code = Handle<Code>::null();
    3883             :   {
    3884        1369 :     if (FLAG_trace_turbo_graph) {  // Simple textual RPO.
    3885           0 :       OFStream os(stdout);
    3886           0 :       os << "-- Wasm to interpreter graph -- " << std::endl;
    3887           0 :       os << AsRPO(graph);
    3888             :     }
    3889             : 
    3890             :     // Schedule and compile to machine code.
    3891             :     CallDescriptor* incoming =
    3892        1369 :         wasm::ModuleEnv::GetWasmCallDescriptor(&zone, sig);
    3893        1369 :     if (machine.Is32()) {
    3894           0 :       incoming = wasm::ModuleEnv::GetI32WasmCallDescriptor(&zone, incoming);
    3895             :     }
    3896             :     Code::Flags flags = Code::ComputeFlags(Code::WASM_INTERPRETER_ENTRY);
    3897             :     EmbeddedVector<char, 32> debug_name;
    3898        1369 :     int name_len = SNPrintF(debug_name, "wasm-to-interpreter#%d", func_index);
    3899             :     DCHECK(name_len > 0 && name_len < debug_name.length());
    3900             :     debug_name.Truncate(name_len);
    3901             :     DCHECK_EQ('\0', debug_name.start()[debug_name.length()]);
    3902             : 
    3903        1369 :     CompilationInfo info(debug_name, isolate, &zone, flags);
    3904        1369 :     code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr);
    3905             : #ifdef ENABLE_DISASSEMBLER
    3906             :     if (FLAG_print_opt_code && !code.is_null()) {
    3907             :       OFStream os(stdout);
    3908             :       code->Disassemble(debug_name.start(), os);
    3909             :     }
    3910             : #endif
    3911             : 
    3912        2738 :     if (isolate->logger()->is_logging_code_events() ||
    3913             :         isolate->is_profiling()) {
    3914             :       RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate, code,
    3915             :                                 "wasm-to-interpreter", func_index,
    3916           0 :                                 wasm::WasmName("module"), debug_name);
    3917        1369 :     }
    3918             :   }
    3919             : 
    3920        1369 :   Handle<FixedArray> deopt_data = isolate->factory()->NewFixedArray(1, TENURED);
    3921        1369 :   Handle<WeakCell> weak_instance = isolate->factory()->NewWeakCell(instance);
    3922        1369 :   deopt_data->set(0, *weak_instance);
    3923        1369 :   code->set_deoptimization_data(*deopt_data);
    3924             : 
    3925        1369 :   return code;
    3926             : }
    3927             : 
    3928       47468 : SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
    3929             :     double* decode_ms) {
    3930             :   base::ElapsedTimer decode_timer;
    3931       47468 :   if (FLAG_trace_wasm_decode_time) {
    3932             :     decode_timer.Start();
    3933             :   }
    3934             :   // Create a TF graph during decoding.
    3935             : 
    3936       47468 :   Graph* graph = jsgraph_->graph();
    3937             :   CommonOperatorBuilder* common = jsgraph_->common();
    3938             :   MachineOperatorBuilder* machine = jsgraph_->machine();
    3939             :   SourcePositionTable* source_position_table =
    3940       47482 :       new (jsgraph_->zone()) SourcePositionTable(graph);
    3941             :   WasmGraphBuilder builder(module_env_, jsgraph_->zone(), jsgraph_,
    3942       94920 :                            func_body_.sig, source_position_table);
    3943       94942 :   graph_construction_result_ =
    3944             :       wasm::BuildTFGraph(isolate_->allocator(), &builder, func_body_);
    3945             : 
    3946       47500 :   if (graph_construction_result_.failed()) {
    3947         342 :     if (FLAG_trace_wasm_compiler) {
    3948           0 :       OFStream os(stdout);
    3949           0 :       os << "Compilation failed: " << graph_construction_result_.error_msg
    3950           0 :          << std::endl;
    3951             :     }
    3952             :     return nullptr;
    3953             :   }
    3954             : 
    3955       47158 :   if (machine->Is32()) {
    3956             :     Int64Lowering(graph, machine, common, jsgraph_->zone(), func_body_.sig)
    3957           0 :         .LowerGraph();
    3958             :   }
    3959             : 
    3960       47158 :   if (builder.has_simd() && !CpuFeatures::SupportsWasmSimd128()) {
    3961           0 :     SimdScalarLowering(jsgraph_, func_body_.sig).LowerGraph();
    3962             :   }
    3963             : 
    3964       94316 :   if (func_index_ >= FLAG_trace_wasm_ast_start &&
    3965       47158 :       func_index_ < FLAG_trace_wasm_ast_end) {
    3966           0 :     PrintRawWasmCode(isolate_->allocator(), func_body_, module_env_->module);
    3967             :   }
    3968       47158 :   if (FLAG_trace_wasm_decode_time) {
    3969           0 :     *decode_ms = decode_timer.Elapsed().InMillisecondsF();
    3970             :   }
    3971       47158 :   return source_position_table;
    3972             : }
    3973             : 
    3974             : namespace {
    3975       47502 : Vector<const char> GetDebugName(Zone* zone, wasm::WasmName name, int index) {
    3976       47502 :   if (!name.is_empty()) {
    3977       39800 :     return name;
    3978             :   }
    3979             :   constexpr int kBufferLength = 15;
    3980             : 
    3981             :   EmbeddedVector<char, kBufferLength> name_vector;
    3982        7702 :   int name_len = SNPrintF(name_vector, "wasm#%d", index);
    3983             :   DCHECK(name_len > 0 && name_len < name_vector.length());
    3984             : 
    3985        7702 :   char* index_name = zone->NewArray<char>(name_len);
    3986        7702 :   memcpy(index_name, name_vector.start(), name_len);
    3987        7702 :   return Vector<const char>(index_name, name_len);
    3988             : }
    3989             : }  // namespace
    3990             : 
    3991       35006 : WasmCompilationUnit::WasmCompilationUnit(Isolate* isolate,
    3992             :                                          wasm::ModuleBytesEnv* module_env,
    3993       35006 :                                          const wasm::WasmFunction* function)
    3994             :     : WasmCompilationUnit(
    3995             :           isolate, &module_env->module_env,
    3996             :           wasm::FunctionBody{
    3997             :               function->sig, module_env->wire_bytes.start(),
    3998       35006 :               module_env->wire_bytes.start() + function->code_start_offset,
    3999       35006 :               module_env->wire_bytes.start() + function->code_end_offset},
    4000             :           module_env->wire_bytes.GetNameOrNull(function),
    4001      175030 :           function->func_index) {}
    4002             : 
    4003      142506 : WasmCompilationUnit::WasmCompilationUnit(Isolate* isolate,
    4004             :                                          wasm::ModuleEnv* module_env,
    4005             :                                          wasm::FunctionBody body,
    4006             :                                          wasm::WasmName name, int index)
    4007             :     : isolate_(isolate),
    4008             :       module_env_(module_env),
    4009             :       func_body_(body),
    4010             :       func_name_(name),
    4011       47502 :       graph_zone_(new Zone(isolate->allocator(), ZONE_NAME)),
    4012             :       jsgraph_(new (graph_zone()) JSGraph(
    4013       47502 :           isolate, new (graph_zone()) Graph(graph_zone()),
    4014       47502 :           new (graph_zone()) CommonOperatorBuilder(graph_zone()), nullptr,
    4015             :           nullptr,
    4016             :           new (graph_zone()) MachineOperatorBuilder(
    4017             :               graph_zone(), MachineType::PointerRepresentation(),
    4018             :               InstructionSelector::SupportedMachineOperatorFlags(),
    4019       47502 :               InstructionSelector::AlignmentRequirements()))),
    4020             :       compilation_zone_(isolate->allocator(), ZONE_NAME),
    4021             :       info_(GetDebugName(&compilation_zone_, name, index), isolate,
    4022             :             &compilation_zone_, Code::ComputeFlags(Code::WASM_FUNCTION)),
    4023             :       func_index_(index),
    4024      332514 :       protected_instructions_(&compilation_zone_) {}
    4025             : 
    4026       38968 : void WasmCompilationUnit::InitializeHandles() {
    4027             :   // Create and cache this node in the main thread, which contains a handle to
    4028             :   // the code object of the c-entry stub.
    4029       47502 :   jsgraph_->CEntryStubConstant(1);
    4030             :   DCHECK(!handles_initialized_);
    4031             : #if DEBUG
    4032             :   handles_initialized_ = true;
    4033             : #endif  // DEBUG
    4034       38968 : }
    4035             : 
    4036       47483 : void WasmCompilationUnit::ExecuteCompilation() {
    4037             :   DCHECK(handles_initialized_);
    4038             :   // TODO(ahaas): The counters are not thread-safe at the moment.
    4039             :   //    HistogramTimerScope wasm_compile_function_time_scope(
    4040             :   //        isolate_->counters()->wasm_compile_function_time());
    4041       47483 :   if (FLAG_trace_wasm_compiler) {
    4042           0 :     if (func_name_.start() != nullptr) {
    4043             :       PrintF("Compiling WASM function %d:'%.*s'\n\n", func_index(),
    4044           0 :              func_name_.length(), func_name_.start());
    4045             :     } else {
    4046           0 :       PrintF("Compiling WASM function %d:<unnamed>\n\n", func_index());
    4047             :     }
    4048             :   }
    4049             : 
    4050       47483 :   double decode_ms = 0;
    4051             :   size_t node_count = 0;
    4052             : 
    4053             :   std::unique_ptr<Zone> graph_zone(graph_zone_.release());
    4054       47483 :   SourcePositionTable* source_positions = BuildGraphForWasmFunction(&decode_ms);
    4055             : 
    4056       47499 :   if (graph_construction_result_.failed()) {
    4057         342 :     ok_ = false;
    4058       47502 :     return;
    4059             :   }
    4060             : 
    4061             :   base::ElapsedTimer pipeline_timer;
    4062       47157 :   if (FLAG_trace_wasm_decode_time) {
    4063       47154 :     node_count = jsgraph_->graph()->NodeCount();
    4064             :     pipeline_timer.Start();
    4065             :   }
    4066             : 
    4067             :   // Run the compiler pipeline to generate machine code.
    4068             :   CallDescriptor* descriptor = wasm::ModuleEnv::GetWasmCallDescriptor(
    4069       47157 :       &compilation_zone_, func_body_.sig);
    4070       94308 :   if (jsgraph_->machine()->Is32()) {
    4071             :     descriptor =
    4072           0 :         module_env_->GetI32WasmCallDescriptor(&compilation_zone_, descriptor);
    4073             :   }
    4074             :   job_.reset(Pipeline::NewWasmCompilationJob(
    4075             :       &info_, jsgraph_, descriptor, source_positions, &protected_instructions_,
    4076       47154 :       !module_env_->module->is_wasm()));
    4077       47121 :   ok_ = job_->ExecuteJob() == CompilationJob::SUCCEEDED;
    4078             :   // TODO(bradnelson): Improve histogram handling of size_t.
    4079             :   // TODO(ahaas): The counters are not thread-safe at the moment.
    4080             :   //    isolate_->counters()->wasm_compile_function_peak_memory_bytes()
    4081             :   // ->AddSample(
    4082             :   //        static_cast<int>(jsgraph->graph()->zone()->allocation_size()));
    4083             : 
    4084       47103 :   if (FLAG_trace_wasm_decode_time) {
    4085           0 :     double pipeline_ms = pipeline_timer.Elapsed().InMillisecondsF();
    4086             :     PrintF(
    4087             :         "wasm-compilation phase 1 ok: %u bytes, %0.3f ms decode, %zu nodes, "
    4088             :         "%0.3f ms pipeline\n",
    4089           0 :         static_cast<unsigned>(func_body_.end - func_body_.start), decode_ms,
    4090           0 :         node_count, pipeline_ms);
    4091             :   }
    4092             : }
    4093             : 
    4094       47502 : Handle<Code> WasmCompilationUnit::FinishCompilation(
    4095             :     wasm::ErrorThrower* thrower) {
    4096       47502 :   if (!ok_) {
    4097         342 :     if (graph_construction_result_.failed()) {
    4098             :       // Add the function as another context for the exception
    4099             :       ScopedVector<char> buffer(128);
    4100         342 :       if (func_name_.start() == nullptr) {
    4101             :         SNPrintF(buffer,
    4102             :                  "Compiling WASM function #%d:%.*s failed:", func_index_,
    4103          27 :                  func_name_.length(), func_name_.start());
    4104             :       } else {
    4105         315 :         SNPrintF(buffer, "Compiling WASM function #%d failed:", func_index_);
    4106             :       }
    4107             :       thrower->CompileFailed(buffer.start(), graph_construction_result_);
    4108             :     }
    4109             : 
    4110             :     return Handle<Code>::null();
    4111             :   }
    4112             :   base::ElapsedTimer codegen_timer;
    4113       47160 :   if (FLAG_trace_wasm_decode_time) {
    4114             :     codegen_timer.Start();
    4115             :   }
    4116       47160 :   if (job_->FinalizeJob() != CompilationJob::SUCCEEDED) {
    4117             :     return Handle<Code>::null();
    4118             :   }
    4119             :   Handle<Code> code = info_.code();
    4120             :   DCHECK(!code.is_null());
    4121             : 
    4122       94320 :   if (isolate_->logger()->is_logging_code_events() ||
    4123             :       isolate_->is_profiling()) {
    4124             :     RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate_, code,
    4125             :                               "WASM_function", func_index_,
    4126           0 :                               wasm::WasmName("module"), func_name_);
    4127             :   }
    4128             : 
    4129       47160 :   if (FLAG_trace_wasm_decode_time) {
    4130           0 :     double codegen_ms = codegen_timer.Elapsed().InMillisecondsF();
    4131             :     PrintF("wasm-code-generation ok: %u bytes, %0.3f ms code generation\n",
    4132           0 :            static_cast<unsigned>(func_body_.end - func_body_.start),
    4133           0 :            codegen_ms);
    4134             :   }
    4135             : 
    4136       47160 :   return code;
    4137             : }
    4138             : 
    4139             : // static
    4140        8534 : Handle<Code> WasmCompilationUnit::CompileWasmFunction(
    4141             :     wasm::ErrorThrower* thrower, Isolate* isolate,
    4142             :     wasm::ModuleBytesEnv* module_env, const wasm::WasmFunction* function) {
    4143        8534 :   WasmCompilationUnit unit(isolate, module_env, function);
    4144             :   unit.InitializeHandles();
    4145        8534 :   unit.ExecuteCompilation();
    4146        8534 :   return unit.FinishCompilation(thrower);
    4147             : }
    4148             : 
    4149             : }  // namespace compiler
    4150             : }  // namespace internal
    4151             : }  // namespace v8

Generated by: LCOV version 1.10