Home | History | Annotate | Download | only in wasm
      1 // Copyright 2016 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 <atomic>
      6 #include <type_traits>
      7 
      8 #include "src/wasm/wasm-interpreter.h"
      9 
     10 #include "src/assembler-inl.h"
     11 #include "src/boxed-float.h"
     12 #include "src/compiler/wasm-compiler.h"
     13 #include "src/conversions.h"
     14 #include "src/identity-map.h"
     15 #include "src/objects-inl.h"
     16 #include "src/trap-handler/trap-handler.h"
     17 #include "src/utils.h"
     18 #include "src/wasm/decoder.h"
     19 #include "src/wasm/function-body-decoder-impl.h"
     20 #include "src/wasm/function-body-decoder.h"
     21 #include "src/wasm/memory-tracing.h"
     22 #include "src/wasm/wasm-engine.h"
     23 #include "src/wasm/wasm-external-refs.h"
     24 #include "src/wasm/wasm-limits.h"
     25 #include "src/wasm/wasm-module.h"
     26 #include "src/wasm/wasm-objects-inl.h"
     27 
     28 #include "src/zone/accounting-allocator.h"
     29 #include "src/zone/zone-containers.h"
     30 
     31 namespace v8 {
     32 namespace internal {
     33 namespace wasm {
     34 
     35 #define TRACE(...)                                        \
     36   do {                                                    \
     37     if (FLAG_trace_wasm_interpreter) PrintF(__VA_ARGS__); \
     38   } while (false)
     39 
     40 #if V8_TARGET_BIG_ENDIAN
     41 #define LANE(i, type) ((sizeof(type.val) / sizeof(type.val[0])) - (i)-1)
     42 #else
     43 #define LANE(i, type) (i)
     44 #endif
     45 
     46 #define FOREACH_INTERNAL_OPCODE(V) V(Breakpoint, 0xFF)
     47 
     48 #define WASM_CTYPES(V) \
     49   V(I32, int32_t) V(I64, int64_t) V(F32, float) V(F64, double) V(S128, Simd128)
     50 
     51 #define FOREACH_SIMPLE_BINOP(V) \
     52   V(I32Add, uint32_t, +)        \
     53   V(I32Sub, uint32_t, -)        \
     54   V(I32Mul, uint32_t, *)        \
     55   V(I32And, uint32_t, &)        \
     56   V(I32Ior, uint32_t, |)        \
     57   V(I32Xor, uint32_t, ^)        \
     58   V(I32Eq, uint32_t, ==)        \
     59   V(I32Ne, uint32_t, !=)        \
     60   V(I32LtU, uint32_t, <)        \
     61   V(I32LeU, uint32_t, <=)       \
     62   V(I32GtU, uint32_t, >)        \
     63   V(I32GeU, uint32_t, >=)       \
     64   V(I32LtS, int32_t, <)         \
     65   V(I32LeS, int32_t, <=)        \
     66   V(I32GtS, int32_t, >)         \
     67   V(I32GeS, int32_t, >=)        \
     68   V(I64Add, uint64_t, +)        \
     69   V(I64Sub, uint64_t, -)        \
     70   V(I64Mul, uint64_t, *)        \
     71   V(I64And, uint64_t, &)        \
     72   V(I64Ior, uint64_t, |)        \
     73   V(I64Xor, uint64_t, ^)        \
     74   V(I64Eq, uint64_t, ==)        \
     75   V(I64Ne, uint64_t, !=)        \
     76   V(I64LtU, uint64_t, <)        \
     77   V(I64LeU, uint64_t, <=)       \
     78   V(I64GtU, uint64_t, >)        \
     79   V(I64GeU, uint64_t, >=)       \
     80   V(I64LtS, int64_t, <)         \
     81   V(I64LeS, int64_t, <=)        \
     82   V(I64GtS, int64_t, >)         \
     83   V(I64GeS, int64_t, >=)        \
     84   V(F32Add, float, +)           \
     85   V(F32Sub, float, -)           \
     86   V(F32Eq, float, ==)           \
     87   V(F32Ne, float, !=)           \
     88   V(F32Lt, float, <)            \
     89   V(F32Le, float, <=)           \
     90   V(F32Gt, float, >)            \
     91   V(F32Ge, float, >=)           \
     92   V(F64Add, double, +)          \
     93   V(F64Sub, double, -)          \
     94   V(F64Eq, double, ==)          \
     95   V(F64Ne, double, !=)          \
     96   V(F64Lt, double, <)           \
     97   V(F64Le, double, <=)          \
     98   V(F64Gt, double, >)           \
     99   V(F64Ge, double, >=)          \
    100   V(F32Mul, float, *)           \
    101   V(F64Mul, double, *)          \
    102   V(F32Div, float, /)           \
    103   V(F64Div, double, /)
    104 
    105 #define FOREACH_OTHER_BINOP(V) \
    106   V(I32DivS, int32_t)          \
    107   V(I32DivU, uint32_t)         \
    108   V(I32RemS, int32_t)          \
    109   V(I32RemU, uint32_t)         \
    110   V(I32Shl, uint32_t)          \
    111   V(I32ShrU, uint32_t)         \
    112   V(I32ShrS, int32_t)          \
    113   V(I64DivS, int64_t)          \
    114   V(I64DivU, uint64_t)         \
    115   V(I64RemS, int64_t)          \
    116   V(I64RemU, uint64_t)         \
    117   V(I64Shl, uint64_t)          \
    118   V(I64ShrU, uint64_t)         \
    119   V(I64ShrS, int64_t)          \
    120   V(I32Ror, int32_t)           \
    121   V(I32Rol, int32_t)           \
    122   V(I64Ror, int64_t)           \
    123   V(I64Rol, int64_t)           \
    124   V(F32Min, float)             \
    125   V(F32Max, float)             \
    126   V(F64Min, double)            \
    127   V(F64Max, double)            \
    128   V(I32AsmjsDivS, int32_t)     \
    129   V(I32AsmjsDivU, uint32_t)    \
    130   V(I32AsmjsRemS, int32_t)     \
    131   V(I32AsmjsRemU, uint32_t)    \
    132   V(F32CopySign, Float32)      \
    133   V(F64CopySign, Float64)
    134 
    135 #define FOREACH_I32CONV_FLOATOP(V)   \
    136   V(I32SConvertF32, int32_t, float)  \
    137   V(I32SConvertF64, int32_t, double) \
    138   V(I32UConvertF32, uint32_t, float) \
    139   V(I32UConvertF64, uint32_t, double)
    140 
    141 #define FOREACH_OTHER_UNOP(V)    \
    142   V(I32Clz, uint32_t)            \
    143   V(I32Ctz, uint32_t)            \
    144   V(I32Popcnt, uint32_t)         \
    145   V(I32Eqz, uint32_t)            \
    146   V(I64Clz, uint64_t)            \
    147   V(I64Ctz, uint64_t)            \
    148   V(I64Popcnt, uint64_t)         \
    149   V(I64Eqz, uint64_t)            \
    150   V(F32Abs, Float32)             \
    151   V(F32Neg, Float32)             \
    152   V(F32Ceil, float)              \
    153   V(F32Floor, float)             \
    154   V(F32Trunc, float)             \
    155   V(F32NearestInt, float)        \
    156   V(F64Abs, Float64)             \
    157   V(F64Neg, Float64)             \
    158   V(F64Ceil, double)             \
    159   V(F64Floor, double)            \
    160   V(F64Trunc, double)            \
    161   V(F64NearestInt, double)       \
    162   V(I32ConvertI64, int64_t)      \
    163   V(I64SConvertF32, float)       \
    164   V(I64SConvertF64, double)      \
    165   V(I64UConvertF32, float)       \
    166   V(I64UConvertF64, double)      \
    167   V(I64SConvertI32, int32_t)     \
    168   V(I64UConvertI32, uint32_t)    \
    169   V(F32SConvertI32, int32_t)     \
    170   V(F32UConvertI32, uint32_t)    \
    171   V(F32SConvertI64, int64_t)     \
    172   V(F32UConvertI64, uint64_t)    \
    173   V(F32ConvertF64, double)       \
    174   V(F32ReinterpretI32, int32_t)  \
    175   V(F64SConvertI32, int32_t)     \
    176   V(F64UConvertI32, uint32_t)    \
    177   V(F64SConvertI64, int64_t)     \
    178   V(F64UConvertI64, uint64_t)    \
    179   V(F64ConvertF32, float)        \
    180   V(F64ReinterpretI64, int64_t)  \
    181   V(I32AsmjsSConvertF32, float)  \
    182   V(I32AsmjsUConvertF32, float)  \
    183   V(I32AsmjsSConvertF64, double) \
    184   V(I32AsmjsUConvertF64, double) \
    185   V(F32Sqrt, float)              \
    186   V(F64Sqrt, double)
    187 
    188 namespace {
    189 
    190 constexpr uint32_t kFloat32SignBitMask = uint32_t{1} << 31;
    191 constexpr uint64_t kFloat64SignBitMask = uint64_t{1} << 63;
    192 
    193 inline int32_t ExecuteI32DivS(int32_t a, int32_t b, TrapReason* trap) {
    194   if (b == 0) {
    195     *trap = kTrapDivByZero;
    196     return 0;
    197   }
    198   if (b == -1 && a == std::numeric_limits<int32_t>::min()) {
    199     *trap = kTrapDivUnrepresentable;
    200     return 0;
    201   }
    202   return a / b;
    203 }
    204 
    205 inline uint32_t ExecuteI32DivU(uint32_t a, uint32_t b, TrapReason* trap) {
    206   if (b == 0) {
    207     *trap = kTrapDivByZero;
    208     return 0;
    209   }
    210   return a / b;
    211 }
    212 
    213 inline int32_t ExecuteI32RemS(int32_t a, int32_t b, TrapReason* trap) {
    214   if (b == 0) {
    215     *trap = kTrapRemByZero;
    216     return 0;
    217   }
    218   if (b == -1) return 0;
    219   return a % b;
    220 }
    221 
    222 inline uint32_t ExecuteI32RemU(uint32_t a, uint32_t b, TrapReason* trap) {
    223   if (b == 0) {
    224     *trap = kTrapRemByZero;
    225     return 0;
    226   }
    227   return a % b;
    228 }
    229 
    230 inline uint32_t ExecuteI32Shl(uint32_t a, uint32_t b, TrapReason* trap) {
    231   return a << (b & 0x1F);
    232 }
    233 
    234 inline uint32_t ExecuteI32ShrU(uint32_t a, uint32_t b, TrapReason* trap) {
    235   return a >> (b & 0x1F);
    236 }
    237 
    238 inline int32_t ExecuteI32ShrS(int32_t a, int32_t b, TrapReason* trap) {
    239   return a >> (b & 0x1F);
    240 }
    241 
    242 inline int64_t ExecuteI64DivS(int64_t a, int64_t b, TrapReason* trap) {
    243   if (b == 0) {
    244     *trap = kTrapDivByZero;
    245     return 0;
    246   }
    247   if (b == -1 && a == std::numeric_limits<int64_t>::min()) {
    248     *trap = kTrapDivUnrepresentable;
    249     return 0;
    250   }
    251   return a / b;
    252 }
    253 
    254 inline uint64_t ExecuteI64DivU(uint64_t a, uint64_t b, TrapReason* trap) {
    255   if (b == 0) {
    256     *trap = kTrapDivByZero;
    257     return 0;
    258   }
    259   return a / b;
    260 }
    261 
    262 inline int64_t ExecuteI64RemS(int64_t a, int64_t b, TrapReason* trap) {
    263   if (b == 0) {
    264     *trap = kTrapRemByZero;
    265     return 0;
    266   }
    267   if (b == -1) return 0;
    268   return a % b;
    269 }
    270 
    271 inline uint64_t ExecuteI64RemU(uint64_t a, uint64_t b, TrapReason* trap) {
    272   if (b == 0) {
    273     *trap = kTrapRemByZero;
    274     return 0;
    275   }
    276   return a % b;
    277 }
    278 
    279 inline uint64_t ExecuteI64Shl(uint64_t a, uint64_t b, TrapReason* trap) {
    280   return a << (b & 0x3F);
    281 }
    282 
    283 inline uint64_t ExecuteI64ShrU(uint64_t a, uint64_t b, TrapReason* trap) {
    284   return a >> (b & 0x3F);
    285 }
    286 
    287 inline int64_t ExecuteI64ShrS(int64_t a, int64_t b, TrapReason* trap) {
    288   return a >> (b & 0x3F);
    289 }
    290 
    291 inline uint32_t ExecuteI32Ror(uint32_t a, uint32_t b, TrapReason* trap) {
    292   uint32_t shift = (b & 0x1F);
    293   return (a >> shift) | (a << (32 - shift));
    294 }
    295 
    296 inline uint32_t ExecuteI32Rol(uint32_t a, uint32_t b, TrapReason* trap) {
    297   uint32_t shift = (b & 0x1F);
    298   return (a << shift) | (a >> (32 - shift));
    299 }
    300 
    301 inline uint64_t ExecuteI64Ror(uint64_t a, uint64_t b, TrapReason* trap) {
    302   uint32_t shift = (b & 0x3F);
    303   return (a >> shift) | (a << (64 - shift));
    304 }
    305 
    306 inline uint64_t ExecuteI64Rol(uint64_t a, uint64_t b, TrapReason* trap) {
    307   uint32_t shift = (b & 0x3F);
    308   return (a << shift) | (a >> (64 - shift));
    309 }
    310 
    311 inline float ExecuteF32Min(float a, float b, TrapReason* trap) {
    312   return JSMin(a, b);
    313 }
    314 
    315 inline float ExecuteF32Max(float a, float b, TrapReason* trap) {
    316   return JSMax(a, b);
    317 }
    318 
    319 inline Float32 ExecuteF32CopySign(Float32 a, Float32 b, TrapReason* trap) {
    320   return Float32::FromBits((a.get_bits() & ~kFloat32SignBitMask) |
    321                            (b.get_bits() & kFloat32SignBitMask));
    322 }
    323 
    324 inline double ExecuteF64Min(double a, double b, TrapReason* trap) {
    325   return JSMin(a, b);
    326 }
    327 
    328 inline double ExecuteF64Max(double a, double b, TrapReason* trap) {
    329   return JSMax(a, b);
    330 }
    331 
    332 inline Float64 ExecuteF64CopySign(Float64 a, Float64 b, TrapReason* trap) {
    333   return Float64::FromBits((a.get_bits() & ~kFloat64SignBitMask) |
    334                            (b.get_bits() & kFloat64SignBitMask));
    335 }
    336 
    337 inline int32_t ExecuteI32AsmjsDivS(int32_t a, int32_t b, TrapReason* trap) {
    338   if (b == 0) return 0;
    339   if (b == -1 && a == std::numeric_limits<int32_t>::min()) {
    340     return std::numeric_limits<int32_t>::min();
    341   }
    342   return a / b;
    343 }
    344 
    345 inline uint32_t ExecuteI32AsmjsDivU(uint32_t a, uint32_t b, TrapReason* trap) {
    346   if (b == 0) return 0;
    347   return a / b;
    348 }
    349 
    350 inline int32_t ExecuteI32AsmjsRemS(int32_t a, int32_t b, TrapReason* trap) {
    351   if (b == 0) return 0;
    352   if (b == -1) return 0;
    353   return a % b;
    354 }
    355 
    356 inline uint32_t ExecuteI32AsmjsRemU(uint32_t a, uint32_t b, TrapReason* trap) {
    357   if (b == 0) return 0;
    358   return a % b;
    359 }
    360 
    361 inline int32_t ExecuteI32AsmjsSConvertF32(float a, TrapReason* trap) {
    362   return DoubleToInt32(a);
    363 }
    364 
    365 inline uint32_t ExecuteI32AsmjsUConvertF32(float a, TrapReason* trap) {
    366   return DoubleToUint32(a);
    367 }
    368 
    369 inline int32_t ExecuteI32AsmjsSConvertF64(double a, TrapReason* trap) {
    370   return DoubleToInt32(a);
    371 }
    372 
    373 inline uint32_t ExecuteI32AsmjsUConvertF64(double a, TrapReason* trap) {
    374   return DoubleToUint32(a);
    375 }
    376 
    377 int32_t ExecuteI32Clz(uint32_t val, TrapReason* trap) {
    378   return base::bits::CountLeadingZeros(val);
    379 }
    380 
    381 uint32_t ExecuteI32Ctz(uint32_t val, TrapReason* trap) {
    382   return base::bits::CountTrailingZeros(val);
    383 }
    384 
    385 uint32_t ExecuteI32Popcnt(uint32_t val, TrapReason* trap) {
    386   return base::bits::CountPopulation(val);
    387 }
    388 
    389 inline uint32_t ExecuteI32Eqz(uint32_t val, TrapReason* trap) {
    390   return val == 0 ? 1 : 0;
    391 }
    392 
    393 int64_t ExecuteI64Clz(uint64_t val, TrapReason* trap) {
    394   return base::bits::CountLeadingZeros(val);
    395 }
    396 
    397 inline uint64_t ExecuteI64Ctz(uint64_t val, TrapReason* trap) {
    398   return base::bits::CountTrailingZeros(val);
    399 }
    400 
    401 inline int64_t ExecuteI64Popcnt(uint64_t val, TrapReason* trap) {
    402   return base::bits::CountPopulation(val);
    403 }
    404 
    405 inline int32_t ExecuteI64Eqz(uint64_t val, TrapReason* trap) {
    406   return val == 0 ? 1 : 0;
    407 }
    408 
    409 inline Float32 ExecuteF32Abs(Float32 a, TrapReason* trap) {
    410   return Float32::FromBits(a.get_bits() & ~kFloat32SignBitMask);
    411 }
    412 
    413 inline Float32 ExecuteF32Neg(Float32 a, TrapReason* trap) {
    414   return Float32::FromBits(a.get_bits() ^ kFloat32SignBitMask);
    415 }
    416 
    417 inline float ExecuteF32Ceil(float a, TrapReason* trap) { return ceilf(a); }
    418 
    419 inline float ExecuteF32Floor(float a, TrapReason* trap) { return floorf(a); }
    420 
    421 inline float ExecuteF32Trunc(float a, TrapReason* trap) { return truncf(a); }
    422 
    423 inline float ExecuteF32NearestInt(float a, TrapReason* trap) {
    424   return nearbyintf(a);
    425 }
    426 
    427 inline float ExecuteF32Sqrt(float a, TrapReason* trap) {
    428   float result = sqrtf(a);
    429   return result;
    430 }
    431 
    432 inline Float64 ExecuteF64Abs(Float64 a, TrapReason* trap) {
    433   return Float64::FromBits(a.get_bits() & ~kFloat64SignBitMask);
    434 }
    435 
    436 inline Float64 ExecuteF64Neg(Float64 a, TrapReason* trap) {
    437   return Float64::FromBits(a.get_bits() ^ kFloat64SignBitMask);
    438 }
    439 
    440 inline double ExecuteF64Ceil(double a, TrapReason* trap) { return ceil(a); }
    441 
    442 inline double ExecuteF64Floor(double a, TrapReason* trap) { return floor(a); }
    443 
    444 inline double ExecuteF64Trunc(double a, TrapReason* trap) { return trunc(a); }
    445 
    446 inline double ExecuteF64NearestInt(double a, TrapReason* trap) {
    447   return nearbyint(a);
    448 }
    449 
    450 inline double ExecuteF64Sqrt(double a, TrapReason* trap) { return sqrt(a); }
    451 
    452 template <typename int_type, typename float_type>
    453 int_type ExecuteConvert(float_type a, TrapReason* trap) {
    454   if (is_inbounds<int_type>(a)) {
    455     return static_cast<int_type>(a);
    456   }
    457   *trap = kTrapFloatUnrepresentable;
    458   return 0;
    459 }
    460 
    461 template <typename int_type, typename float_type>
    462 int_type ExecuteConvertSaturate(float_type a) {
    463   TrapReason base_trap = kTrapCount;
    464   int32_t val = ExecuteConvert<int_type>(a, &base_trap);
    465   if (base_trap == kTrapCount) {
    466     return val;
    467   }
    468   return std::isnan(a) ? 0
    469                        : (a < static_cast<float_type>(0.0)
    470                               ? std::numeric_limits<int_type>::min()
    471                               : std::numeric_limits<int_type>::max());
    472 }
    473 
    474 template <typename dst_type, typename src_type, void (*fn)(Address)>
    475 inline dst_type CallExternalIntToFloatFunction(src_type input) {
    476   uint8_t data[std::max(sizeof(dst_type), sizeof(src_type))];
    477   Address data_addr = reinterpret_cast<Address>(data);
    478   WriteUnalignedValue<src_type>(data_addr, input);
    479   fn(data_addr);
    480   return ReadUnalignedValue<dst_type>(data_addr);
    481 }
    482 
    483 template <typename dst_type, typename src_type, int32_t (*fn)(Address)>
    484 inline dst_type CallExternalFloatToIntFunction(src_type input,
    485                                                TrapReason* trap) {
    486   uint8_t data[std::max(sizeof(dst_type), sizeof(src_type))];
    487   Address data_addr = reinterpret_cast<Address>(data);
    488   WriteUnalignedValue<src_type>(data_addr, input);
    489   if (!fn(data_addr)) *trap = kTrapFloatUnrepresentable;
    490   return ReadUnalignedValue<dst_type>(data_addr);
    491 }
    492 
    493 inline uint32_t ExecuteI32ConvertI64(int64_t a, TrapReason* trap) {
    494   return static_cast<uint32_t>(a & 0xFFFFFFFF);
    495 }
    496 
    497 int64_t ExecuteI64SConvertF32(float a, TrapReason* trap) {
    498   return CallExternalFloatToIntFunction<int64_t, float,
    499                                         float32_to_int64_wrapper>(a, trap);
    500 }
    501 
    502 int64_t ExecuteI64SConvertSatF32(float a) {
    503   TrapReason base_trap = kTrapCount;
    504   int64_t val = ExecuteI64SConvertF32(a, &base_trap);
    505   if (base_trap == kTrapCount) {
    506     return val;
    507   }
    508   return std::isnan(a) ? 0
    509                        : (a < 0.0 ? std::numeric_limits<int64_t>::min()
    510                                   : std::numeric_limits<int64_t>::max());
    511 }
    512 
    513 int64_t ExecuteI64SConvertF64(double a, TrapReason* trap) {
    514   return CallExternalFloatToIntFunction<int64_t, double,
    515                                         float64_to_int64_wrapper>(a, trap);
    516 }
    517 
    518 int64_t ExecuteI64SConvertSatF64(double a) {
    519   TrapReason base_trap = kTrapCount;
    520   int64_t val = ExecuteI64SConvertF64(a, &base_trap);
    521   if (base_trap == kTrapCount) {
    522     return val;
    523   }
    524   return std::isnan(a) ? 0
    525                        : (a < 0.0 ? std::numeric_limits<int64_t>::min()
    526                                   : std::numeric_limits<int64_t>::max());
    527 }
    528 
    529 uint64_t ExecuteI64UConvertF32(float a, TrapReason* trap) {
    530   return CallExternalFloatToIntFunction<uint64_t, float,
    531                                         float32_to_uint64_wrapper>(a, trap);
    532 }
    533 
    534 uint64_t ExecuteI64UConvertSatF32(float a) {
    535   TrapReason base_trap = kTrapCount;
    536   uint64_t val = ExecuteI64UConvertF32(a, &base_trap);
    537   if (base_trap == kTrapCount) {
    538     return val;
    539   }
    540   return std::isnan(a) ? 0
    541                        : (a < 0.0 ? std::numeric_limits<uint64_t>::min()
    542                                   : std::numeric_limits<uint64_t>::max());
    543 }
    544 
    545 uint64_t ExecuteI64UConvertF64(double a, TrapReason* trap) {
    546   return CallExternalFloatToIntFunction<uint64_t, double,
    547                                         float64_to_uint64_wrapper>(a, trap);
    548 }
    549 
    550 uint64_t ExecuteI64UConvertSatF64(double a) {
    551   TrapReason base_trap = kTrapCount;
    552   int64_t val = ExecuteI64UConvertF64(a, &base_trap);
    553   if (base_trap == kTrapCount) {
    554     return val;
    555   }
    556   return std::isnan(a) ? 0
    557                        : (a < 0.0 ? std::numeric_limits<uint64_t>::min()
    558                                   : std::numeric_limits<uint64_t>::max());
    559 }
    560 
    561 inline int64_t ExecuteI64SConvertI32(int32_t a, TrapReason* trap) {
    562   return static_cast<int64_t>(a);
    563 }
    564 
    565 inline int64_t ExecuteI64UConvertI32(uint32_t a, TrapReason* trap) {
    566   return static_cast<uint64_t>(a);
    567 }
    568 
    569 inline float ExecuteF32SConvertI32(int32_t a, TrapReason* trap) {
    570   return static_cast<float>(a);
    571 }
    572 
    573 inline float ExecuteF32UConvertI32(uint32_t a, TrapReason* trap) {
    574   return static_cast<float>(a);
    575 }
    576 
    577 inline float ExecuteF32SConvertI64(int64_t a, TrapReason* trap) {
    578   return static_cast<float>(a);
    579 }
    580 
    581 inline float ExecuteF32UConvertI64(uint64_t a, TrapReason* trap) {
    582   return CallExternalIntToFloatFunction<float, uint64_t,
    583                                         uint64_to_float32_wrapper>(a);
    584 }
    585 
    586 inline float ExecuteF32ConvertF64(double a, TrapReason* trap) {
    587   return static_cast<float>(a);
    588 }
    589 
    590 inline Float32 ExecuteF32ReinterpretI32(int32_t a, TrapReason* trap) {
    591   return Float32::FromBits(a);
    592 }
    593 
    594 inline double ExecuteF64SConvertI32(int32_t a, TrapReason* trap) {
    595   return static_cast<double>(a);
    596 }
    597 
    598 inline double ExecuteF64UConvertI32(uint32_t a, TrapReason* trap) {
    599   return static_cast<double>(a);
    600 }
    601 
    602 inline double ExecuteF64SConvertI64(int64_t a, TrapReason* trap) {
    603   return static_cast<double>(a);
    604 }
    605 
    606 inline double ExecuteF64UConvertI64(uint64_t a, TrapReason* trap) {
    607   return CallExternalIntToFloatFunction<double, uint64_t,
    608                                         uint64_to_float64_wrapper>(a);
    609 }
    610 
    611 inline double ExecuteF64ConvertF32(float a, TrapReason* trap) {
    612   return static_cast<double>(a);
    613 }
    614 
    615 inline Float64 ExecuteF64ReinterpretI64(int64_t a, TrapReason* trap) {
    616   return Float64::FromBits(a);
    617 }
    618 
    619 inline int32_t ExecuteI32ReinterpretF32(WasmValue a) {
    620   return a.to_f32_boxed().get_bits();
    621 }
    622 
    623 inline int64_t ExecuteI64ReinterpretF64(WasmValue a) {
    624   return a.to_f64_boxed().get_bits();
    625 }
    626 
    627 enum InternalOpcode {
    628 #define DECL_INTERNAL_ENUM(name, value) kInternal##name = value,
    629   FOREACH_INTERNAL_OPCODE(DECL_INTERNAL_ENUM)
    630 #undef DECL_INTERNAL_ENUM
    631 };
    632 
    633 const char* OpcodeName(uint32_t val) {
    634   switch (val) {
    635 #define DECL_INTERNAL_CASE(name, value) \
    636   case kInternal##name:                 \
    637     return "Internal" #name;
    638     FOREACH_INTERNAL_OPCODE(DECL_INTERNAL_CASE)
    639 #undef DECL_INTERNAL_CASE
    640   }
    641   return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(val));
    642 }
    643 
    644 class SideTable;
    645 
    646 // Code and metadata needed to execute a function.
    647 struct InterpreterCode {
    648   const WasmFunction* function;  // wasm function
    649   BodyLocalDecls locals;         // local declarations
    650   const byte* orig_start;        // start of original code
    651   const byte* orig_end;          // end of original code
    652   byte* start;                   // start of (maybe altered) code
    653   byte* end;                     // end of (maybe altered) code
    654   SideTable* side_table;         // precomputed side table for control flow.
    655 
    656   const byte* at(pc_t pc) { return start + pc; }
    657 };
    658 
    659 // A helper class to compute the control transfers for each bytecode offset.
    660 // Control transfers allow Br, BrIf, BrTable, If, Else, and End bytecodes to
    661 // be directly executed without the need to dynamically track blocks.
    662 class SideTable : public ZoneObject {
    663  public:
    664   ControlTransferMap map_;
    665   uint32_t max_stack_height_ = 0;
    666 
    667   SideTable(Zone* zone, const WasmModule* module, InterpreterCode* code)
    668       : map_(zone) {
    669     // Create a zone for all temporary objects.
    670     Zone control_transfer_zone(zone->allocator(), ZONE_NAME);
    671 
    672     // Represents a control flow label.
    673     class CLabel : public ZoneObject {
    674       explicit CLabel(Zone* zone, uint32_t target_stack_height, uint32_t arity)
    675           : target_stack_height(target_stack_height),
    676             arity(arity),
    677             refs(zone) {}
    678 
    679      public:
    680       struct Ref {
    681         const byte* from_pc;
    682         const uint32_t stack_height;
    683       };
    684       const byte* target = nullptr;
    685       uint32_t target_stack_height;
    686       // Arity when branching to this label.
    687       const uint32_t arity;
    688       ZoneVector<Ref> refs;
    689 
    690       static CLabel* New(Zone* zone, uint32_t stack_height, uint32_t arity) {
    691         return new (zone) CLabel(zone, stack_height, arity);
    692       }
    693 
    694       // Bind this label to the given PC.
    695       void Bind(const byte* pc) {
    696         DCHECK_NULL(target);
    697         target = pc;
    698       }
    699 
    700       // Reference this label from the given location.
    701       void Ref(const byte* from_pc, uint32_t stack_height) {
    702         // Target being bound before a reference means this is a loop.
    703         DCHECK_IMPLIES(target, *target == kExprLoop);
    704         refs.push_back({from_pc, stack_height});
    705       }
    706 
    707       void Finish(ControlTransferMap* map, const byte* start) {
    708         DCHECK_NOT_NULL(target);
    709         for (auto ref : refs) {
    710           size_t offset = static_cast<size_t>(ref.from_pc - start);
    711           auto pcdiff = static_cast<pcdiff_t>(target - ref.from_pc);
    712           DCHECK_GE(ref.stack_height, target_stack_height);
    713           spdiff_t spdiff =
    714               static_cast<spdiff_t>(ref.stack_height - target_stack_height);
    715           TRACE("control transfer @%zu: pc %d, stack %u->%u = -%u\n", offset,
    716                 pcdiff, ref.stack_height, target_stack_height, spdiff);
    717           ControlTransferEntry& entry = (*map)[offset];
    718           entry.pc_diff = pcdiff;
    719           entry.sp_diff = spdiff;
    720           entry.target_arity = arity;
    721         }
    722       }
    723     };
    724 
    725     // An entry in the control stack.
    726     struct Control {
    727       const byte* pc;
    728       CLabel* end_label;
    729       CLabel* else_label;
    730       // Arity (number of values on the stack) when exiting this control
    731       // structure via |end|.
    732       uint32_t exit_arity;
    733       // Track whether this block was already left, i.e. all further
    734       // instructions are unreachable.
    735       bool unreachable = false;
    736 
    737       Control(const byte* pc, CLabel* end_label, CLabel* else_label,
    738               uint32_t exit_arity)
    739           : pc(pc),
    740             end_label(end_label),
    741             else_label(else_label),
    742             exit_arity(exit_arity) {}
    743       Control(const byte* pc, CLabel* end_label, uint32_t exit_arity)
    744           : Control(pc, end_label, nullptr, exit_arity) {}
    745 
    746       void Finish(ControlTransferMap* map, const byte* start) {
    747         end_label->Finish(map, start);
    748         if (else_label) else_label->Finish(map, start);
    749       }
    750     };
    751 
    752     // Compute the ControlTransfer map.
    753     // This algorithm maintains a stack of control constructs similar to the
    754     // AST decoder. The {control_stack} allows matching {br,br_if,br_table}
    755     // bytecodes with their target, as well as determining whether the current
    756     // bytecodes are within the true or false block of an else.
    757     ZoneVector<Control> control_stack(&control_transfer_zone);
    758     uint32_t stack_height = 0;
    759     uint32_t func_arity =
    760         static_cast<uint32_t>(code->function->sig->return_count());
    761     CLabel* func_label =
    762         CLabel::New(&control_transfer_zone, stack_height, func_arity);
    763     control_stack.emplace_back(code->orig_start, func_label, func_arity);
    764     auto control_parent = [&]() -> Control& {
    765       DCHECK_LE(2, control_stack.size());
    766       return control_stack[control_stack.size() - 2];
    767     };
    768     auto copy_unreachable = [&] {
    769       control_stack.back().unreachable = control_parent().unreachable;
    770     };
    771     for (BytecodeIterator i(code->orig_start, code->orig_end, &code->locals);
    772          i.has_next(); i.next()) {
    773       WasmOpcode opcode = i.current();
    774       if (WasmOpcodes::IsPrefixOpcode(opcode)) opcode = i.prefixed_opcode();
    775       bool unreachable = control_stack.back().unreachable;
    776       if (unreachable) {
    777         TRACE("@%u: %s (is unreachable)\n", i.pc_offset(),
    778               WasmOpcodes::OpcodeName(opcode));
    779       } else {
    780         auto stack_effect =
    781             StackEffect(module, code->function->sig, i.pc(), i.end());
    782         TRACE("@%u: %s (sp %d - %d + %d)\n", i.pc_offset(),
    783               WasmOpcodes::OpcodeName(opcode), stack_height, stack_effect.first,
    784               stack_effect.second);
    785         DCHECK_GE(stack_height, stack_effect.first);
    786         DCHECK_GE(kMaxUInt32, static_cast<uint64_t>(stack_height) -
    787                                   stack_effect.first + stack_effect.second);
    788         stack_height = stack_height - stack_effect.first + stack_effect.second;
    789         if (stack_height > max_stack_height_) max_stack_height_ = stack_height;
    790       }
    791       switch (opcode) {
    792         case kExprBlock:
    793         case kExprLoop: {
    794           bool is_loop = opcode == kExprLoop;
    795           BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures, &i,
    796                                                        i.pc());
    797           if (imm.type == kWasmVar) {
    798             imm.sig = module->signatures[imm.sig_index];
    799           }
    800           TRACE("control @%u: %s, arity %d->%d\n", i.pc_offset(),
    801                 is_loop ? "Loop" : "Block", imm.in_arity(), imm.out_arity());
    802           CLabel* label =
    803               CLabel::New(&control_transfer_zone, stack_height,
    804                           is_loop ? imm.in_arity() : imm.out_arity());
    805           control_stack.emplace_back(i.pc(), label, imm.out_arity());
    806           copy_unreachable();
    807           if (is_loop) label->Bind(i.pc());
    808           break;
    809         }
    810         case kExprIf: {
    811           BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures, &i,
    812                                                        i.pc());
    813           if (imm.type == kWasmVar) {
    814             imm.sig = module->signatures[imm.sig_index];
    815           }
    816           TRACE("control @%u: If, arity %d->%d\n", i.pc_offset(),
    817                 imm.in_arity(), imm.out_arity());
    818           CLabel* end_label = CLabel::New(&control_transfer_zone, stack_height,
    819                                           imm.out_arity());
    820           CLabel* else_label =
    821               CLabel::New(&control_transfer_zone, stack_height, 0);
    822           control_stack.emplace_back(i.pc(), end_label, else_label,
    823                                      imm.out_arity());
    824           copy_unreachable();
    825           if (!unreachable) else_label->Ref(i.pc(), stack_height);
    826           break;
    827         }
    828         case kExprElse: {
    829           Control* c = &control_stack.back();
    830           copy_unreachable();
    831           TRACE("control @%u: Else\n", i.pc_offset());
    832           if (!control_parent().unreachable) {
    833             c->end_label->Ref(i.pc(), stack_height);
    834           }
    835           DCHECK_NOT_NULL(c->else_label);
    836           c->else_label->Bind(i.pc() + 1);
    837           c->else_label->Finish(&map_, code->orig_start);
    838           c->else_label = nullptr;
    839           DCHECK_GE(stack_height, c->end_label->target_stack_height);
    840           stack_height = c->end_label->target_stack_height;
    841           break;
    842         }
    843         case kExprEnd: {
    844           Control* c = &control_stack.back();
    845           TRACE("control @%u: End\n", i.pc_offset());
    846           // Only loops have bound labels.
    847           DCHECK_IMPLIES(c->end_label->target, *c->pc == kExprLoop);
    848           if (!c->end_label->target) {
    849             if (c->else_label) c->else_label->Bind(i.pc());
    850             c->end_label->Bind(i.pc() + 1);
    851           }
    852           c->Finish(&map_, code->orig_start);
    853           DCHECK_GE(stack_height, c->end_label->target_stack_height);
    854           stack_height = c->end_label->target_stack_height + c->exit_arity;
    855           control_stack.pop_back();
    856           break;
    857         }
    858         case kExprBr: {
    859           BreakDepthImmediate<Decoder::kNoValidate> imm(&i, i.pc());
    860           TRACE("control @%u: Br[depth=%u]\n", i.pc_offset(), imm.depth);
    861           Control* c = &control_stack[control_stack.size() - imm.depth - 1];
    862           if (!unreachable) c->end_label->Ref(i.pc(), stack_height);
    863           break;
    864         }
    865         case kExprBrIf: {
    866           BreakDepthImmediate<Decoder::kNoValidate> imm(&i, i.pc());
    867           TRACE("control @%u: BrIf[depth=%u]\n", i.pc_offset(), imm.depth);
    868           Control* c = &control_stack[control_stack.size() - imm.depth - 1];
    869           if (!unreachable) c->end_label->Ref(i.pc(), stack_height);
    870           break;
    871         }
    872         case kExprBrTable: {
    873           BranchTableImmediate<Decoder::kNoValidate> imm(&i, i.pc());
    874           BranchTableIterator<Decoder::kNoValidate> iterator(&i, imm);
    875           TRACE("control @%u: BrTable[count=%u]\n", i.pc_offset(),
    876                 imm.table_count);
    877           if (!unreachable) {
    878             while (iterator.has_next()) {
    879               uint32_t j = iterator.cur_index();
    880               uint32_t target = iterator.next();
    881               Control* c = &control_stack[control_stack.size() - target - 1];
    882               c->end_label->Ref(i.pc() + j, stack_height);
    883             }
    884           }
    885           break;
    886         }
    887         default:
    888           break;
    889       }
    890       if (WasmOpcodes::IsUnconditionalJump(opcode)) {
    891         control_stack.back().unreachable = true;
    892       }
    893     }
    894     DCHECK_EQ(0, control_stack.size());
    895     DCHECK_EQ(func_arity, stack_height);
    896   }
    897 
    898   ControlTransferEntry& Lookup(pc_t from) {
    899     auto result = map_.find(from);
    900     DCHECK(result != map_.end());
    901     return result->second;
    902   }
    903 };
    904 
    905 struct ExternalCallResult {
    906   enum Type {
    907     // The function should be executed inside this interpreter.
    908     INTERNAL,
    909     // For indirect calls: Table or function does not exist.
    910     INVALID_FUNC,
    911     // For indirect calls: Signature does not match expected signature.
    912     SIGNATURE_MISMATCH,
    913     // The function was executed and returned normally.
    914     EXTERNAL_RETURNED,
    915     // The function was executed, threw an exception, and the stack was unwound.
    916     EXTERNAL_UNWOUND
    917   };
    918   Type type;
    919   // If type is INTERNAL, this field holds the function to call internally.
    920   InterpreterCode* interpreter_code;
    921 
    922   ExternalCallResult(Type type) : type(type) {  // NOLINT
    923     DCHECK_NE(INTERNAL, type);
    924   }
    925   ExternalCallResult(Type type, InterpreterCode* code)
    926       : type(type), interpreter_code(code) {
    927     DCHECK_EQ(INTERNAL, type);
    928   }
    929 };
    930 
    931 // The main storage for interpreter code. It maps {WasmFunction} to the
    932 // metadata needed to execute each function.
    933 class CodeMap {
    934   Zone* zone_;
    935   const WasmModule* module_;
    936   ZoneVector<InterpreterCode> interpreter_code_;
    937   // TODO(wasm): Remove this testing wart. It is needed because interpreter
    938   // entry stubs are not generated in testing the interpreter in cctests.
    939   bool call_indirect_through_module_ = false;
    940 
    941  public:
    942   CodeMap(const WasmModule* module, const uint8_t* module_start, Zone* zone)
    943       : zone_(zone), module_(module), interpreter_code_(zone) {
    944     if (module == nullptr) return;
    945     interpreter_code_.reserve(module->functions.size());
    946     for (const WasmFunction& function : module->functions) {
    947       if (function.imported) {
    948         DCHECK(!function.code.is_set());
    949         AddFunction(&function, nullptr, nullptr);
    950       } else {
    951         AddFunction(&function, module_start + function.code.offset(),
    952                     module_start + function.code.end_offset());
    953       }
    954     }
    955   }
    956 
    957   bool call_indirect_through_module() { return call_indirect_through_module_; }
    958 
    959   void set_call_indirect_through_module(bool val) {
    960     call_indirect_through_module_ = val;
    961   }
    962 
    963   const WasmModule* module() const { return module_; }
    964 
    965   InterpreterCode* GetCode(const WasmFunction* function) {
    966     InterpreterCode* code = GetCode(function->func_index);
    967     DCHECK_EQ(function, code->function);
    968     return code;
    969   }
    970 
    971   InterpreterCode* GetCode(uint32_t function_index) {
    972     DCHECK_LT(function_index, interpreter_code_.size());
    973     return Preprocess(&interpreter_code_[function_index]);
    974   }
    975 
    976   InterpreterCode* GetIndirectCode(uint32_t table_index, uint32_t entry_index) {
    977     uint32_t saved_index;
    978     USE(saved_index);
    979     if (table_index >= module_->tables.size()) return nullptr;
    980     // Mask table index for SSCA mitigation.
    981     saved_index = table_index;
    982     table_index &= static_cast<int32_t>((table_index - module_->tables.size()) &
    983                                         ~static_cast<int32_t>(table_index)) >>
    984                    31;
    985     DCHECK_EQ(table_index, saved_index);
    986     const WasmTable* table = &module_->tables[table_index];
    987     if (entry_index >= table->values.size()) return nullptr;
    988     // Mask entry_index for SSCA mitigation.
    989     saved_index = entry_index;
    990     entry_index &= static_cast<int32_t>((entry_index - table->values.size()) &
    991                                         ~static_cast<int32_t>(entry_index)) >>
    992                    31;
    993     DCHECK_EQ(entry_index, saved_index);
    994     uint32_t index = table->values[entry_index];
    995     if (index >= interpreter_code_.size()) return nullptr;
    996     // Mask index for SSCA mitigation.
    997     saved_index = index;
    998     index &= static_cast<int32_t>((index - interpreter_code_.size()) &
    999                                   ~static_cast<int32_t>(index)) >>
   1000              31;
   1001     DCHECK_EQ(index, saved_index);
   1002 
   1003     return GetCode(index);
   1004   }
   1005 
   1006   InterpreterCode* Preprocess(InterpreterCode* code) {
   1007     DCHECK_EQ(code->function->imported, code->start == nullptr);
   1008     if (!code->side_table && code->start) {
   1009       // Compute the control targets map and the local declarations.
   1010       code->side_table = new (zone_) SideTable(zone_, module_, code);
   1011     }
   1012     return code;
   1013   }
   1014 
   1015   void AddFunction(const WasmFunction* function, const byte* code_start,
   1016                    const byte* code_end) {
   1017     InterpreterCode code = {
   1018         function, BodyLocalDecls(zone_),         code_start,
   1019         code_end, const_cast<byte*>(code_start), const_cast<byte*>(code_end),
   1020         nullptr};
   1021 
   1022     DCHECK_EQ(interpreter_code_.size(), function->func_index);
   1023     interpreter_code_.push_back(code);
   1024   }
   1025 
   1026   void SetFunctionCode(const WasmFunction* function, const byte* start,
   1027                        const byte* end) {
   1028     DCHECK_LT(function->func_index, interpreter_code_.size());
   1029     InterpreterCode* code = &interpreter_code_[function->func_index];
   1030     DCHECK_EQ(function, code->function);
   1031     code->orig_start = start;
   1032     code->orig_end = end;
   1033     code->start = const_cast<byte*>(start);
   1034     code->end = const_cast<byte*>(end);
   1035     code->side_table = nullptr;
   1036     Preprocess(code);
   1037   }
   1038 };
   1039 
   1040 // Like a static_cast from src to dst, but specialized for boxed floats.
   1041 template <typename dst, typename src>
   1042 struct converter {
   1043   dst operator()(src val) const { return static_cast<dst>(val); }
   1044 };
   1045 template <>
   1046 struct converter<Float64, uint64_t> {
   1047   Float64 operator()(uint64_t val) const { return Float64::FromBits(val); }
   1048 };
   1049 template <>
   1050 struct converter<Float32, uint32_t> {
   1051   Float32 operator()(uint32_t val) const { return Float32::FromBits(val); }
   1052 };
   1053 template <>
   1054 struct converter<uint64_t, Float64> {
   1055   uint64_t operator()(Float64 val) const { return val.get_bits(); }
   1056 };
   1057 template <>
   1058 struct converter<uint32_t, Float32> {
   1059   uint32_t operator()(Float32 val) const { return val.get_bits(); }
   1060 };
   1061 
   1062 template <typename T>
   1063 V8_INLINE bool has_nondeterminism(T val) {
   1064   static_assert(!std::is_floating_point<T>::value, "missing specialization");
   1065   return false;
   1066 }
   1067 template <>
   1068 V8_INLINE bool has_nondeterminism<float>(float val) {
   1069   return std::isnan(val);
   1070 }
   1071 template <>
   1072 V8_INLINE bool has_nondeterminism<double>(double val) {
   1073   return std::isnan(val);
   1074 }
   1075 
   1076 // Responsible for executing code directly.
   1077 class ThreadImpl {
   1078   struct Activation {
   1079     uint32_t fp;
   1080     sp_t sp;
   1081     Activation(uint32_t fp, sp_t sp) : fp(fp), sp(sp) {}
   1082   };
   1083 
   1084  public:
   1085   ThreadImpl(Zone* zone, CodeMap* codemap,
   1086              Handle<WasmInstanceObject> instance_object)
   1087       : codemap_(codemap),
   1088         instance_object_(instance_object),
   1089         frames_(zone),
   1090         activations_(zone) {}
   1091 
   1092   //==========================================================================
   1093   // Implementation of public interface for WasmInterpreter::Thread.
   1094   //==========================================================================
   1095 
   1096   WasmInterpreter::State state() { return state_; }
   1097 
   1098   void InitFrame(const WasmFunction* function, WasmValue* args) {
   1099     DCHECK_EQ(current_activation().fp, frames_.size());
   1100     InterpreterCode* code = codemap()->GetCode(function);
   1101     size_t num_params = function->sig->parameter_count();
   1102     EnsureStackSpace(num_params);
   1103     Push(args, num_params);
   1104     PushFrame(code);
   1105   }
   1106 
   1107   WasmInterpreter::State Run(int num_steps = -1) {
   1108     DCHECK(state_ == WasmInterpreter::STOPPED ||
   1109            state_ == WasmInterpreter::PAUSED);
   1110     DCHECK(num_steps == -1 || num_steps > 0);
   1111     if (num_steps == -1) {
   1112       TRACE("  => Run()\n");
   1113     } else if (num_steps == 1) {
   1114       TRACE("  => Step()\n");
   1115     } else {
   1116       TRACE("  => Run(%d)\n", num_steps);
   1117     }
   1118     state_ = WasmInterpreter::RUNNING;
   1119     Execute(frames_.back().code, frames_.back().pc, num_steps);
   1120     // If state_ is STOPPED, the current activation must be fully unwound.
   1121     DCHECK_IMPLIES(state_ == WasmInterpreter::STOPPED,
   1122                    current_activation().fp == frames_.size());
   1123     return state_;
   1124   }
   1125 
   1126   void Pause() { UNIMPLEMENTED(); }
   1127 
   1128   void Reset() {
   1129     TRACE("----- RESET -----\n");
   1130     sp_ = stack_.get();
   1131     frames_.clear();
   1132     state_ = WasmInterpreter::STOPPED;
   1133     trap_reason_ = kTrapCount;
   1134     possible_nondeterminism_ = false;
   1135   }
   1136 
   1137   int GetFrameCount() {
   1138     DCHECK_GE(kMaxInt, frames_.size());
   1139     return static_cast<int>(frames_.size());
   1140   }
   1141 
   1142   WasmValue GetReturnValue(uint32_t index) {
   1143     if (state_ == WasmInterpreter::TRAPPED) return WasmValue(0xDEADBEEF);
   1144     DCHECK_EQ(WasmInterpreter::FINISHED, state_);
   1145     Activation act = current_activation();
   1146     // Current activation must be finished.
   1147     DCHECK_EQ(act.fp, frames_.size());
   1148     return GetStackValue(act.sp + index);
   1149   }
   1150 
   1151   WasmValue GetStackValue(sp_t index) {
   1152     DCHECK_GT(StackHeight(), index);
   1153     return stack_[index];
   1154   }
   1155 
   1156   void SetStackValue(sp_t index, WasmValue value) {
   1157     DCHECK_GT(StackHeight(), index);
   1158     stack_[index] = value;
   1159   }
   1160 
   1161   TrapReason GetTrapReason() { return trap_reason_; }
   1162 
   1163   pc_t GetBreakpointPc() { return break_pc_; }
   1164 
   1165   bool PossibleNondeterminism() { return possible_nondeterminism_; }
   1166 
   1167   uint64_t NumInterpretedCalls() { return num_interpreted_calls_; }
   1168 
   1169   void AddBreakFlags(uint8_t flags) { break_flags_ |= flags; }
   1170 
   1171   void ClearBreakFlags() { break_flags_ = WasmInterpreter::BreakFlag::None; }
   1172 
   1173   uint32_t NumActivations() {
   1174     return static_cast<uint32_t>(activations_.size());
   1175   }
   1176 
   1177   uint32_t StartActivation() {
   1178     TRACE("----- START ACTIVATION %zu -----\n", activations_.size());
   1179     // If you use activations, use them consistently:
   1180     DCHECK_IMPLIES(activations_.empty(), frames_.empty());
   1181     DCHECK_IMPLIES(activations_.empty(), StackHeight() == 0);
   1182     uint32_t activation_id = static_cast<uint32_t>(activations_.size());
   1183     activations_.emplace_back(static_cast<uint32_t>(frames_.size()),
   1184                               StackHeight());
   1185     state_ = WasmInterpreter::STOPPED;
   1186     return activation_id;
   1187   }
   1188 
   1189   void FinishActivation(uint32_t id) {
   1190     TRACE("----- FINISH ACTIVATION %zu -----\n", activations_.size() - 1);
   1191     DCHECK_LT(0, activations_.size());
   1192     DCHECK_EQ(activations_.size() - 1, id);
   1193     // Stack height must match the start of this activation (otherwise unwind
   1194     // first).
   1195     DCHECK_EQ(activations_.back().fp, frames_.size());
   1196     DCHECK_LE(activations_.back().sp, StackHeight());
   1197     sp_ = stack_.get() + activations_.back().sp;
   1198     activations_.pop_back();
   1199   }
   1200 
   1201   uint32_t ActivationFrameBase(uint32_t id) {
   1202     DCHECK_GT(activations_.size(), id);
   1203     return activations_[id].fp;
   1204   }
   1205 
   1206   // Handle a thrown exception. Returns whether the exception was handled inside
   1207   // the current activation. Unwinds the interpreted stack accordingly.
   1208   WasmInterpreter::Thread::ExceptionHandlingResult HandleException(
   1209       Isolate* isolate) {
   1210     DCHECK(isolate->has_pending_exception());
   1211     // TODO(wasm): Add wasm exception handling (would return HANDLED).
   1212     USE(isolate->pending_exception());
   1213     TRACE("----- UNWIND -----\n");
   1214     DCHECK_LT(0, activations_.size());
   1215     Activation& act = activations_.back();
   1216     DCHECK_LE(act.fp, frames_.size());
   1217     frames_.resize(act.fp);
   1218     DCHECK_LE(act.sp, StackHeight());
   1219     sp_ = stack_.get() + act.sp;
   1220     state_ = WasmInterpreter::STOPPED;
   1221     return WasmInterpreter::Thread::UNWOUND;
   1222   }
   1223 
   1224  private:
   1225   // Entries on the stack of functions being evaluated.
   1226   struct Frame {
   1227     InterpreterCode* code;
   1228     pc_t pc;
   1229     sp_t sp;
   1230 
   1231     // Limit of parameters.
   1232     sp_t plimit() { return sp + code->function->sig->parameter_count(); }
   1233     // Limit of locals.
   1234     sp_t llimit() { return plimit() + code->locals.type_list.size(); }
   1235   };
   1236 
   1237   struct Block {
   1238     pc_t pc;
   1239     sp_t sp;
   1240     size_t fp;
   1241     unsigned arity;
   1242   };
   1243 
   1244   friend class InterpretedFrameImpl;
   1245 
   1246   CodeMap* codemap_;
   1247   Handle<WasmInstanceObject> instance_object_;
   1248   std::unique_ptr<WasmValue[]> stack_;
   1249   WasmValue* stack_limit_ = nullptr;  // End of allocated stack space.
   1250   WasmValue* sp_ = nullptr;           // Current stack pointer.
   1251   ZoneVector<Frame> frames_;
   1252   WasmInterpreter::State state_ = WasmInterpreter::STOPPED;
   1253   pc_t break_pc_ = kInvalidPc;
   1254   TrapReason trap_reason_ = kTrapCount;
   1255   bool possible_nondeterminism_ = false;
   1256   uint8_t break_flags_ = 0;  // a combination of WasmInterpreter::BreakFlag
   1257   uint64_t num_interpreted_calls_ = 0;
   1258   // Store the stack height of each activation (for unwind and frame
   1259   // inspection).
   1260   ZoneVector<Activation> activations_;
   1261 
   1262   CodeMap* codemap() const { return codemap_; }
   1263   const WasmModule* module() const { return codemap_->module(); }
   1264 
   1265   void DoTrap(TrapReason trap, pc_t pc) {
   1266     TRACE("TRAP: %s\n", WasmOpcodes::TrapReasonMessage(trap));
   1267     state_ = WasmInterpreter::TRAPPED;
   1268     trap_reason_ = trap;
   1269     CommitPc(pc);
   1270   }
   1271 
   1272   // Push a frame with arguments already on the stack.
   1273   void PushFrame(InterpreterCode* code) {
   1274     DCHECK_NOT_NULL(code);
   1275     DCHECK_NOT_NULL(code->side_table);
   1276     EnsureStackSpace(code->side_table->max_stack_height_ +
   1277                      code->locals.type_list.size());
   1278 
   1279     ++num_interpreted_calls_;
   1280     size_t arity = code->function->sig->parameter_count();
   1281     // The parameters will overlap the arguments already on the stack.
   1282     DCHECK_GE(StackHeight(), arity);
   1283     frames_.push_back({code, 0, StackHeight() - arity});
   1284     frames_.back().pc = InitLocals(code);
   1285     TRACE("  => PushFrame #%zu (#%u @%zu)\n", frames_.size() - 1,
   1286           code->function->func_index, frames_.back().pc);
   1287   }
   1288 
   1289   pc_t InitLocals(InterpreterCode* code) {
   1290     for (auto p : code->locals.type_list) {
   1291       WasmValue val;
   1292       switch (p) {
   1293 #define CASE_TYPE(wasm, ctype) \
   1294   case kWasm##wasm:            \
   1295     val = WasmValue(ctype{});  \
   1296     break;
   1297         WASM_CTYPES(CASE_TYPE)
   1298 #undef CASE_TYPE
   1299         default:
   1300           UNREACHABLE();
   1301           break;
   1302       }
   1303       Push(val);
   1304     }
   1305     return code->locals.encoded_size;
   1306   }
   1307 
   1308   void CommitPc(pc_t pc) {
   1309     DCHECK(!frames_.empty());
   1310     frames_.back().pc = pc;
   1311   }
   1312 
   1313   bool SkipBreakpoint(InterpreterCode* code, pc_t pc) {
   1314     if (pc == break_pc_) {
   1315       // Skip the previously hit breakpoint when resuming.
   1316       break_pc_ = kInvalidPc;
   1317       return true;
   1318     }
   1319     return false;
   1320   }
   1321 
   1322   int LookupTargetDelta(InterpreterCode* code, pc_t pc) {
   1323     return static_cast<int>(code->side_table->Lookup(pc).pc_diff);
   1324   }
   1325 
   1326   int DoBreak(InterpreterCode* code, pc_t pc, size_t depth) {
   1327     ControlTransferEntry& control_transfer_entry = code->side_table->Lookup(pc);
   1328     DoStackTransfer(sp_ - control_transfer_entry.sp_diff,
   1329                     control_transfer_entry.target_arity);
   1330     return control_transfer_entry.pc_diff;
   1331   }
   1332 
   1333   pc_t ReturnPc(Decoder* decoder, InterpreterCode* code, pc_t pc) {
   1334     switch (code->orig_start[pc]) {
   1335       case kExprCallFunction: {
   1336         CallFunctionImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc));
   1337         return pc + 1 + imm.length;
   1338       }
   1339       case kExprCallIndirect: {
   1340         CallIndirectImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc));
   1341         return pc + 1 + imm.length;
   1342       }
   1343       default:
   1344         UNREACHABLE();
   1345     }
   1346   }
   1347 
   1348   bool DoReturn(Decoder* decoder, InterpreterCode** code, pc_t* pc, pc_t* limit,
   1349                 size_t arity) {
   1350     DCHECK_GT(frames_.size(), 0);
   1351     WasmValue* sp_dest = stack_.get() + frames_.back().sp;
   1352     frames_.pop_back();
   1353     if (frames_.size() == current_activation().fp) {
   1354       // A return from the last frame terminates the execution.
   1355       state_ = WasmInterpreter::FINISHED;
   1356       DoStackTransfer(sp_dest, arity);
   1357       TRACE("  => finish\n");
   1358       return false;
   1359     } else {
   1360       // Return to caller frame.
   1361       Frame* top = &frames_.back();
   1362       *code = top->code;
   1363       decoder->Reset((*code)->start, (*code)->end);
   1364       *pc = ReturnPc(decoder, *code, top->pc);
   1365       *limit = top->code->end - top->code->start;
   1366       TRACE("  => Return to #%zu (#%u @%zu)\n", frames_.size() - 1,
   1367             (*code)->function->func_index, *pc);
   1368       DoStackTransfer(sp_dest, arity);
   1369       return true;
   1370     }
   1371   }
   1372 
   1373   // Returns true if the call was successful, false if the stack check failed
   1374   // and the current activation was fully unwound.
   1375   bool DoCall(Decoder* decoder, InterpreterCode* target, pc_t* pc,
   1376               pc_t* limit) V8_WARN_UNUSED_RESULT {
   1377     frames_.back().pc = *pc;
   1378     PushFrame(target);
   1379     if (!DoStackCheck()) return false;
   1380     *pc = frames_.back().pc;
   1381     *limit = target->end - target->start;
   1382     decoder->Reset(target->start, target->end);
   1383     return true;
   1384   }
   1385 
   1386   // Copies {arity} values on the top of the stack down the stack to {dest},
   1387   // dropping the values in-between.
   1388   void DoStackTransfer(WasmValue* dest, size_t arity) {
   1389     // before: |---------------| pop_count | arity |
   1390     //         ^ 0             ^ dest              ^ sp_
   1391     //
   1392     // after:  |---------------| arity |
   1393     //         ^ 0                     ^ sp_
   1394     DCHECK_LE(dest, sp_);
   1395     DCHECK_LE(dest + arity, sp_);
   1396     if (arity) memmove(dest, sp_ - arity, arity * sizeof(*sp_));
   1397     sp_ = dest + arity;
   1398   }
   1399 
   1400   template <typename mtype>
   1401   inline Address BoundsCheckMem(uint32_t offset, uint32_t index) {
   1402     size_t mem_size = instance_object_->memory_size();
   1403     if (sizeof(mtype) > mem_size) return kNullAddress;
   1404     if (offset > (mem_size - sizeof(mtype))) return kNullAddress;
   1405     if (index > (mem_size - sizeof(mtype) - offset)) return kNullAddress;
   1406     // Compute the effective address of the access, making sure to condition
   1407     // the index even in the in-bounds case.
   1408     return reinterpret_cast<Address>(instance_object_->memory_start()) +
   1409            offset + (index & instance_object_->memory_mask());
   1410   }
   1411 
   1412   template <typename ctype, typename mtype>
   1413   bool ExecuteLoad(Decoder* decoder, InterpreterCode* code, pc_t pc, int& len,
   1414                    MachineRepresentation rep) {
   1415     MemoryAccessImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc),
   1416                                                     sizeof(ctype));
   1417     uint32_t index = Pop().to<uint32_t>();
   1418     Address addr = BoundsCheckMem<mtype>(imm.offset, index);
   1419     if (!addr) {
   1420       DoTrap(kTrapMemOutOfBounds, pc);
   1421       return false;
   1422     }
   1423     WasmValue result(
   1424         converter<ctype, mtype>{}(ReadLittleEndianValue<mtype>(addr)));
   1425 
   1426     Push(result);
   1427     len = 1 + imm.length;
   1428 
   1429     if (FLAG_wasm_trace_memory) {
   1430       MemoryTracingInfo info(imm.offset + index, false, rep);
   1431       TraceMemoryOperation(ExecutionTier::kInterpreter, &info,
   1432                            code->function->func_index, static_cast<int>(pc),
   1433                            instance_object_->memory_start());
   1434     }
   1435 
   1436     return true;
   1437   }
   1438 
   1439   template <typename ctype, typename mtype>
   1440   bool ExecuteStore(Decoder* decoder, InterpreterCode* code, pc_t pc, int& len,
   1441                     MachineRepresentation rep) {
   1442     MemoryAccessImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc),
   1443                                                     sizeof(ctype));
   1444     ctype val = Pop().to<ctype>();
   1445 
   1446     uint32_t index = Pop().to<uint32_t>();
   1447     Address addr = BoundsCheckMem<mtype>(imm.offset, index);
   1448     if (!addr) {
   1449       DoTrap(kTrapMemOutOfBounds, pc);
   1450       return false;
   1451     }
   1452     WriteLittleEndianValue<mtype>(addr, converter<mtype, ctype>{}(val));
   1453     len = 1 + imm.length;
   1454 
   1455     if (FLAG_wasm_trace_memory) {
   1456       MemoryTracingInfo info(imm.offset + index, true, rep);
   1457       TraceMemoryOperation(ExecutionTier::kInterpreter, &info,
   1458                            code->function->func_index, static_cast<int>(pc),
   1459                            instance_object_->memory_start());
   1460     }
   1461 
   1462     return true;
   1463   }
   1464 
   1465   template <typename type, typename op_type>
   1466   bool ExtractAtomicOpParams(Decoder* decoder, InterpreterCode* code,
   1467                              Address& address, pc_t pc, int& len,
   1468                              type* val = nullptr, type* val2 = nullptr) {
   1469     MemoryAccessImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc + 1),
   1470                                                     sizeof(type));
   1471     if (val2) *val2 = static_cast<type>(Pop().to<op_type>());
   1472     if (val) *val = static_cast<type>(Pop().to<op_type>());
   1473     uint32_t index = Pop().to<uint32_t>();
   1474     address = BoundsCheckMem<type>(imm.offset, index);
   1475     if (!address) {
   1476       DoTrap(kTrapMemOutOfBounds, pc);
   1477       return false;
   1478     }
   1479     len = 2 + imm.length;
   1480     return true;
   1481   }
   1482 
   1483   bool ExecuteNumericOp(WasmOpcode opcode, Decoder* decoder,
   1484                         InterpreterCode* code, pc_t pc, int& len) {
   1485     switch (opcode) {
   1486       case kExprI32SConvertSatF32:
   1487         Push(WasmValue(ExecuteConvertSaturate<int32_t>(Pop().to<float>())));
   1488         return true;
   1489       case kExprI32UConvertSatF32:
   1490         Push(WasmValue(ExecuteConvertSaturate<uint32_t>(Pop().to<float>())));
   1491         return true;
   1492       case kExprI32SConvertSatF64:
   1493         Push(WasmValue(ExecuteConvertSaturate<int32_t>(Pop().to<double>())));
   1494         return true;
   1495       case kExprI32UConvertSatF64:
   1496         Push(WasmValue(ExecuteConvertSaturate<uint32_t>(Pop().to<double>())));
   1497         return true;
   1498       case kExprI64SConvertSatF32:
   1499         Push(WasmValue(ExecuteI64SConvertSatF32(Pop().to<float>())));
   1500         return true;
   1501       case kExprI64UConvertSatF32:
   1502         Push(WasmValue(ExecuteI64UConvertSatF32(Pop().to<float>())));
   1503         return true;
   1504       case kExprI64SConvertSatF64:
   1505         Push(WasmValue(ExecuteI64SConvertSatF64(Pop().to<double>())));
   1506         return true;
   1507       case kExprI64UConvertSatF64:
   1508         Push(WasmValue(ExecuteI64UConvertSatF64(Pop().to<double>())));
   1509         return true;
   1510       default:
   1511         FATAL("Unknown or unimplemented opcode #%d:%s", code->start[pc],
   1512               OpcodeName(code->start[pc]));
   1513         UNREACHABLE();
   1514     }
   1515     return false;
   1516   }
   1517 
   1518   bool ExecuteAtomicOp(WasmOpcode opcode, Decoder* decoder,
   1519                        InterpreterCode* code, pc_t pc, int& len) {
   1520     WasmValue result;
   1521     switch (opcode) {
   1522 // Disabling on Mips as 32 bit atomics are not correctly laid out for load/store
   1523 // on big endian and 64 bit atomics fail to compile.
   1524 #if !(V8_TARGET_ARCH_MIPS && V8_TARGET_BIG_ENDIAN)
   1525 #define ATOMIC_BINOP_CASE(name, type, op_type, operation)                   \
   1526   case kExpr##name: {                                                       \
   1527     type val;                                                               \
   1528     Address addr;                                                           \
   1529     if (!ExtractAtomicOpParams<type, op_type>(decoder, code, addr, pc, len, \
   1530                                               &val)) {                      \
   1531       return false;                                                         \
   1532     }                                                                       \
   1533     static_assert(sizeof(std::atomic<type>) == sizeof(type),                \
   1534                   "Size mismatch for types std::atomic<" #type              \
   1535                   ">, and " #type);                                         \
   1536     result = WasmValue(static_cast<op_type>(                                \
   1537         std::operation(reinterpret_cast<std::atomic<type>*>(addr), val)));  \
   1538     Push(result);                                                           \
   1539     break;                                                                  \
   1540   }
   1541       ATOMIC_BINOP_CASE(I32AtomicAdd, uint32_t, uint32_t, atomic_fetch_add);
   1542       ATOMIC_BINOP_CASE(I32AtomicAdd8U, uint8_t, uint32_t, atomic_fetch_add);
   1543       ATOMIC_BINOP_CASE(I32AtomicAdd16U, uint16_t, uint32_t, atomic_fetch_add);
   1544       ATOMIC_BINOP_CASE(I32AtomicSub, uint32_t, uint32_t, atomic_fetch_sub);
   1545       ATOMIC_BINOP_CASE(I32AtomicSub8U, uint8_t, uint32_t, atomic_fetch_sub);
   1546       ATOMIC_BINOP_CASE(I32AtomicSub16U, uint16_t, uint32_t, atomic_fetch_sub);
   1547       ATOMIC_BINOP_CASE(I32AtomicAnd, uint32_t, uint32_t, atomic_fetch_and);
   1548       ATOMIC_BINOP_CASE(I32AtomicAnd8U, uint8_t, uint32_t, atomic_fetch_and);
   1549       ATOMIC_BINOP_CASE(I32AtomicAnd16U, uint16_t, uint32_t, atomic_fetch_and);
   1550       ATOMIC_BINOP_CASE(I32AtomicOr, uint32_t, uint32_t, atomic_fetch_or);
   1551       ATOMIC_BINOP_CASE(I32AtomicOr8U, uint8_t, uint32_t, atomic_fetch_or);
   1552       ATOMIC_BINOP_CASE(I32AtomicOr16U, uint16_t, uint32_t, atomic_fetch_or);
   1553       ATOMIC_BINOP_CASE(I32AtomicXor, uint32_t, uint32_t, atomic_fetch_xor);
   1554       ATOMIC_BINOP_CASE(I32AtomicXor8U, uint8_t, uint32_t, atomic_fetch_xor);
   1555       ATOMIC_BINOP_CASE(I32AtomicXor16U, uint16_t, uint32_t, atomic_fetch_xor);
   1556       ATOMIC_BINOP_CASE(I32AtomicExchange, uint32_t, uint32_t, atomic_exchange);
   1557       ATOMIC_BINOP_CASE(I32AtomicExchange8U, uint8_t, uint32_t,
   1558                         atomic_exchange);
   1559       ATOMIC_BINOP_CASE(I32AtomicExchange16U, uint16_t, uint32_t,
   1560                         atomic_exchange);
   1561       ATOMIC_BINOP_CASE(I64AtomicAdd, uint64_t, uint64_t, atomic_fetch_add);
   1562       ATOMIC_BINOP_CASE(I64AtomicAdd8U, uint8_t, uint64_t, atomic_fetch_add);
   1563       ATOMIC_BINOP_CASE(I64AtomicAdd16U, uint16_t, uint64_t, atomic_fetch_add);
   1564       ATOMIC_BINOP_CASE(I64AtomicAdd32U, uint32_t, uint64_t, atomic_fetch_add);
   1565       ATOMIC_BINOP_CASE(I64AtomicSub, uint64_t, uint64_t, atomic_fetch_sub);
   1566       ATOMIC_BINOP_CASE(I64AtomicSub8U, uint8_t, uint64_t, atomic_fetch_sub);
   1567       ATOMIC_BINOP_CASE(I64AtomicSub16U, uint16_t, uint64_t, atomic_fetch_sub);
   1568       ATOMIC_BINOP_CASE(I64AtomicSub32U, uint32_t, uint64_t, atomic_fetch_sub);
   1569       ATOMIC_BINOP_CASE(I64AtomicAnd, uint64_t, uint64_t, atomic_fetch_and);
   1570       ATOMIC_BINOP_CASE(I64AtomicAnd8U, uint8_t, uint64_t, atomic_fetch_and);
   1571       ATOMIC_BINOP_CASE(I64AtomicAnd16U, uint16_t, uint64_t, atomic_fetch_and);
   1572       ATOMIC_BINOP_CASE(I64AtomicAnd32U, uint32_t, uint64_t, atomic_fetch_and);
   1573       ATOMIC_BINOP_CASE(I64AtomicOr, uint64_t, uint64_t, atomic_fetch_or);
   1574       ATOMIC_BINOP_CASE(I64AtomicOr8U, uint8_t, uint64_t, atomic_fetch_or);
   1575       ATOMIC_BINOP_CASE(I64AtomicOr16U, uint16_t, uint64_t, atomic_fetch_or);
   1576       ATOMIC_BINOP_CASE(I64AtomicOr32U, uint32_t, uint64_t, atomic_fetch_or);
   1577       ATOMIC_BINOP_CASE(I64AtomicXor, uint64_t, uint64_t, atomic_fetch_xor);
   1578       ATOMIC_BINOP_CASE(I64AtomicXor8U, uint8_t, uint64_t, atomic_fetch_xor);
   1579       ATOMIC_BINOP_CASE(I64AtomicXor16U, uint16_t, uint64_t, atomic_fetch_xor);
   1580       ATOMIC_BINOP_CASE(I64AtomicXor32U, uint32_t, uint64_t, atomic_fetch_xor);
   1581       ATOMIC_BINOP_CASE(I64AtomicExchange, uint64_t, uint64_t, atomic_exchange);
   1582       ATOMIC_BINOP_CASE(I64AtomicExchange8U, uint8_t, uint64_t,
   1583                         atomic_exchange);
   1584       ATOMIC_BINOP_CASE(I64AtomicExchange16U, uint16_t, uint64_t,
   1585                         atomic_exchange);
   1586       ATOMIC_BINOP_CASE(I64AtomicExchange32U, uint32_t, uint64_t,
   1587                         atomic_exchange);
   1588 #undef ATOMIC_BINOP_CASE
   1589 #define ATOMIC_COMPARE_EXCHANGE_CASE(name, type, op_type)                   \
   1590   case kExpr##name: {                                                       \
   1591     type val;                                                               \
   1592     type val2;                                                              \
   1593     Address addr;                                                           \
   1594     if (!ExtractAtomicOpParams<type, op_type>(decoder, code, addr, pc, len, \
   1595                                               &val, &val2)) {               \
   1596       return false;                                                         \
   1597     }                                                                       \
   1598     static_assert(sizeof(std::atomic<type>) == sizeof(type),                \
   1599                   "Size mismatch for types std::atomic<" #type              \
   1600                   ">, and " #type);                                         \
   1601     std::atomic_compare_exchange_strong(                                    \
   1602         reinterpret_cast<std::atomic<type>*>(addr), &val, val2);            \
   1603     Push(WasmValue(static_cast<op_type>(val)));                             \
   1604     break;                                                                  \
   1605   }
   1606       ATOMIC_COMPARE_EXCHANGE_CASE(I32AtomicCompareExchange, uint32_t,
   1607                                    uint32_t);
   1608       ATOMIC_COMPARE_EXCHANGE_CASE(I32AtomicCompareExchange8U, uint8_t,
   1609                                    uint32_t);
   1610       ATOMIC_COMPARE_EXCHANGE_CASE(I32AtomicCompareExchange16U, uint16_t,
   1611                                    uint32_t);
   1612       ATOMIC_COMPARE_EXCHANGE_CASE(I64AtomicCompareExchange, uint64_t,
   1613                                    uint64_t);
   1614       ATOMIC_COMPARE_EXCHANGE_CASE(I64AtomicCompareExchange8U, uint8_t,
   1615                                    uint64_t);
   1616       ATOMIC_COMPARE_EXCHANGE_CASE(I64AtomicCompareExchange16U, uint16_t,
   1617                                    uint64_t);
   1618       ATOMIC_COMPARE_EXCHANGE_CASE(I64AtomicCompareExchange32U, uint32_t,
   1619                                    uint64_t);
   1620 #undef ATOMIC_COMPARE_EXCHANGE_CASE
   1621 #define ATOMIC_LOAD_CASE(name, type, op_type, operation)                       \
   1622   case kExpr##name: {                                                          \
   1623     Address addr;                                                              \
   1624     if (!ExtractAtomicOpParams<type, op_type>(decoder, code, addr, pc, len)) { \
   1625       return false;                                                            \
   1626     }                                                                          \
   1627     static_assert(sizeof(std::atomic<type>) == sizeof(type),                   \
   1628                   "Size mismatch for types std::atomic<" #type                 \
   1629                   ">, and " #type);                                            \
   1630     result = WasmValue(static_cast<op_type>(                                   \
   1631         std::operation(reinterpret_cast<std::atomic<type>*>(addr))));          \
   1632     Push(result);                                                              \
   1633     break;                                                                     \
   1634   }
   1635       ATOMIC_LOAD_CASE(I32AtomicLoad, uint32_t, uint32_t, atomic_load);
   1636       ATOMIC_LOAD_CASE(I32AtomicLoad8U, uint8_t, uint32_t, atomic_load);
   1637       ATOMIC_LOAD_CASE(I32AtomicLoad16U, uint16_t, uint32_t, atomic_load);
   1638       ATOMIC_LOAD_CASE(I64AtomicLoad, uint64_t, uint64_t, atomic_load);
   1639       ATOMIC_LOAD_CASE(I64AtomicLoad8U, uint8_t, uint64_t, atomic_load);
   1640       ATOMIC_LOAD_CASE(I64AtomicLoad16U, uint16_t, uint64_t, atomic_load);
   1641       ATOMIC_LOAD_CASE(I64AtomicLoad32U, uint32_t, uint64_t, atomic_load);
   1642 #undef ATOMIC_LOAD_CASE
   1643 #define ATOMIC_STORE_CASE(name, type, op_type, operation)                   \
   1644   case kExpr##name: {                                                       \
   1645     type val;                                                               \
   1646     Address addr;                                                           \
   1647     if (!ExtractAtomicOpParams<type, op_type>(decoder, code, addr, pc, len, \
   1648                                               &val)) {                      \
   1649       return false;                                                         \
   1650     }                                                                       \
   1651     static_assert(sizeof(std::atomic<type>) == sizeof(type),                \
   1652                   "Size mismatch for types std::atomic<" #type              \
   1653                   ">, and " #type);                                         \
   1654     std::operation(reinterpret_cast<std::atomic<type>*>(addr), val);        \
   1655     break;                                                                  \
   1656   }
   1657       ATOMIC_STORE_CASE(I32AtomicStore, uint32_t, uint32_t, atomic_store);
   1658       ATOMIC_STORE_CASE(I32AtomicStore8U, uint8_t, uint32_t, atomic_store);
   1659       ATOMIC_STORE_CASE(I32AtomicStore16U, uint16_t, uint32_t, atomic_store);
   1660       ATOMIC_STORE_CASE(I64AtomicStore, uint64_t, uint64_t, atomic_store);
   1661       ATOMIC_STORE_CASE(I64AtomicStore8U, uint8_t, uint64_t, atomic_store);
   1662       ATOMIC_STORE_CASE(I64AtomicStore16U, uint16_t, uint64_t, atomic_store);
   1663       ATOMIC_STORE_CASE(I64AtomicStore32U, uint32_t, uint64_t, atomic_store);
   1664 #undef ATOMIC_STORE_CASE
   1665 #endif  // !(V8_TARGET_ARCH_MIPS && V8_TARGET_BIG_ENDIAN)
   1666       default:
   1667         UNREACHABLE();
   1668         return false;
   1669     }
   1670     return true;
   1671   }
   1672 
   1673   byte* GetGlobalPtr(const WasmGlobal* global) {
   1674     if (global->mutability && global->imported) {
   1675       return reinterpret_cast<byte*>(
   1676           instance_object_->imported_mutable_globals()[global->index]);
   1677     } else {
   1678       return instance_object_->globals_start() + global->offset;
   1679     }
   1680   }
   1681 
   1682   bool ExecuteSimdOp(WasmOpcode opcode, Decoder* decoder, InterpreterCode* code,
   1683                      pc_t pc, int& len) {
   1684     switch (opcode) {
   1685 #define SPLAT_CASE(format, sType, valType, num) \
   1686   case kExpr##format##Splat: {                  \
   1687     WasmValue val = Pop();                      \
   1688     valType v = val.to<valType>();              \
   1689     sType s;                                    \
   1690     for (int i = 0; i < num; i++) s.val[i] = v; \
   1691     Push(WasmValue(Simd128(s)));                \
   1692     return true;                                \
   1693   }
   1694       SPLAT_CASE(I32x4, int4, int32_t, 4)
   1695       SPLAT_CASE(F32x4, float4, float, 4)
   1696       SPLAT_CASE(I16x8, int8, int32_t, 8)
   1697       SPLAT_CASE(I8x16, int16, int32_t, 16)
   1698 #undef SPLAT_CASE
   1699 #define EXTRACT_LANE_CASE(format, name)                                 \
   1700   case kExpr##format##ExtractLane: {                                    \
   1701     SimdLaneImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc)); \
   1702     ++len;                                                              \
   1703     WasmValue val = Pop();                                              \
   1704     Simd128 s = val.to_s128();                                          \
   1705     auto ss = s.to_##name();                                            \
   1706     Push(WasmValue(ss.val[LANE(imm.lane, ss)]));                        \
   1707     return true;                                                        \
   1708   }
   1709       EXTRACT_LANE_CASE(I32x4, i32x4)
   1710       EXTRACT_LANE_CASE(F32x4, f32x4)
   1711       EXTRACT_LANE_CASE(I16x8, i16x8)
   1712       EXTRACT_LANE_CASE(I8x16, i8x16)
   1713 #undef EXTRACT_LANE_CASE
   1714 #define BINOP_CASE(op, name, stype, count, expr) \
   1715   case kExpr##op: {                              \
   1716     WasmValue v2 = Pop();                        \
   1717     WasmValue v1 = Pop();                        \
   1718     stype s1 = v1.to_s128().to_##name();         \
   1719     stype s2 = v2.to_s128().to_##name();         \
   1720     stype res;                                   \
   1721     for (size_t i = 0; i < count; ++i) {         \
   1722       auto a = s1.val[LANE(i, s1)];              \
   1723       auto b = s2.val[LANE(i, s1)];              \
   1724       res.val[LANE(i, s1)] = expr;               \
   1725     }                                            \
   1726     Push(WasmValue(Simd128(res)));               \
   1727     return true;                                 \
   1728   }
   1729       BINOP_CASE(F32x4Add, f32x4, float4, 4, a + b)
   1730       BINOP_CASE(F32x4Sub, f32x4, float4, 4, a - b)
   1731       BINOP_CASE(F32x4Mul, f32x4, float4, 4, a * b)
   1732       BINOP_CASE(F32x4Min, f32x4, float4, 4, a < b ? a : b)
   1733       BINOP_CASE(F32x4Max, f32x4, float4, 4, a > b ? a : b)
   1734       BINOP_CASE(I32x4Add, i32x4, int4, 4, a + b)
   1735       BINOP_CASE(I32x4Sub, i32x4, int4, 4, a - b)
   1736       BINOP_CASE(I32x4Mul, i32x4, int4, 4, a * b)
   1737       BINOP_CASE(I32x4MinS, i32x4, int4, 4, a < b ? a : b)
   1738       BINOP_CASE(I32x4MinU, i32x4, int4, 4,
   1739                  static_cast<uint32_t>(a) < static_cast<uint32_t>(b) ? a : b)
   1740       BINOP_CASE(I32x4MaxS, i32x4, int4, 4, a > b ? a : b)
   1741       BINOP_CASE(I32x4MaxU, i32x4, int4, 4,
   1742                  static_cast<uint32_t>(a) > static_cast<uint32_t>(b) ? a : b)
   1743       BINOP_CASE(S128And, i32x4, int4, 4, a & b)
   1744       BINOP_CASE(S128Or, i32x4, int4, 4, a | b)
   1745       BINOP_CASE(S128Xor, i32x4, int4, 4, a ^ b)
   1746       BINOP_CASE(I16x8Add, i16x8, int8, 8, a + b)
   1747       BINOP_CASE(I16x8Sub, i16x8, int8, 8, a - b)
   1748       BINOP_CASE(I16x8Mul, i16x8, int8, 8, a * b)
   1749       BINOP_CASE(I16x8MinS, i16x8, int8, 8, a < b ? a : b)
   1750       BINOP_CASE(I16x8MinU, i16x8, int8, 8,
   1751                  static_cast<uint16_t>(a) < static_cast<uint16_t>(b) ? a : b)
   1752       BINOP_CASE(I16x8MaxS, i16x8, int8, 8, a > b ? a : b)
   1753       BINOP_CASE(I16x8MaxU, i16x8, int8, 8,
   1754                  static_cast<uint16_t>(a) > static_cast<uint16_t>(b) ? a : b)
   1755       BINOP_CASE(I16x8AddSaturateS, i16x8, int8, 8, SaturateAdd<int16_t>(a, b))
   1756       BINOP_CASE(I16x8AddSaturateU, i16x8, int8, 8, SaturateAdd<uint16_t>(a, b))
   1757       BINOP_CASE(I16x8SubSaturateS, i16x8, int8, 8, SaturateSub<int16_t>(a, b))
   1758       BINOP_CASE(I16x8SubSaturateU, i16x8, int8, 8, SaturateSub<uint16_t>(a, b))
   1759       BINOP_CASE(I8x16Add, i8x16, int16, 16, a + b)
   1760       BINOP_CASE(I8x16Sub, i8x16, int16, 16, a - b)
   1761       BINOP_CASE(I8x16Mul, i8x16, int16, 16, a * b)
   1762       BINOP_CASE(I8x16MinS, i8x16, int16, 16, a < b ? a : b)
   1763       BINOP_CASE(I8x16MinU, i8x16, int16, 16,
   1764                  static_cast<uint8_t>(a) < static_cast<uint8_t>(b) ? a : b)
   1765       BINOP_CASE(I8x16MaxS, i8x16, int16, 16, a > b ? a : b)
   1766       BINOP_CASE(I8x16MaxU, i8x16, int16, 16,
   1767                  static_cast<uint8_t>(a) > static_cast<uint8_t>(b) ? a : b)
   1768       BINOP_CASE(I8x16AddSaturateS, i8x16, int16, 16, SaturateAdd<int8_t>(a, b))
   1769       BINOP_CASE(I8x16AddSaturateU, i8x16, int16, 16,
   1770                  SaturateAdd<uint8_t>(a, b))
   1771       BINOP_CASE(I8x16SubSaturateS, i8x16, int16, 16, SaturateSub<int8_t>(a, b))
   1772       BINOP_CASE(I8x16SubSaturateU, i8x16, int16, 16,
   1773                  SaturateSub<uint8_t>(a, b))
   1774 #undef BINOP_CASE
   1775 #define UNOP_CASE(op, name, stype, count, expr) \
   1776   case kExpr##op: {                             \
   1777     WasmValue v = Pop();                        \
   1778     stype s = v.to_s128().to_##name();          \
   1779     stype res;                                  \
   1780     for (size_t i = 0; i < count; ++i) {        \
   1781       auto a = s.val[i];                        \
   1782       res.val[i] = expr;                        \
   1783     }                                           \
   1784     Push(WasmValue(Simd128(res)));              \
   1785     return true;                                \
   1786   }
   1787       UNOP_CASE(F32x4Abs, f32x4, float4, 4, std::abs(a))
   1788       UNOP_CASE(F32x4Neg, f32x4, float4, 4, -a)
   1789       UNOP_CASE(F32x4RecipApprox, f32x4, float4, 4, 1.0f / a)
   1790       UNOP_CASE(F32x4RecipSqrtApprox, f32x4, float4, 4, 1.0f / std::sqrt(a))
   1791       UNOP_CASE(I32x4Neg, i32x4, int4, 4, -a)
   1792       UNOP_CASE(S128Not, i32x4, int4, 4, ~a)
   1793       UNOP_CASE(I16x8Neg, i16x8, int8, 8, -a)
   1794       UNOP_CASE(I8x16Neg, i8x16, int16, 16, -a)
   1795 #undef UNOP_CASE
   1796 #define CMPOP_CASE(op, name, stype, out_stype, count, expr) \
   1797   case kExpr##op: {                                         \
   1798     WasmValue v2 = Pop();                                   \
   1799     WasmValue v1 = Pop();                                   \
   1800     stype s1 = v1.to_s128().to_##name();                    \
   1801     stype s2 = v2.to_s128().to_##name();                    \
   1802     out_stype res;                                          \
   1803     for (size_t i = 0; i < count; ++i) {                    \
   1804       auto a = s1.val[i];                                   \
   1805       auto b = s2.val[i];                                   \
   1806       res.val[i] = expr ? -1 : 0;                           \
   1807     }                                                       \
   1808     Push(WasmValue(Simd128(res)));                          \
   1809     return true;                                            \
   1810   }
   1811       CMPOP_CASE(F32x4Eq, f32x4, float4, int4, 4, a == b)
   1812       CMPOP_CASE(F32x4Ne, f32x4, float4, int4, 4, a != b)
   1813       CMPOP_CASE(F32x4Gt, f32x4, float4, int4, 4, a > b)
   1814       CMPOP_CASE(F32x4Ge, f32x4, float4, int4, 4, a >= b)
   1815       CMPOP_CASE(F32x4Lt, f32x4, float4, int4, 4, a < b)
   1816       CMPOP_CASE(F32x4Le, f32x4, float4, int4, 4, a <= b)
   1817       CMPOP_CASE(I32x4Eq, i32x4, int4, int4, 4, a == b)
   1818       CMPOP_CASE(I32x4Ne, i32x4, int4, int4, 4, a != b)
   1819       CMPOP_CASE(I32x4GtS, i32x4, int4, int4, 4, a > b)
   1820       CMPOP_CASE(I32x4GeS, i32x4, int4, int4, 4, a >= b)
   1821       CMPOP_CASE(I32x4LtS, i32x4, int4, int4, 4, a < b)
   1822       CMPOP_CASE(I32x4LeS, i32x4, int4, int4, 4, a <= b)
   1823       CMPOP_CASE(I32x4GtU, i32x4, int4, int4, 4,
   1824                  static_cast<uint32_t>(a) > static_cast<uint32_t>(b))
   1825       CMPOP_CASE(I32x4GeU, i32x4, int4, int4, 4,
   1826                  static_cast<uint32_t>(a) >= static_cast<uint32_t>(b))
   1827       CMPOP_CASE(I32x4LtU, i32x4, int4, int4, 4,
   1828                  static_cast<uint32_t>(a) < static_cast<uint32_t>(b))
   1829       CMPOP_CASE(I32x4LeU, i32x4, int4, int4, 4,
   1830                  static_cast<uint32_t>(a) <= static_cast<uint32_t>(b))
   1831       CMPOP_CASE(I16x8Eq, i16x8, int8, int8, 8, a == b)
   1832       CMPOP_CASE(I16x8Ne, i16x8, int8, int8, 8, a != b)
   1833       CMPOP_CASE(I16x8GtS, i16x8, int8, int8, 8, a > b)
   1834       CMPOP_CASE(I16x8GeS, i16x8, int8, int8, 8, a >= b)
   1835       CMPOP_CASE(I16x8LtS, i16x8, int8, int8, 8, a < b)
   1836       CMPOP_CASE(I16x8LeS, i16x8, int8, int8, 8, a <= b)
   1837       CMPOP_CASE(I16x8GtU, i16x8, int8, int8, 8,
   1838                  static_cast<uint16_t>(a) > static_cast<uint16_t>(b))
   1839       CMPOP_CASE(I16x8GeU, i16x8, int8, int8, 8,
   1840                  static_cast<uint16_t>(a) >= static_cast<uint16_t>(b))
   1841       CMPOP_CASE(I16x8LtU, i16x8, int8, int8, 8,
   1842                  static_cast<uint16_t>(a) < static_cast<uint16_t>(b))
   1843       CMPOP_CASE(I16x8LeU, i16x8, int8, int8, 8,
   1844                  static_cast<uint16_t>(a) <= static_cast<uint16_t>(b))
   1845       CMPOP_CASE(I8x16Eq, i8x16, int16, int16, 16, a == b)
   1846       CMPOP_CASE(I8x16Ne, i8x16, int16, int16, 16, a != b)
   1847       CMPOP_CASE(I8x16GtS, i8x16, int16, int16, 16, a > b)
   1848       CMPOP_CASE(I8x16GeS, i8x16, int16, int16, 16, a >= b)
   1849       CMPOP_CASE(I8x16LtS, i8x16, int16, int16, 16, a < b)
   1850       CMPOP_CASE(I8x16LeS, i8x16, int16, int16, 16, a <= b)
   1851       CMPOP_CASE(I8x16GtU, i8x16, int16, int16, 16,
   1852                  static_cast<uint8_t>(a) > static_cast<uint8_t>(b))
   1853       CMPOP_CASE(I8x16GeU, i8x16, int16, int16, 16,
   1854                  static_cast<uint8_t>(a) >= static_cast<uint8_t>(b))
   1855       CMPOP_CASE(I8x16LtU, i8x16, int16, int16, 16,
   1856                  static_cast<uint8_t>(a) < static_cast<uint8_t>(b))
   1857       CMPOP_CASE(I8x16LeU, i8x16, int16, int16, 16,
   1858                  static_cast<uint8_t>(a) <= static_cast<uint8_t>(b))
   1859 #undef CMPOP_CASE
   1860 #define REPLACE_LANE_CASE(format, name, stype, ctype)                   \
   1861   case kExpr##format##ReplaceLane: {                                    \
   1862     SimdLaneImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc)); \
   1863     ++len;                                                              \
   1864     WasmValue new_val = Pop();                                          \
   1865     WasmValue simd_val = Pop();                                         \
   1866     stype s = simd_val.to_s128().to_##name();                           \
   1867     s.val[LANE(imm.lane, s)] = new_val.to<ctype>();                     \
   1868     Push(WasmValue(Simd128(s)));                                        \
   1869     return true;                                                        \
   1870   }
   1871       REPLACE_LANE_CASE(F32x4, f32x4, float4, float)
   1872       REPLACE_LANE_CASE(I32x4, i32x4, int4, int32_t)
   1873       REPLACE_LANE_CASE(I16x8, i16x8, int8, int32_t)
   1874       REPLACE_LANE_CASE(I8x16, i8x16, int16, int32_t)
   1875 #undef REPLACE_LANE_CASE
   1876       case kExprS128LoadMem:
   1877         return ExecuteLoad<Simd128, Simd128>(decoder, code, pc, len,
   1878                                              MachineRepresentation::kSimd128);
   1879       case kExprS128StoreMem:
   1880         return ExecuteStore<Simd128, Simd128>(decoder, code, pc, len,
   1881                                               MachineRepresentation::kSimd128);
   1882 #define SHIFT_CASE(op, name, stype, count, expr)                         \
   1883   case kExpr##op: {                                                      \
   1884     SimdShiftImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc)); \
   1885     ++len;                                                               \
   1886     WasmValue v = Pop();                                                 \
   1887     stype s = v.to_s128().to_##name();                                   \
   1888     stype res;                                                           \
   1889     for (size_t i = 0; i < count; ++i) {                                 \
   1890       auto a = s.val[i];                                                 \
   1891       res.val[i] = expr;                                                 \
   1892     }                                                                    \
   1893     Push(WasmValue(Simd128(res)));                                       \
   1894     return true;                                                         \
   1895   }
   1896         SHIFT_CASE(I32x4Shl, i32x4, int4, 4, a << imm.shift)
   1897         SHIFT_CASE(I32x4ShrS, i32x4, int4, 4, a >> imm.shift)
   1898         SHIFT_CASE(I32x4ShrU, i32x4, int4, 4,
   1899                    static_cast<uint32_t>(a) >> imm.shift)
   1900         SHIFT_CASE(I16x8Shl, i16x8, int8, 8, a << imm.shift)
   1901         SHIFT_CASE(I16x8ShrS, i16x8, int8, 8, a >> imm.shift)
   1902         SHIFT_CASE(I16x8ShrU, i16x8, int8, 8,
   1903                    static_cast<uint16_t>(a) >> imm.shift)
   1904         SHIFT_CASE(I8x16Shl, i8x16, int16, 16, a << imm.shift)
   1905         SHIFT_CASE(I8x16ShrS, i8x16, int16, 16, a >> imm.shift)
   1906         SHIFT_CASE(I8x16ShrU, i8x16, int16, 16,
   1907                    static_cast<uint8_t>(a) >> imm.shift)
   1908 #undef SHIFT_CASE
   1909 #define CONVERT_CASE(op, src_type, name, dst_type, count, start_index, ctype, \
   1910                      expr)                                                    \
   1911   case kExpr##op: {                                                           \
   1912     WasmValue v = Pop();                                                      \
   1913     src_type s = v.to_s128().to_##name();                                     \
   1914     dst_type res;                                                             \
   1915     for (size_t i = 0; i < count; ++i) {                                      \
   1916       ctype a = s.val[LANE(start_index + i, s)];                              \
   1917       res.val[LANE(i, res)] = expr;                                           \
   1918     }                                                                         \
   1919     Push(WasmValue(Simd128(res)));                                            \
   1920     return true;                                                              \
   1921   }
   1922         CONVERT_CASE(F32x4SConvertI32x4, int4, i32x4, float4, 4, 0, int32_t,
   1923                      static_cast<float>(a))
   1924         CONVERT_CASE(F32x4UConvertI32x4, int4, i32x4, float4, 4, 0, uint32_t,
   1925                      static_cast<float>(a))
   1926         CONVERT_CASE(I32x4SConvertF32x4, float4, f32x4, int4, 4, 0, double,
   1927                      std::isnan(a) ? 0
   1928                                    : a<kMinInt ? kMinInt : a> kMaxInt
   1929                                          ? kMaxInt
   1930                                          : static_cast<int32_t>(a))
   1931         CONVERT_CASE(I32x4UConvertF32x4, float4, f32x4, int4, 4, 0, double,
   1932                      std::isnan(a)
   1933                          ? 0
   1934                          : a<0 ? 0 : a> kMaxUInt32 ? kMaxUInt32
   1935                                                    : static_cast<uint32_t>(a))
   1936         CONVERT_CASE(I32x4SConvertI16x8High, int8, i16x8, int4, 4, 4, int16_t,
   1937                      a)
   1938         CONVERT_CASE(I32x4UConvertI16x8High, int8, i16x8, int4, 4, 4, uint16_t,
   1939                      a)
   1940         CONVERT_CASE(I32x4SConvertI16x8Low, int8, i16x8, int4, 4, 0, int16_t, a)
   1941         CONVERT_CASE(I32x4UConvertI16x8Low, int8, i16x8, int4, 4, 0, uint16_t,
   1942                      a)
   1943         CONVERT_CASE(I16x8SConvertI8x16High, int16, i8x16, int8, 8, 8, int8_t,
   1944                      a)
   1945         CONVERT_CASE(I16x8UConvertI8x16High, int16, i8x16, int8, 8, 8, uint8_t,
   1946                      a)
   1947         CONVERT_CASE(I16x8SConvertI8x16Low, int16, i8x16, int8, 8, 0, int8_t, a)
   1948         CONVERT_CASE(I16x8UConvertI8x16Low, int16, i8x16, int8, 8, 0, uint8_t,
   1949                      a)
   1950 #undef CONVERT_CASE
   1951 #define PACK_CASE(op, src_type, name, dst_type, count, ctype, dst_ctype,   \
   1952                   is_unsigned)                                             \
   1953   case kExpr##op: {                                                        \
   1954     WasmValue v2 = Pop();                                                  \
   1955     WasmValue v1 = Pop();                                                  \
   1956     src_type s1 = v1.to_s128().to_##name();                                \
   1957     src_type s2 = v2.to_s128().to_##name();                                \
   1958     dst_type res;                                                          \
   1959     int64_t min = std::numeric_limits<ctype>::min();                       \
   1960     int64_t max = std::numeric_limits<ctype>::max();                       \
   1961     for (size_t i = 0; i < count; ++i) {                                   \
   1962       int32_t v = i < count / 2 ? s1.val[LANE(i, s1)]                      \
   1963                                 : s2.val[LANE(i - count / 2, s2)];         \
   1964       int64_t a = is_unsigned ? static_cast<int64_t>(v & 0xFFFFFFFFu) : v; \
   1965       res.val[LANE(i, res)] =                                              \
   1966           static_cast<dst_ctype>(std::max(min, std::min(max, a)));         \
   1967     }                                                                      \
   1968     Push(WasmValue(Simd128(res)));                                         \
   1969     return true;                                                           \
   1970   }
   1971         PACK_CASE(I16x8SConvertI32x4, int4, i32x4, int8, 8, int16_t, int16_t,
   1972                   false)
   1973         PACK_CASE(I16x8UConvertI32x4, int4, i32x4, int8, 8, uint16_t, int16_t,
   1974                   true)
   1975         PACK_CASE(I8x16SConvertI16x8, int8, i16x8, int16, 16, int8_t, int8_t,
   1976                   false)
   1977         PACK_CASE(I8x16UConvertI16x8, int8, i16x8, int16, 16, uint8_t, int8_t,
   1978                   true)
   1979 #undef PACK_CASE
   1980       case kExprS128Select: {
   1981         int4 v2 = Pop().to_s128().to_i32x4();
   1982         int4 v1 = Pop().to_s128().to_i32x4();
   1983         int4 bool_val = Pop().to_s128().to_i32x4();
   1984         int4 res;
   1985         for (size_t i = 0; i < 4; ++i) {
   1986           res.val[i] = v2.val[i] ^ ((v1.val[i] ^ v2.val[i]) & bool_val.val[i]);
   1987         }
   1988         Push(WasmValue(Simd128(res)));
   1989         return true;
   1990       }
   1991 #define ADD_HORIZ_CASE(op, name, stype, count)                   \
   1992   case kExpr##op: {                                              \
   1993     WasmValue v2 = Pop();                                        \
   1994     WasmValue v1 = Pop();                                        \
   1995     stype s1 = v1.to_s128().to_##name();                         \
   1996     stype s2 = v2.to_s128().to_##name();                         \
   1997     stype res;                                                   \
   1998     for (size_t i = 0; i < count / 2; ++i) {                     \
   1999       res.val[LANE(i, s1)] =                                     \
   2000           s1.val[LANE(i * 2, s1)] + s1.val[LANE(i * 2 + 1, s1)]; \
   2001       res.val[LANE(i + count / 2, s1)] =                         \
   2002           s2.val[LANE(i * 2, s1)] + s2.val[LANE(i * 2 + 1, s1)]; \
   2003     }                                                            \
   2004     Push(WasmValue(Simd128(res)));                               \
   2005     return true;                                                 \
   2006   }
   2007         ADD_HORIZ_CASE(I32x4AddHoriz, i32x4, int4, 4)
   2008         ADD_HORIZ_CASE(F32x4AddHoriz, f32x4, float4, 4)
   2009         ADD_HORIZ_CASE(I16x8AddHoriz, i16x8, int8, 8)
   2010 #undef ADD_HORIZ_CASE
   2011       case kExprS8x16Shuffle: {
   2012         Simd8x16ShuffleImmediate<Decoder::kNoValidate> imm(decoder,
   2013                                                            code->at(pc));
   2014         len += 16;
   2015         int16 v2 = Pop().to_s128().to_i8x16();
   2016         int16 v1 = Pop().to_s128().to_i8x16();
   2017         int16 res;
   2018         for (size_t i = 0; i < kSimd128Size; ++i) {
   2019           int lane = imm.shuffle[i];
   2020           res.val[LANE(i, v1)] = lane < kSimd128Size
   2021                                      ? v1.val[LANE(lane, v1)]
   2022                                      : v2.val[LANE(lane - kSimd128Size, v1)];
   2023         }
   2024         Push(WasmValue(Simd128(res)));
   2025         return true;
   2026       }
   2027 #define REDUCTION_CASE(op, name, stype, count, operation) \
   2028   case kExpr##op: {                                       \
   2029     stype s = Pop().to_s128().to_##name();                \
   2030     int32_t res = s.val[0];                               \
   2031     for (size_t i = 1; i < count; ++i) {                  \
   2032       res = res operation static_cast<int32_t>(s.val[i]); \
   2033     }                                                     \
   2034     Push(WasmValue(res));                                 \
   2035     return true;                                          \
   2036   }
   2037         REDUCTION_CASE(S1x4AnyTrue, i32x4, int4, 4, |)
   2038         REDUCTION_CASE(S1x4AllTrue, i32x4, int4, 4, &)
   2039         REDUCTION_CASE(S1x8AnyTrue, i16x8, int8, 8, |)
   2040         REDUCTION_CASE(S1x8AllTrue, i16x8, int8, 8, &)
   2041         REDUCTION_CASE(S1x16AnyTrue, i8x16, int16, 16, |)
   2042         REDUCTION_CASE(S1x16AllTrue, i8x16, int16, 16, &)
   2043 #undef REDUCTION_CASE
   2044       default:
   2045         return false;
   2046     }
   2047   }
   2048 
   2049   // Check if our control stack (frames_) exceeds the limit. Trigger stack
   2050   // overflow if it does, and unwinding the current frame.
   2051   // Returns true if execution can continue, false if the current activation was
   2052   // fully unwound.
   2053   // Do call this function immediately *after* pushing a new frame. The pc of
   2054   // the top frame will be reset to 0 if the stack check fails.
   2055   bool DoStackCheck() V8_WARN_UNUSED_RESULT {
   2056     // The goal of this stack check is not to prevent actual stack overflows,
   2057     // but to simulate stack overflows during the execution of compiled code.
   2058     // That is why this function uses FLAG_stack_size, even though the value
   2059     // stack actually lies in zone memory.
   2060     const size_t stack_size_limit = FLAG_stack_size * KB;
   2061     // Sum up the value stack size and the control stack size.
   2062     const size_t current_stack_size =
   2063         (sp_ - stack_.get()) + frames_.size() * sizeof(Frame);
   2064     if (V8_LIKELY(current_stack_size <= stack_size_limit)) {
   2065       return true;
   2066     }
   2067     // The pc of the top frame is initialized to the first instruction. We reset
   2068     // it to 0 here such that we report the same position as in compiled code.
   2069     frames_.back().pc = 0;
   2070     Isolate* isolate = instance_object_->GetIsolate();
   2071     HandleScope handle_scope(isolate);
   2072     isolate->StackOverflow();
   2073     return HandleException(isolate) == WasmInterpreter::Thread::HANDLED;
   2074   }
   2075 
   2076   void Execute(InterpreterCode* code, pc_t pc, int max) {
   2077     DCHECK_NOT_NULL(code->side_table);
   2078     DCHECK(!frames_.empty());
   2079     // There must be enough space on the stack to hold the arguments, locals,
   2080     // and the value stack.
   2081     DCHECK_LE(code->function->sig->parameter_count() +
   2082                   code->locals.type_list.size() +
   2083                   code->side_table->max_stack_height_,
   2084               stack_limit_ - stack_.get() - frames_.back().sp);
   2085 
   2086     Decoder decoder(code->start, code->end);
   2087     pc_t limit = code->end - code->start;
   2088     bool hit_break = false;
   2089 
   2090     while (true) {
   2091 #define PAUSE_IF_BREAK_FLAG(flag)                                     \
   2092   if (V8_UNLIKELY(break_flags_ & WasmInterpreter::BreakFlag::flag)) { \
   2093     hit_break = true;                                                 \
   2094     max = 0;                                                          \
   2095   }
   2096 
   2097       DCHECK_GT(limit, pc);
   2098       DCHECK_NOT_NULL(code->start);
   2099 
   2100       // Do first check for a breakpoint, in order to set hit_break correctly.
   2101       const char* skip = "        ";
   2102       int len = 1;
   2103       byte orig = code->start[pc];
   2104       WasmOpcode opcode = static_cast<WasmOpcode>(orig);
   2105       if (WasmOpcodes::IsPrefixOpcode(opcode)) {
   2106         opcode = static_cast<WasmOpcode>(opcode << 8 | code->start[pc + 1]);
   2107       }
   2108       if (V8_UNLIKELY(orig == kInternalBreakpoint)) {
   2109         orig = code->orig_start[pc];
   2110         if (WasmOpcodes::IsPrefixOpcode(static_cast<WasmOpcode>(orig))) {
   2111           opcode =
   2112               static_cast<WasmOpcode>(orig << 8 | code->orig_start[pc + 1]);
   2113         }
   2114         if (SkipBreakpoint(code, pc)) {
   2115           // skip breakpoint by switching on original code.
   2116           skip = "[skip]  ";
   2117         } else {
   2118           TRACE("@%-3zu: [break] %-24s:", pc, WasmOpcodes::OpcodeName(opcode));
   2119           TraceValueStack();
   2120           TRACE("\n");
   2121           hit_break = true;
   2122           break;
   2123         }
   2124       }
   2125 
   2126       // If max is 0, break. If max is positive (a limit is set), decrement it.
   2127       if (max == 0) break;
   2128       if (max > 0) --max;
   2129 
   2130       USE(skip);
   2131       TRACE("@%-3zu: %s%-24s:", pc, skip, WasmOpcodes::OpcodeName(opcode));
   2132       TraceValueStack();
   2133       TRACE("\n");
   2134 
   2135 #ifdef DEBUG
   2136       // Compute the stack effect of this opcode, and verify later that the
   2137       // stack was modified accordingly.
   2138       std::pair<uint32_t, uint32_t> stack_effect =
   2139           StackEffect(codemap_->module(), frames_.back().code->function->sig,
   2140                       code->orig_start + pc, code->orig_end);
   2141       sp_t expected_new_stack_height =
   2142           StackHeight() - stack_effect.first + stack_effect.second;
   2143 #endif
   2144 
   2145       switch (orig) {
   2146         case kExprNop:
   2147           break;
   2148         case kExprBlock: {
   2149           BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures,
   2150                                                        &decoder, code->at(pc));
   2151           len = 1 + imm.length;
   2152           break;
   2153         }
   2154         case kExprLoop: {
   2155           BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures,
   2156                                                        &decoder, code->at(pc));
   2157           len = 1 + imm.length;
   2158           break;
   2159         }
   2160         case kExprIf: {
   2161           BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures,
   2162                                                        &decoder, code->at(pc));
   2163           WasmValue cond = Pop();
   2164           bool is_true = cond.to<uint32_t>() != 0;
   2165           if (is_true) {
   2166             // fall through to the true block.
   2167             len = 1 + imm.length;
   2168             TRACE("  true => fallthrough\n");
   2169           } else {
   2170             len = LookupTargetDelta(code, pc);
   2171             TRACE("  false => @%zu\n", pc + len);
   2172           }
   2173           break;
   2174         }
   2175         case kExprElse: {
   2176           len = LookupTargetDelta(code, pc);
   2177           TRACE("  end => @%zu\n", pc + len);
   2178           break;
   2179         }
   2180         case kExprSelect: {
   2181           WasmValue cond = Pop();
   2182           WasmValue fval = Pop();
   2183           WasmValue tval = Pop();
   2184           Push(cond.to<int32_t>() != 0 ? tval : fval);
   2185           break;
   2186         }
   2187         case kExprBr: {
   2188           BreakDepthImmediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
   2189           len = DoBreak(code, pc, imm.depth);
   2190           TRACE("  br => @%zu\n", pc + len);
   2191           break;
   2192         }
   2193         case kExprBrIf: {
   2194           BreakDepthImmediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
   2195           WasmValue cond = Pop();
   2196           bool is_true = cond.to<uint32_t>() != 0;
   2197           if (is_true) {
   2198             len = DoBreak(code, pc, imm.depth);
   2199             TRACE("  br_if => @%zu\n", pc + len);
   2200           } else {
   2201             TRACE("  false => fallthrough\n");
   2202             len = 1 + imm.length;
   2203           }
   2204           break;
   2205         }
   2206         case kExprBrTable: {
   2207           BranchTableImmediate<Decoder::kNoValidate> imm(&decoder,
   2208                                                          code->at(pc));
   2209           BranchTableIterator<Decoder::kNoValidate> iterator(&decoder, imm);
   2210           uint32_t key = Pop().to<uint32_t>();
   2211           uint32_t depth = 0;
   2212           if (key >= imm.table_count) key = imm.table_count;
   2213           for (uint32_t i = 0; i <= key; i++) {
   2214             DCHECK(iterator.has_next());
   2215             depth = iterator.next();
   2216           }
   2217           len = key + DoBreak(code, pc + key, static_cast<size_t>(depth));
   2218           TRACE("  br[%u] => @%zu\n", key, pc + key + len);
   2219           break;
   2220         }
   2221         case kExprReturn: {
   2222           size_t arity = code->function->sig->return_count();
   2223           if (!DoReturn(&decoder, &code, &pc, &limit, arity)) return;
   2224           PAUSE_IF_BREAK_FLAG(AfterReturn);
   2225           continue;
   2226         }
   2227         case kExprUnreachable: {
   2228           return DoTrap(kTrapUnreachable, pc);
   2229         }
   2230         case kExprEnd: {
   2231           break;
   2232         }
   2233         case kExprI32Const: {
   2234           ImmI32Immediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
   2235           Push(WasmValue(imm.value));
   2236           len = 1 + imm.length;
   2237           break;
   2238         }
   2239         case kExprI64Const: {
   2240           ImmI64Immediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
   2241           Push(WasmValue(imm.value));
   2242           len = 1 + imm.length;
   2243           break;
   2244         }
   2245         case kExprF32Const: {
   2246           ImmF32Immediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
   2247           Push(WasmValue(imm.value));
   2248           len = 1 + imm.length;
   2249           break;
   2250         }
   2251         case kExprF64Const: {
   2252           ImmF64Immediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
   2253           Push(WasmValue(imm.value));
   2254           len = 1 + imm.length;
   2255           break;
   2256         }
   2257         case kExprGetLocal: {
   2258           LocalIndexImmediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
   2259           Push(GetStackValue(frames_.back().sp + imm.index));
   2260           len = 1 + imm.length;
   2261           break;
   2262         }
   2263         case kExprSetLocal: {
   2264           LocalIndexImmediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
   2265           WasmValue val = Pop();
   2266           SetStackValue(frames_.back().sp + imm.index, val);
   2267           len = 1 + imm.length;
   2268           break;
   2269         }
   2270         case kExprTeeLocal: {
   2271           LocalIndexImmediate<Decoder::kNoValidate> imm(&decoder, code->at(pc));
   2272           WasmValue val = Pop();
   2273           SetStackValue(frames_.back().sp + imm.index, val);
   2274           Push(val);
   2275           len = 1 + imm.length;
   2276           break;
   2277         }
   2278         case kExprDrop: {
   2279           Pop();
   2280           break;
   2281         }
   2282         case kExprCallFunction: {
   2283           CallFunctionImmediate<Decoder::kNoValidate> imm(&decoder,
   2284                                                           code->at(pc));
   2285           InterpreterCode* target = codemap()->GetCode(imm.index);
   2286           if (target->function->imported) {
   2287             CommitPc(pc);
   2288             ExternalCallResult result =
   2289                 CallImportedFunction(target->function->func_index);
   2290             switch (result.type) {
   2291               case ExternalCallResult::INTERNAL:
   2292                 // The import is a function of this instance. Call it directly.
   2293                 target = result.interpreter_code;
   2294                 DCHECK(!target->function->imported);
   2295                 break;
   2296               case ExternalCallResult::INVALID_FUNC:
   2297               case ExternalCallResult::SIGNATURE_MISMATCH:
   2298                 // Direct calls are checked statically.
   2299                 UNREACHABLE();
   2300               case ExternalCallResult::EXTERNAL_RETURNED:
   2301                 PAUSE_IF_BREAK_FLAG(AfterCall);
   2302                 len = 1 + imm.length;
   2303                 break;
   2304               case ExternalCallResult::EXTERNAL_UNWOUND:
   2305                 return;
   2306             }
   2307             if (result.type != ExternalCallResult::INTERNAL) break;
   2308           }
   2309           // Execute an internal call.
   2310           if (!DoCall(&decoder, target, &pc, &limit)) return;
   2311           code = target;
   2312           PAUSE_IF_BREAK_FLAG(AfterCall);
   2313           continue;  // don't bump pc
   2314         } break;
   2315         case kExprCallIndirect: {
   2316           CallIndirectImmediate<Decoder::kNoValidate> imm(&decoder,
   2317                                                           code->at(pc));
   2318           uint32_t entry_index = Pop().to<uint32_t>();
   2319           // Assume only one table for now.
   2320           DCHECK_LE(module()->tables.size(), 1u);
   2321           CommitPc(pc);  // TODO(wasm): Be more disciplined about committing PC.
   2322           ExternalCallResult result =
   2323               CallIndirectFunction(0, entry_index, imm.sig_index);
   2324           switch (result.type) {
   2325             case ExternalCallResult::INTERNAL:
   2326               // The import is a function of this instance. Call it directly.
   2327               if (!DoCall(&decoder, result.interpreter_code, &pc, &limit))
   2328                 return;
   2329               code = result.interpreter_code;
   2330               PAUSE_IF_BREAK_FLAG(AfterCall);
   2331               continue;  // don't bump pc
   2332             case ExternalCallResult::INVALID_FUNC:
   2333               return DoTrap(kTrapFuncInvalid, pc);
   2334             case ExternalCallResult::SIGNATURE_MISMATCH:
   2335               return DoTrap(kTrapFuncSigMismatch, pc);
   2336             case ExternalCallResult::EXTERNAL_RETURNED:
   2337               PAUSE_IF_BREAK_FLAG(AfterCall);
   2338               len = 1 + imm.length;
   2339               break;
   2340             case ExternalCallResult::EXTERNAL_UNWOUND:
   2341               return;
   2342           }
   2343         } break;
   2344         case kExprGetGlobal: {
   2345           GlobalIndexImmediate<Decoder::kNoValidate> imm(&decoder,
   2346                                                          code->at(pc));
   2347           const WasmGlobal* global = &module()->globals[imm.index];
   2348           byte* ptr = GetGlobalPtr(global);
   2349           WasmValue val;
   2350           switch (global->type) {
   2351 #define CASE_TYPE(wasm, ctype)                                         \
   2352   case kWasm##wasm:                                                    \
   2353     val = WasmValue(                                                   \
   2354         ReadLittleEndianValue<ctype>(reinterpret_cast<Address>(ptr))); \
   2355     break;
   2356             WASM_CTYPES(CASE_TYPE)
   2357 #undef CASE_TYPE
   2358             default:
   2359               UNREACHABLE();
   2360           }
   2361           Push(val);
   2362           len = 1 + imm.length;
   2363           break;
   2364         }
   2365         case kExprSetGlobal: {
   2366           GlobalIndexImmediate<Decoder::kNoValidate> imm(&decoder,
   2367                                                          code->at(pc));
   2368           const WasmGlobal* global = &module()->globals[imm.index];
   2369           byte* ptr = GetGlobalPtr(global);
   2370           WasmValue val = Pop();
   2371           switch (global->type) {
   2372 #define CASE_TYPE(wasm, ctype)                                    \
   2373   case kWasm##wasm:                                               \
   2374     WriteLittleEndianValue<ctype>(reinterpret_cast<Address>(ptr), \
   2375                                   val.to<ctype>());               \
   2376     break;
   2377             WASM_CTYPES(CASE_TYPE)
   2378 #undef CASE_TYPE
   2379             default:
   2380               UNREACHABLE();
   2381           }
   2382           len = 1 + imm.length;
   2383           break;
   2384         }
   2385 
   2386 #define LOAD_CASE(name, ctype, mtype, rep)                      \
   2387   case kExpr##name: {                                           \
   2388     if (!ExecuteLoad<ctype, mtype>(&decoder, code, pc, len,     \
   2389                                    MachineRepresentation::rep)) \
   2390       return;                                                   \
   2391     break;                                                      \
   2392   }
   2393 
   2394           LOAD_CASE(I32LoadMem8S, int32_t, int8_t, kWord8);
   2395           LOAD_CASE(I32LoadMem8U, int32_t, uint8_t, kWord8);
   2396           LOAD_CASE(I32LoadMem16S, int32_t, int16_t, kWord16);
   2397           LOAD_CASE(I32LoadMem16U, int32_t, uint16_t, kWord16);
   2398           LOAD_CASE(I64LoadMem8S, int64_t, int8_t, kWord8);
   2399           LOAD_CASE(I64LoadMem8U, int64_t, uint8_t, kWord16);
   2400           LOAD_CASE(I64LoadMem16S, int64_t, int16_t, kWord16);
   2401           LOAD_CASE(I64LoadMem16U, int64_t, uint16_t, kWord16);
   2402           LOAD_CASE(I64LoadMem32S, int64_t, int32_t, kWord32);
   2403           LOAD_CASE(I64LoadMem32U, int64_t, uint32_t, kWord32);
   2404           LOAD_CASE(I32LoadMem, int32_t, int32_t, kWord32);
   2405           LOAD_CASE(I64LoadMem, int64_t, int64_t, kWord64);
   2406           LOAD_CASE(F32LoadMem, Float32, uint32_t, kFloat32);
   2407           LOAD_CASE(F64LoadMem, Float64, uint64_t, kFloat64);
   2408 #undef LOAD_CASE
   2409 
   2410 #define STORE_CASE(name, ctype, mtype, rep)                      \
   2411   case kExpr##name: {                                            \
   2412     if (!ExecuteStore<ctype, mtype>(&decoder, code, pc, len,     \
   2413                                     MachineRepresentation::rep)) \
   2414       return;                                                    \
   2415     break;                                                       \
   2416   }
   2417 
   2418           STORE_CASE(I32StoreMem8, int32_t, int8_t, kWord8);
   2419           STORE_CASE(I32StoreMem16, int32_t, int16_t, kWord16);
   2420           STORE_CASE(I64StoreMem8, int64_t, int8_t, kWord8);
   2421           STORE_CASE(I64StoreMem16, int64_t, int16_t, kWord16);
   2422           STORE_CASE(I64StoreMem32, int64_t, int32_t, kWord32);
   2423           STORE_CASE(I32StoreMem, int32_t, int32_t, kWord32);
   2424           STORE_CASE(I64StoreMem, int64_t, int64_t, kWord64);
   2425           STORE_CASE(F32StoreMem, Float32, uint32_t, kFloat32);
   2426           STORE_CASE(F64StoreMem, Float64, uint64_t, kFloat64);
   2427 #undef STORE_CASE
   2428 
   2429 #define ASMJS_LOAD_CASE(name, ctype, mtype, defval)                 \
   2430   case kExpr##name: {                                               \
   2431     uint32_t index = Pop().to<uint32_t>();                          \
   2432     ctype result;                                                   \
   2433     Address addr = BoundsCheckMem<mtype>(0, index);                 \
   2434     if (!addr) {                                                    \
   2435       result = defval;                                              \
   2436     } else {                                                        \
   2437       /* TODO(titzer): alignment for asmjs load mem? */             \
   2438       result = static_cast<ctype>(*reinterpret_cast<mtype*>(addr)); \
   2439     }                                                               \
   2440     Push(WasmValue(result));                                        \
   2441     break;                                                          \
   2442   }
   2443           ASMJS_LOAD_CASE(I32AsmjsLoadMem8S, int32_t, int8_t, 0);
   2444           ASMJS_LOAD_CASE(I32AsmjsLoadMem8U, int32_t, uint8_t, 0);
   2445           ASMJS_LOAD_CASE(I32AsmjsLoadMem16S, int32_t, int16_t, 0);
   2446           ASMJS_LOAD_CASE(I32AsmjsLoadMem16U, int32_t, uint16_t, 0);
   2447           ASMJS_LOAD_CASE(I32AsmjsLoadMem, int32_t, int32_t, 0);
   2448           ASMJS_LOAD_CASE(F32AsmjsLoadMem, float, float,
   2449                           std::numeric_limits<float>::quiet_NaN());
   2450           ASMJS_LOAD_CASE(F64AsmjsLoadMem, double, double,
   2451                           std::numeric_limits<double>::quiet_NaN());
   2452 #undef ASMJS_LOAD_CASE
   2453 
   2454 #define ASMJS_STORE_CASE(name, ctype, mtype)                                   \
   2455   case kExpr##name: {                                                          \
   2456     WasmValue val = Pop();                                                     \
   2457     uint32_t index = Pop().to<uint32_t>();                                     \
   2458     Address addr = BoundsCheckMem<mtype>(0, index);                            \
   2459     if (addr) {                                                                \
   2460       *(reinterpret_cast<mtype*>(addr)) = static_cast<mtype>(val.to<ctype>()); \
   2461     }                                                                          \
   2462     Push(val);                                                                 \
   2463     break;                                                                     \
   2464   }
   2465 
   2466           ASMJS_STORE_CASE(I32AsmjsStoreMem8, int32_t, int8_t);
   2467           ASMJS_STORE_CASE(I32AsmjsStoreMem16, int32_t, int16_t);
   2468           ASMJS_STORE_CASE(I32AsmjsStoreMem, int32_t, int32_t);
   2469           ASMJS_STORE_CASE(F32AsmjsStoreMem, float, float);
   2470           ASMJS_STORE_CASE(F64AsmjsStoreMem, double, double);
   2471 #undef ASMJS_STORE_CASE
   2472         case kExprGrowMemory: {
   2473           MemoryIndexImmediate<Decoder::kNoValidate> imm(&decoder,
   2474                                                          code->at(pc));
   2475           uint32_t delta_pages = Pop().to<uint32_t>();
   2476           Handle<WasmMemoryObject> memory(instance_object_->memory_object(),
   2477                                           instance_object_->GetIsolate());
   2478           Isolate* isolate = memory->GetIsolate();
   2479           int32_t result = WasmMemoryObject::Grow(isolate, memory, delta_pages);
   2480           Push(WasmValue(result));
   2481           len = 1 + imm.length;
   2482           // Treat one grow_memory instruction like 1000 other instructions,
   2483           // because it is a really expensive operation.
   2484           if (max > 0) max = std::max(0, max - 1000);
   2485           break;
   2486         }
   2487         case kExprMemorySize: {
   2488           MemoryIndexImmediate<Decoder::kNoValidate> imm(&decoder,
   2489                                                          code->at(pc));
   2490           Push(WasmValue(static_cast<uint32_t>(instance_object_->memory_size() /
   2491                                                kWasmPageSize)));
   2492           len = 1 + imm.length;
   2493           break;
   2494         }
   2495         // We need to treat kExprI32ReinterpretF32 and kExprI64ReinterpretF64
   2496         // specially to guarantee that the quiet bit of a NaN is preserved on
   2497         // ia32 by the reinterpret casts.
   2498         case kExprI32ReinterpretF32: {
   2499           WasmValue val = Pop();
   2500           Push(WasmValue(ExecuteI32ReinterpretF32(val)));
   2501           break;
   2502         }
   2503         case kExprI64ReinterpretF64: {
   2504           WasmValue val = Pop();
   2505           Push(WasmValue(ExecuteI64ReinterpretF64(val)));
   2506           break;
   2507         }
   2508 #define SIGN_EXTENSION_CASE(name, wtype, ntype)        \
   2509   case kExpr##name: {                                  \
   2510     ntype val = static_cast<ntype>(Pop().to<wtype>()); \
   2511     Push(WasmValue(static_cast<wtype>(val)));          \
   2512     break;                                             \
   2513   }
   2514           SIGN_EXTENSION_CASE(I32SExtendI8, int32_t, int8_t);
   2515           SIGN_EXTENSION_CASE(I32SExtendI16, int32_t, int16_t);
   2516           SIGN_EXTENSION_CASE(I64SExtendI8, int64_t, int8_t);
   2517           SIGN_EXTENSION_CASE(I64SExtendI16, int64_t, int16_t);
   2518           SIGN_EXTENSION_CASE(I64SExtendI32, int64_t, int32_t);
   2519 #undef SIGN_EXTENSION_CASE
   2520         case kNumericPrefix: {
   2521           ++len;
   2522           if (!ExecuteNumericOp(opcode, &decoder, code, pc, len)) return;
   2523           break;
   2524         }
   2525         case kAtomicPrefix: {
   2526           if (!ExecuteAtomicOp(opcode, &decoder, code, pc, len)) return;
   2527           break;
   2528         }
   2529         case kSimdPrefix: {
   2530           ++len;
   2531           if (!ExecuteSimdOp(opcode, &decoder, code, pc, len)) return;
   2532           break;
   2533         }
   2534 
   2535 #define EXECUTE_SIMPLE_BINOP(name, ctype, op)               \
   2536   case kExpr##name: {                                       \
   2537     WasmValue rval = Pop();                                 \
   2538     WasmValue lval = Pop();                                 \
   2539     auto result = lval.to<ctype>() op rval.to<ctype>();     \
   2540     possible_nondeterminism_ |= has_nondeterminism(result); \
   2541     Push(WasmValue(result));                                \
   2542     break;                                                  \
   2543   }
   2544           FOREACH_SIMPLE_BINOP(EXECUTE_SIMPLE_BINOP)
   2545 #undef EXECUTE_SIMPLE_BINOP
   2546 
   2547 #define EXECUTE_OTHER_BINOP(name, ctype)                    \
   2548   case kExpr##name: {                                       \
   2549     TrapReason trap = kTrapCount;                           \
   2550     ctype rval = Pop().to<ctype>();                         \
   2551     ctype lval = Pop().to<ctype>();                         \
   2552     auto result = Execute##name(lval, rval, &trap);         \
   2553     possible_nondeterminism_ |= has_nondeterminism(result); \
   2554     if (trap != kTrapCount) return DoTrap(trap, pc);        \
   2555     Push(WasmValue(result));                                \
   2556     break;                                                  \
   2557   }
   2558           FOREACH_OTHER_BINOP(EXECUTE_OTHER_BINOP)
   2559 #undef EXECUTE_OTHER_BINOP
   2560 
   2561 #define EXECUTE_UNOP(name, ctype, exec_fn)                  \
   2562   case kExpr##name: {                                       \
   2563     TrapReason trap = kTrapCount;                           \
   2564     ctype val = Pop().to<ctype>();                          \
   2565     auto result = exec_fn(val, &trap);                      \
   2566     possible_nondeterminism_ |= has_nondeterminism(result); \
   2567     if (trap != kTrapCount) return DoTrap(trap, pc);        \
   2568     Push(WasmValue(result));                                \
   2569     break;                                                  \
   2570   }
   2571 
   2572 #define EXECUTE_OTHER_UNOP(name, ctype) EXECUTE_UNOP(name, ctype, Execute##name)
   2573           FOREACH_OTHER_UNOP(EXECUTE_OTHER_UNOP)
   2574 #undef EXECUTE_OTHER_UNOP
   2575 
   2576 #define EXECUTE_I32CONV_FLOATOP(name, out_type, in_type) \
   2577   EXECUTE_UNOP(name, in_type, ExecuteConvert<out_type>)
   2578           FOREACH_I32CONV_FLOATOP(EXECUTE_I32CONV_FLOATOP)
   2579 #undef EXECUTE_I32CONV_FLOATOP
   2580 #undef EXECUTE_UNOP
   2581 
   2582         default:
   2583           FATAL("Unknown or unimplemented opcode #%d:%s", code->start[pc],
   2584                 OpcodeName(code->start[pc]));
   2585           UNREACHABLE();
   2586       }
   2587 
   2588 #ifdef DEBUG
   2589       if (!WasmOpcodes::IsControlOpcode(opcode)) {
   2590         DCHECK_EQ(expected_new_stack_height, StackHeight());
   2591       }
   2592 #endif
   2593 
   2594       pc += len;
   2595       if (pc == limit) {
   2596         // Fell off end of code; do an implicit return.
   2597         TRACE("@%-3zu: ImplicitReturn\n", pc);
   2598         if (!DoReturn(&decoder, &code, &pc, &limit,
   2599                       code->function->sig->return_count()))
   2600           return;
   2601         PAUSE_IF_BREAK_FLAG(AfterReturn);
   2602       }
   2603 #undef PAUSE_IF_BREAK_FLAG
   2604     }
   2605 
   2606     state_ = WasmInterpreter::PAUSED;
   2607     break_pc_ = hit_break ? pc : kInvalidPc;
   2608     CommitPc(pc);
   2609   }
   2610 
   2611   WasmValue Pop() {
   2612     DCHECK_GT(frames_.size(), 0);
   2613     DCHECK_GT(StackHeight(), frames_.back().llimit());  // can't pop into locals
   2614     return *--sp_;
   2615   }
   2616 
   2617   void PopN(int n) {
   2618     DCHECK_GE(StackHeight(), n);
   2619     DCHECK_GT(frames_.size(), 0);
   2620     // Check that we don't pop into locals.
   2621     DCHECK_GE(StackHeight() - n, frames_.back().llimit());
   2622     sp_ -= n;
   2623   }
   2624 
   2625   WasmValue PopArity(size_t arity) {
   2626     if (arity == 0) return WasmValue();
   2627     CHECK_EQ(1, arity);
   2628     return Pop();
   2629   }
   2630 
   2631   void Push(WasmValue val) {
   2632     DCHECK_NE(kWasmStmt, val.type());
   2633     DCHECK_LE(1, stack_limit_ - sp_);
   2634     *sp_++ = val;
   2635   }
   2636 
   2637   void Push(WasmValue* vals, size_t arity) {
   2638     DCHECK_LE(arity, stack_limit_ - sp_);
   2639     for (WasmValue *val = vals, *end = vals + arity; val != end; ++val) {
   2640       DCHECK_NE(kWasmStmt, val->type());
   2641     }
   2642     memcpy(sp_, vals, arity * sizeof(*sp_));
   2643     sp_ += arity;
   2644   }
   2645 
   2646   void EnsureStackSpace(size_t size) {
   2647     if (V8_LIKELY(static_cast<size_t>(stack_limit_ - sp_) >= size)) return;
   2648     size_t old_size = stack_limit_ - stack_.get();
   2649     size_t requested_size =
   2650         base::bits::RoundUpToPowerOfTwo64((sp_ - stack_.get()) + size);
   2651     size_t new_size = Max(size_t{8}, Max(2 * old_size, requested_size));
   2652     std::unique_ptr<WasmValue[]> new_stack(new WasmValue[new_size]);
   2653     memcpy(new_stack.get(), stack_.get(), old_size * sizeof(*sp_));
   2654     sp_ = new_stack.get() + (sp_ - stack_.get());
   2655     stack_ = std::move(new_stack);
   2656     stack_limit_ = stack_.get() + new_size;
   2657   }
   2658 
   2659   sp_t StackHeight() { return sp_ - stack_.get(); }
   2660 
   2661   void TraceValueStack() {
   2662 #ifdef DEBUG
   2663     if (!FLAG_trace_wasm_interpreter) return;
   2664     Frame* top = frames_.size() > 0 ? &frames_.back() : nullptr;
   2665     sp_t sp = top ? top->sp : 0;
   2666     sp_t plimit = top ? top->plimit() : 0;
   2667     sp_t llimit = top ? top->llimit() : 0;
   2668     for (size_t i = sp; i < StackHeight(); ++i) {
   2669       if (i < plimit)
   2670         PrintF(" p%zu:", i);
   2671       else if (i < llimit)
   2672         PrintF(" l%zu:", i);
   2673       else
   2674         PrintF(" s%zu:", i);
   2675       WasmValue val = GetStackValue(i);
   2676       switch (val.type()) {
   2677         case kWasmI32:
   2678           PrintF("i32:%d", val.to<int32_t>());
   2679           break;
   2680         case kWasmI64:
   2681           PrintF("i64:%" PRId64 "", val.to<int64_t>());
   2682           break;
   2683         case kWasmF32:
   2684           PrintF("f32:%f", val.to<float>());
   2685           break;
   2686         case kWasmF64:
   2687           PrintF("f64:%lf", val.to<double>());
   2688           break;
   2689         case kWasmStmt:
   2690           PrintF("void");
   2691           break;
   2692         default:
   2693           UNREACHABLE();
   2694           break;
   2695       }
   2696     }
   2697 #endif  // DEBUG
   2698   }
   2699 
   2700   ExternalCallResult TryHandleException(Isolate* isolate) {
   2701     if (HandleException(isolate) == WasmInterpreter::Thread::UNWOUND) {
   2702       return {ExternalCallResult::EXTERNAL_UNWOUND};
   2703     }
   2704     return {ExternalCallResult::EXTERNAL_RETURNED};
   2705   }
   2706 
   2707   ExternalCallResult CallExternalWasmFunction(
   2708       Isolate* isolate, Handle<WasmInstanceObject> instance,
   2709       const WasmCode* code, FunctionSig* sig) {
   2710     if (code->kind() == WasmCode::kWasmToJsWrapper &&
   2711         !IsJSCompatibleSignature(sig)) {
   2712       isolate->Throw(*isolate->factory()->NewTypeError(
   2713           MessageTemplate::kWasmTrapTypeError));
   2714       return TryHandleException(isolate);
   2715     }
   2716 
   2717     Handle<WasmDebugInfo> debug_info(instance_object_->debug_info(), isolate);
   2718     Handle<JSFunction> wasm_entry =
   2719         WasmDebugInfo::GetCWasmEntry(debug_info, sig);
   2720 
   2721     TRACE("  => Calling external wasm function\n");
   2722 
   2723     // Copy the arguments to one buffer.
   2724     // TODO(clemensh): Introduce a helper for all argument buffer
   2725     // con-/destruction.
   2726     int num_args = static_cast<int>(sig->parameter_count());
   2727     std::vector<uint8_t> arg_buffer(num_args * 8);
   2728     size_t offset = 0;
   2729     WasmValue* wasm_args = sp_ - num_args;
   2730     for (int i = 0; i < num_args; ++i) {
   2731       int param_size = ValueTypes::ElementSizeInBytes(sig->GetParam(i));
   2732       if (arg_buffer.size() < offset + param_size) {
   2733         arg_buffer.resize(std::max(2 * arg_buffer.size(), offset + param_size));
   2734       }
   2735       Address address = reinterpret_cast<Address>(arg_buffer.data()) + offset;
   2736       switch (sig->GetParam(i)) {
   2737         case kWasmI32:
   2738           WriteUnalignedValue(address, wasm_args[i].to<uint32_t>());
   2739           break;
   2740         case kWasmI64:
   2741           WriteUnalignedValue(address, wasm_args[i].to<uint64_t>());
   2742           break;
   2743         case kWasmF32:
   2744           WriteUnalignedValue(address, wasm_args[i].to<float>());
   2745           break;
   2746         case kWasmF64:
   2747           WriteUnalignedValue(address, wasm_args[i].to<double>());
   2748           break;
   2749         default:
   2750           UNIMPLEMENTED();
   2751       }
   2752       offset += param_size;
   2753     }
   2754 
   2755     // Ensure that there is enough space in the arg_buffer to hold the return
   2756     // value(s).
   2757     size_t return_size = 0;
   2758     for (ValueType t : sig->returns()) {
   2759       return_size += ValueTypes::ElementSizeInBytes(t);
   2760     }
   2761     if (arg_buffer.size() < return_size) {
   2762       arg_buffer.resize(return_size);
   2763     }
   2764 
   2765     // Wrap the arg_buffer data pointer in a handle. As
   2766     // this is an aligned pointer, to the GC it will look like a Smi.
   2767     Handle<Object> arg_buffer_obj(reinterpret_cast<Object*>(arg_buffer.data()),
   2768                                   isolate);
   2769     DCHECK(!arg_buffer_obj->IsHeapObject());
   2770 
   2771     static_assert(compiler::CWasmEntryParameters::kNumParameters == 3,
   2772                   "code below needs adaption");
   2773     Handle<Object> args[compiler::CWasmEntryParameters::kNumParameters];
   2774     args[compiler::CWasmEntryParameters::kCodeObject] = Handle<Object>::cast(
   2775         isolate->factory()->NewForeign(code->instruction_start(), TENURED));
   2776     args[compiler::CWasmEntryParameters::kWasmInstance] = instance;
   2777     args[compiler::CWasmEntryParameters::kArgumentsBuffer] = arg_buffer_obj;
   2778 
   2779     Handle<Object> receiver = isolate->factory()->undefined_value();
   2780     trap_handler::SetThreadInWasm();
   2781     MaybeHandle<Object> maybe_retval =
   2782         Execution::Call(isolate, wasm_entry, receiver, arraysize(args), args);
   2783     TRACE("  => External wasm function returned%s\n",
   2784           maybe_retval.is_null() ? " with exception" : "");
   2785 
   2786     if (maybe_retval.is_null()) {
   2787       // JSEntryStub may through a stack overflow before we actually get to wasm
   2788       // code or back to the interpreter, meaning the thread-in-wasm flag won't
   2789       // be cleared.
   2790       if (trap_handler::IsThreadInWasm()) {
   2791         trap_handler::ClearThreadInWasm();
   2792       }
   2793       return TryHandleException(isolate);
   2794     }
   2795 
   2796     trap_handler::ClearThreadInWasm();
   2797 
   2798     // Pop arguments off the stack.
   2799     sp_ -= num_args;
   2800     // Push return values.
   2801     if (sig->return_count() > 0) {
   2802       // TODO(wasm): Handle multiple returns.
   2803       DCHECK_EQ(1, sig->return_count());
   2804       Address address = reinterpret_cast<Address>(arg_buffer.data());
   2805       switch (sig->GetReturn()) {
   2806         case kWasmI32:
   2807           Push(WasmValue(ReadUnalignedValue<uint32_t>(address)));
   2808           break;
   2809         case kWasmI64:
   2810           Push(WasmValue(ReadUnalignedValue<uint64_t>(address)));
   2811           break;
   2812         case kWasmF32:
   2813           Push(WasmValue(ReadUnalignedValue<float>(address)));
   2814           break;
   2815         case kWasmF64:
   2816           Push(WasmValue(ReadUnalignedValue<double>(address)));
   2817           break;
   2818         default:
   2819           UNIMPLEMENTED();
   2820       }
   2821     }
   2822     return {ExternalCallResult::EXTERNAL_RETURNED};
   2823   }
   2824 
   2825   static WasmCode* GetTargetCode(WasmCodeManager* code_manager,
   2826                                  Address target) {
   2827     NativeModule* native_module = code_manager->LookupNativeModule(target);
   2828     if (native_module->is_jump_table_slot(target)) {
   2829       uint32_t func_index =
   2830           native_module->GetFunctionIndexFromJumpTableSlot(target);
   2831       return native_module->code(func_index);
   2832     }
   2833     WasmCode* code = native_module->Lookup(target);
   2834     DCHECK_EQ(code->instruction_start(), target);
   2835     return code;
   2836   }
   2837 
   2838   ExternalCallResult CallImportedFunction(uint32_t function_index) {
   2839     // Use a new HandleScope to avoid leaking / accumulating handles in the
   2840     // outer scope.
   2841     Isolate* isolate = instance_object_->GetIsolate();
   2842     HandleScope handle_scope(isolate);
   2843 
   2844     DCHECK_GT(module()->num_imported_functions, function_index);
   2845     Handle<WasmInstanceObject> instance;
   2846     ImportedFunctionEntry entry(instance_object_, function_index);
   2847     instance = handle(entry.instance(), isolate);
   2848     WasmCode* code =
   2849         GetTargetCode(isolate->wasm_engine()->code_manager(), entry.target());
   2850     FunctionSig* sig = codemap()->module()->functions[function_index].sig;
   2851     return CallExternalWasmFunction(isolate, instance, code, sig);
   2852   }
   2853 
   2854   ExternalCallResult CallIndirectFunction(uint32_t table_index,
   2855                                           uint32_t entry_index,
   2856                                           uint32_t sig_index) {
   2857     if (codemap()->call_indirect_through_module()) {
   2858       // Rely on the information stored in the WasmModule.
   2859       InterpreterCode* code =
   2860           codemap()->GetIndirectCode(table_index, entry_index);
   2861       if (!code) return {ExternalCallResult::INVALID_FUNC};
   2862       if (code->function->sig_index != sig_index) {
   2863         // If not an exact match, we have to do a canonical check.
   2864         int function_canonical_id =
   2865             module()->signature_ids[code->function->sig_index];
   2866         int expected_canonical_id = module()->signature_ids[sig_index];
   2867         DCHECK_EQ(function_canonical_id,
   2868                   module()->signature_map.Find(*code->function->sig));
   2869         if (function_canonical_id != expected_canonical_id) {
   2870           return {ExternalCallResult::SIGNATURE_MISMATCH};
   2871         }
   2872       }
   2873       return {ExternalCallResult::INTERNAL, code};
   2874     }
   2875 
   2876     Isolate* isolate = instance_object_->GetIsolate();
   2877     uint32_t expected_sig_id = module()->signature_ids[sig_index];
   2878     DCHECK_EQ(expected_sig_id,
   2879               module()->signature_map.Find(*module()->signatures[sig_index]));
   2880 
   2881     // The function table is stored in the instance.
   2882     // TODO(wasm): the wasm interpreter currently supports only one table.
   2883     CHECK_EQ(0, table_index);
   2884     // Bounds check against table size.
   2885     if (entry_index >= instance_object_->indirect_function_table_size()) {
   2886       return {ExternalCallResult::INVALID_FUNC};
   2887     }
   2888 
   2889     IndirectFunctionTableEntry entry(instance_object_, entry_index);
   2890     // Signature check.
   2891     if (entry.sig_id() != static_cast<int32_t>(expected_sig_id)) {
   2892       return {ExternalCallResult::SIGNATURE_MISMATCH};
   2893     }
   2894 
   2895     Handle<WasmInstanceObject> instance = handle(entry.instance(), isolate);
   2896     WasmCode* code =
   2897         GetTargetCode(isolate->wasm_engine()->code_manager(), entry.target());
   2898 
   2899     // Call either an internal or external WASM function.
   2900     HandleScope scope(isolate);
   2901     FunctionSig* signature = module()->signatures[sig_index];
   2902 
   2903     if (code->kind() == WasmCode::kFunction) {
   2904       if (!instance_object_.is_identical_to(instance)) {
   2905         // Cross instance call.
   2906         return CallExternalWasmFunction(isolate, instance, code, signature);
   2907       }
   2908       return {ExternalCallResult::INTERNAL, codemap()->GetCode(code->index())};
   2909     }
   2910 
   2911     // Call to external function.
   2912     if (code->kind() == WasmCode::kInterpreterEntry ||
   2913         code->kind() == WasmCode::kWasmToJsWrapper) {
   2914       return CallExternalWasmFunction(isolate, instance, code, signature);
   2915     }
   2916     return {ExternalCallResult::INVALID_FUNC};
   2917   }
   2918 
   2919   inline Activation current_activation() {
   2920     return activations_.empty() ? Activation(0, 0) : activations_.back();
   2921   }
   2922 };
   2923 
   2924 class InterpretedFrameImpl {
   2925  public:
   2926   InterpretedFrameImpl(ThreadImpl* thread, int index)
   2927       : thread_(thread), index_(index) {
   2928     DCHECK_LE(0, index);
   2929   }
   2930 
   2931   const WasmFunction* function() const { return frame()->code->function; }
   2932 
   2933   int pc() const {
   2934     DCHECK_LE(0, frame()->pc);
   2935     DCHECK_GE(kMaxInt, frame()->pc);
   2936     return static_cast<int>(frame()->pc);
   2937   }
   2938 
   2939   int GetParameterCount() const {
   2940     DCHECK_GE(kMaxInt, function()->sig->parameter_count());
   2941     return static_cast<int>(function()->sig->parameter_count());
   2942   }
   2943 
   2944   int GetLocalCount() const {
   2945     size_t num_locals = function()->sig->parameter_count() +
   2946                         frame()->code->locals.type_list.size();
   2947     DCHECK_GE(kMaxInt, num_locals);
   2948     return static_cast<int>(num_locals);
   2949   }
   2950 
   2951   int GetStackHeight() const {
   2952     bool is_top_frame =
   2953         static_cast<size_t>(index_) + 1 == thread_->frames_.size();
   2954     size_t stack_limit =
   2955         is_top_frame ? thread_->StackHeight() : thread_->frames_[index_ + 1].sp;
   2956     DCHECK_LE(frame()->sp, stack_limit);
   2957     size_t frame_size = stack_limit - frame()->sp;
   2958     DCHECK_LE(GetLocalCount(), frame_size);
   2959     return static_cast<int>(frame_size) - GetLocalCount();
   2960   }
   2961 
   2962   WasmValue GetLocalValue(int index) const {
   2963     DCHECK_LE(0, index);
   2964     DCHECK_GT(GetLocalCount(), index);
   2965     return thread_->GetStackValue(static_cast<int>(frame()->sp) + index);
   2966   }
   2967 
   2968   WasmValue GetStackValue(int index) const {
   2969     DCHECK_LE(0, index);
   2970     // Index must be within the number of stack values of this frame.
   2971     DCHECK_GT(GetStackHeight(), index);
   2972     return thread_->GetStackValue(static_cast<int>(frame()->sp) +
   2973                                   GetLocalCount() + index);
   2974   }
   2975 
   2976  private:
   2977   ThreadImpl* thread_;
   2978   int index_;
   2979 
   2980   ThreadImpl::Frame* frame() const {
   2981     DCHECK_GT(thread_->frames_.size(), index_);
   2982     return &thread_->frames_[index_];
   2983   }
   2984 };
   2985 
   2986 // Converters between WasmInterpreter::Thread and WasmInterpreter::ThreadImpl.
   2987 // Thread* is the public interface, without knowledge of the object layout.
   2988 // This cast is potentially risky, but as long as we always cast it back before
   2989 // accessing any data, it should be fine. UBSan is not complaining.
   2990 WasmInterpreter::Thread* ToThread(ThreadImpl* impl) {
   2991   return reinterpret_cast<WasmInterpreter::Thread*>(impl);
   2992 }
   2993 ThreadImpl* ToImpl(WasmInterpreter::Thread* thread) {
   2994   return reinterpret_cast<ThreadImpl*>(thread);
   2995 }
   2996 
   2997 // Same conversion for InterpretedFrame and InterpretedFrameImpl.
   2998 InterpretedFrame* ToFrame(InterpretedFrameImpl* impl) {
   2999   return reinterpret_cast<InterpretedFrame*>(impl);
   3000 }
   3001 const InterpretedFrameImpl* ToImpl(const InterpretedFrame* frame) {
   3002   return reinterpret_cast<const InterpretedFrameImpl*>(frame);
   3003 }
   3004 
   3005 }  // namespace
   3006 
   3007 //============================================================================
   3008 // Implementation of the pimpl idiom for WasmInterpreter::Thread.
   3009 // Instead of placing a pointer to the ThreadImpl inside of the Thread object,
   3010 // we just reinterpret_cast them. ThreadImpls are only allocated inside this
   3011 // translation unit anyway.
   3012 //============================================================================
   3013 WasmInterpreter::State WasmInterpreter::Thread::state() {
   3014   return ToImpl(this)->state();
   3015 }
   3016 void WasmInterpreter::Thread::InitFrame(const WasmFunction* function,
   3017                                         WasmValue* args) {
   3018   ToImpl(this)->InitFrame(function, args);
   3019 }
   3020 WasmInterpreter::State WasmInterpreter::Thread::Run(int num_steps) {
   3021   return ToImpl(this)->Run(num_steps);
   3022 }
   3023 void WasmInterpreter::Thread::Pause() { return ToImpl(this)->Pause(); }
   3024 void WasmInterpreter::Thread::Reset() { return ToImpl(this)->Reset(); }
   3025 WasmInterpreter::Thread::ExceptionHandlingResult
   3026 WasmInterpreter::Thread::HandleException(Isolate* isolate) {
   3027   return ToImpl(this)->HandleException(isolate);
   3028 }
   3029 pc_t WasmInterpreter::Thread::GetBreakpointPc() {
   3030   return ToImpl(this)->GetBreakpointPc();
   3031 }
   3032 int WasmInterpreter::Thread::GetFrameCount() {
   3033   return ToImpl(this)->GetFrameCount();
   3034 }
   3035 WasmInterpreter::FramePtr WasmInterpreter::Thread::GetFrame(int index) {
   3036   DCHECK_LE(0, index);
   3037   DCHECK_GT(GetFrameCount(), index);
   3038   return FramePtr(ToFrame(new InterpretedFrameImpl(ToImpl(this), index)));
   3039 }
   3040 WasmValue WasmInterpreter::Thread::GetReturnValue(int index) {
   3041   return ToImpl(this)->GetReturnValue(index);
   3042 }
   3043 TrapReason WasmInterpreter::Thread::GetTrapReason() {
   3044   return ToImpl(this)->GetTrapReason();
   3045 }
   3046 bool WasmInterpreter::Thread::PossibleNondeterminism() {
   3047   return ToImpl(this)->PossibleNondeterminism();
   3048 }
   3049 uint64_t WasmInterpreter::Thread::NumInterpretedCalls() {
   3050   return ToImpl(this)->NumInterpretedCalls();
   3051 }
   3052 void WasmInterpreter::Thread::AddBreakFlags(uint8_t flags) {
   3053   ToImpl(this)->AddBreakFlags(flags);
   3054 }
   3055 void WasmInterpreter::Thread::ClearBreakFlags() {
   3056   ToImpl(this)->ClearBreakFlags();
   3057 }
   3058 uint32_t WasmInterpreter::Thread::NumActivations() {
   3059   return ToImpl(this)->NumActivations();
   3060 }
   3061 uint32_t WasmInterpreter::Thread::StartActivation() {
   3062   return ToImpl(this)->StartActivation();
   3063 }
   3064 void WasmInterpreter::Thread::FinishActivation(uint32_t id) {
   3065   ToImpl(this)->FinishActivation(id);
   3066 }
   3067 uint32_t WasmInterpreter::Thread::ActivationFrameBase(uint32_t id) {
   3068   return ToImpl(this)->ActivationFrameBase(id);
   3069 }
   3070 
   3071 //============================================================================
   3072 // The implementation details of the interpreter.
   3073 //============================================================================
   3074 class WasmInterpreterInternals : public ZoneObject {
   3075  public:
   3076   // Create a copy of the module bytes for the interpreter, since the passed
   3077   // pointer might be invalidated after constructing the interpreter.
   3078   const ZoneVector<uint8_t> module_bytes_;
   3079   CodeMap codemap_;
   3080   ZoneVector<ThreadImpl> threads_;
   3081 
   3082   WasmInterpreterInternals(Zone* zone, const WasmModule* module,
   3083                            const ModuleWireBytes& wire_bytes,
   3084                            Handle<WasmInstanceObject> instance_object)
   3085       : module_bytes_(wire_bytes.start(), wire_bytes.end(), zone),
   3086         codemap_(module, module_bytes_.data(), zone),
   3087         threads_(zone) {
   3088     threads_.emplace_back(zone, &codemap_, instance_object);
   3089   }
   3090 };
   3091 
   3092 namespace {
   3093 // TODO(wasm): a finalizer is only required to delete the global handle.
   3094 void GlobalHandleDeleter(const v8::WeakCallbackInfo<void>& data) {
   3095   GlobalHandles::Destroy(reinterpret_cast<Object**>(
   3096       reinterpret_cast<JSObject**>(data.GetParameter())));
   3097 }
   3098 
   3099 Handle<WasmInstanceObject> MakeWeak(
   3100     Isolate* isolate, Handle<WasmInstanceObject> instance_object) {
   3101   Handle<Object> handle = isolate->global_handles()->Create(*instance_object);
   3102   // TODO(wasm): use a phantom handle in the WasmInterpreter.
   3103   GlobalHandles::MakeWeak(handle.location(), handle.location(),
   3104                           &GlobalHandleDeleter,
   3105                           v8::WeakCallbackType::kFinalizer);
   3106   return Handle<WasmInstanceObject>::cast(handle);
   3107 }
   3108 }  // namespace
   3109 
   3110 //============================================================================
   3111 // Implementation of the public interface of the interpreter.
   3112 //============================================================================
   3113 WasmInterpreter::WasmInterpreter(Isolate* isolate, const WasmModule* module,
   3114                                  const ModuleWireBytes& wire_bytes,
   3115                                  Handle<WasmInstanceObject> instance_object)
   3116     : zone_(isolate->allocator(), ZONE_NAME),
   3117       internals_(new (&zone_) WasmInterpreterInternals(
   3118           &zone_, module, wire_bytes, MakeWeak(isolate, instance_object))) {}
   3119 
   3120 WasmInterpreter::~WasmInterpreter() { internals_->~WasmInterpreterInternals(); }
   3121 
   3122 void WasmInterpreter::Run() { internals_->threads_[0].Run(); }
   3123 
   3124 void WasmInterpreter::Pause() { internals_->threads_[0].Pause(); }
   3125 
   3126 bool WasmInterpreter::SetBreakpoint(const WasmFunction* function, pc_t pc,
   3127                                     bool enabled) {
   3128   InterpreterCode* code = internals_->codemap_.GetCode(function);
   3129   size_t size = static_cast<size_t>(code->end - code->start);
   3130   // Check bounds for {pc}.
   3131   if (pc < code->locals.encoded_size || pc >= size) return false;
   3132   // Make a copy of the code before enabling a breakpoint.
   3133   if (enabled && code->orig_start == code->start) {
   3134     code->start = reinterpret_cast<byte*>(zone_.New(size));
   3135     memcpy(code->start, code->orig_start, size);
   3136     code->end = code->start + size;
   3137   }
   3138   bool prev = code->start[pc] == kInternalBreakpoint;
   3139   if (enabled) {
   3140     code->start[pc] = kInternalBreakpoint;
   3141   } else {
   3142     code->start[pc] = code->orig_start[pc];
   3143   }
   3144   return prev;
   3145 }
   3146 
   3147 bool WasmInterpreter::GetBreakpoint(const WasmFunction* function, pc_t pc) {
   3148   InterpreterCode* code = internals_->codemap_.GetCode(function);
   3149   size_t size = static_cast<size_t>(code->end - code->start);
   3150   // Check bounds for {pc}.
   3151   if (pc < code->locals.encoded_size || pc >= size) return false;
   3152   // Check if a breakpoint is present at that place in the code.
   3153   return code->start[pc] == kInternalBreakpoint;
   3154 }
   3155 
   3156 bool WasmInterpreter::SetTracing(const WasmFunction* function, bool enabled) {
   3157   UNIMPLEMENTED();
   3158   return false;
   3159 }
   3160 
   3161 int WasmInterpreter::GetThreadCount() {
   3162   return 1;  // only one thread for now.
   3163 }
   3164 
   3165 WasmInterpreter::Thread* WasmInterpreter::GetThread(int id) {
   3166   CHECK_EQ(0, id);  // only one thread for now.
   3167   return ToThread(&internals_->threads_[id]);
   3168 }
   3169 
   3170 void WasmInterpreter::AddFunctionForTesting(const WasmFunction* function) {
   3171   internals_->codemap_.AddFunction(function, nullptr, nullptr);
   3172 }
   3173 
   3174 void WasmInterpreter::SetFunctionCodeForTesting(const WasmFunction* function,
   3175                                                 const byte* start,
   3176                                                 const byte* end) {
   3177   internals_->codemap_.SetFunctionCode(function, start, end);
   3178 }
   3179 
   3180 void WasmInterpreter::SetCallIndirectTestMode() {
   3181   internals_->codemap_.set_call_indirect_through_module(true);
   3182 }
   3183 
   3184 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting(
   3185     Zone* zone, const WasmModule* module, const byte* start, const byte* end) {
   3186   // Create some dummy structures, to avoid special-casing the implementation
   3187   // just for testing.
   3188   FunctionSig sig(0, 0, nullptr);
   3189   WasmFunction function{&sig, 0, 0, {0, 0}, false, false};
   3190   InterpreterCode code{
   3191       &function, BodyLocalDecls(zone), start, end, nullptr, nullptr, nullptr};
   3192 
   3193   // Now compute and return the control transfers.
   3194   SideTable side_table(zone, module, &code);
   3195   return side_table.map_;
   3196 }
   3197 
   3198 //============================================================================
   3199 // Implementation of the frame inspection interface.
   3200 //============================================================================
   3201 const WasmFunction* InterpretedFrame::function() const {
   3202   return ToImpl(this)->function();
   3203 }
   3204 int InterpretedFrame::pc() const { return ToImpl(this)->pc(); }
   3205 int InterpretedFrame::GetParameterCount() const {
   3206   return ToImpl(this)->GetParameterCount();
   3207 }
   3208 int InterpretedFrame::GetLocalCount() const {
   3209   return ToImpl(this)->GetLocalCount();
   3210 }
   3211 int InterpretedFrame::GetStackHeight() const {
   3212   return ToImpl(this)->GetStackHeight();
   3213 }
   3214 WasmValue InterpretedFrame::GetLocalValue(int index) const {
   3215   return ToImpl(this)->GetLocalValue(index);
   3216 }
   3217 WasmValue InterpretedFrame::GetStackValue(int index) const {
   3218   return ToImpl(this)->GetStackValue(index);
   3219 }
   3220 void InterpretedFrameDeleter::operator()(InterpretedFrame* ptr) {
   3221   delete ToImpl(ptr);
   3222 }
   3223 
   3224 #undef TRACE
   3225 #undef LANE
   3226 #undef FOREACH_INTERNAL_OPCODE
   3227 #undef WASM_CTYPES
   3228 #undef FOREACH_SIMPLE_BINOP
   3229 #undef FOREACH_OTHER_BINOP
   3230 #undef FOREACH_I32CONV_FLOATOP
   3231 #undef FOREACH_OTHER_UNOP
   3232 
   3233 }  // namespace wasm
   3234 }  // namespace internal
   3235 }  // namespace v8
   3236