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