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