LCOV - code coverage report
Current view: top level - src/wasm - wasm-interpreter.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 974 1042 93.5 %
Date: 2019-01-20 Functions: 120 136 88.2 %

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

Generated by: LCOV version 1.10