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