LCOV - code coverage report
Current view: top level - src/wasm - function-body-decoder-impl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 991 1046 94.7 %
Date: 2019-04-17 Functions: 146 180 81.1 %

          Line data    Source code
       1             : // Copyright 2017 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             : #ifndef V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
       6             : #define V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
       7             : 
       8             : // Do only include this header for implementing new Interface of the
       9             : // WasmFullDecoder.
      10             : 
      11             : #include "src/base/platform/elapsed-timer.h"
      12             : #include "src/bit-vector.h"
      13             : #include "src/wasm/decoder.h"
      14             : #include "src/wasm/function-body-decoder.h"
      15             : #include "src/wasm/wasm-features.h"
      16             : #include "src/wasm/wasm-limits.h"
      17             : #include "src/wasm/wasm-module.h"
      18             : #include "src/wasm/wasm-opcodes.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : namespace wasm {
      23             : 
      24             : struct WasmGlobal;
      25             : struct WasmException;
      26             : 
      27             : #define TRACE(...)                                    \
      28             :   do {                                                \
      29             :     if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
      30             :   } while (false)
      31             : 
      32             : #define TRACE_INST_FORMAT "  @%-8d #%-20s|"
      33             : 
      34             : // Return the evaluation of `condition` if validate==true, DCHECK that it's
      35             : // true and always return true otherwise.
      36             : #define VALIDATE(condition)       \
      37             :   (validate ? (condition) : [&] { \
      38             :     DCHECK(condition);            \
      39             :     return true;                  \
      40             :   }())
      41             : 
      42             : #define RET_ON_PROTOTYPE_OPCODE(feat)                                          \
      43             :   DCHECK(!this->module_ || this->module_->origin == kWasmOrigin);              \
      44             :   if (!this->enabled_.feat) {                                                  \
      45             :     this->error("Invalid opcode (enable with --experimental-wasm-" #feat ")"); \
      46             :   } else {                                                                     \
      47             :     this->detected_->feat = true;                                              \
      48             :   }
      49             : 
      50             : #define CHECK_PROTOTYPE_OPCODE(feat)                                           \
      51             :   DCHECK(!this->module_ || this->module_->origin == kWasmOrigin);              \
      52             :   if (!this->enabled_.feat) {                                                  \
      53             :     this->error("Invalid opcode (enable with --experimental-wasm-" #feat ")"); \
      54             :     break;                                                                     \
      55             :   } else {                                                                     \
      56             :     this->detected_->feat = true;                                              \
      57             :   }
      58             : 
      59             : #define OPCODE_ERROR(opcode, message)                                 \
      60             :   (this->errorf(this->pc_, "%s: %s", WasmOpcodes::OpcodeName(opcode), \
      61             :                 (message)))
      62             : 
      63             : #define ATOMIC_OP_LIST(V)                \
      64             :   V(AtomicNotify, Uint32)                \
      65             :   V(I32AtomicWait, Uint32)               \
      66             :   V(I64AtomicWait, Uint32)               \
      67             :   V(I32AtomicLoad, Uint32)               \
      68             :   V(I64AtomicLoad, Uint64)               \
      69             :   V(I32AtomicLoad8U, Uint8)              \
      70             :   V(I32AtomicLoad16U, Uint16)            \
      71             :   V(I64AtomicLoad8U, Uint8)              \
      72             :   V(I64AtomicLoad16U, Uint16)            \
      73             :   V(I64AtomicLoad32U, Uint32)            \
      74             :   V(I32AtomicAdd, Uint32)                \
      75             :   V(I32AtomicAdd8U, Uint8)               \
      76             :   V(I32AtomicAdd16U, Uint16)             \
      77             :   V(I64AtomicAdd, Uint64)                \
      78             :   V(I64AtomicAdd8U, Uint8)               \
      79             :   V(I64AtomicAdd16U, Uint16)             \
      80             :   V(I64AtomicAdd32U, Uint32)             \
      81             :   V(I32AtomicSub, Uint32)                \
      82             :   V(I64AtomicSub, Uint64)                \
      83             :   V(I32AtomicSub8U, Uint8)               \
      84             :   V(I32AtomicSub16U, Uint16)             \
      85             :   V(I64AtomicSub8U, Uint8)               \
      86             :   V(I64AtomicSub16U, Uint16)             \
      87             :   V(I64AtomicSub32U, Uint32)             \
      88             :   V(I32AtomicAnd, Uint32)                \
      89             :   V(I64AtomicAnd, Uint64)                \
      90             :   V(I32AtomicAnd8U, Uint8)               \
      91             :   V(I32AtomicAnd16U, Uint16)             \
      92             :   V(I64AtomicAnd8U, Uint8)               \
      93             :   V(I64AtomicAnd16U, Uint16)             \
      94             :   V(I64AtomicAnd32U, Uint32)             \
      95             :   V(I32AtomicOr, Uint32)                 \
      96             :   V(I64AtomicOr, Uint64)                 \
      97             :   V(I32AtomicOr8U, Uint8)                \
      98             :   V(I32AtomicOr16U, Uint16)              \
      99             :   V(I64AtomicOr8U, Uint8)                \
     100             :   V(I64AtomicOr16U, Uint16)              \
     101             :   V(I64AtomicOr32U, Uint32)              \
     102             :   V(I32AtomicXor, Uint32)                \
     103             :   V(I64AtomicXor, Uint64)                \
     104             :   V(I32AtomicXor8U, Uint8)               \
     105             :   V(I32AtomicXor16U, Uint16)             \
     106             :   V(I64AtomicXor8U, Uint8)               \
     107             :   V(I64AtomicXor16U, Uint16)             \
     108             :   V(I64AtomicXor32U, Uint32)             \
     109             :   V(I32AtomicExchange, Uint32)           \
     110             :   V(I64AtomicExchange, Uint64)           \
     111             :   V(I32AtomicExchange8U, Uint8)          \
     112             :   V(I32AtomicExchange16U, Uint16)        \
     113             :   V(I64AtomicExchange8U, Uint8)          \
     114             :   V(I64AtomicExchange16U, Uint16)        \
     115             :   V(I64AtomicExchange32U, Uint32)        \
     116             :   V(I32AtomicCompareExchange, Uint32)    \
     117             :   V(I64AtomicCompareExchange, Uint64)    \
     118             :   V(I32AtomicCompareExchange8U, Uint8)   \
     119             :   V(I32AtomicCompareExchange16U, Uint16) \
     120             :   V(I64AtomicCompareExchange8U, Uint8)   \
     121             :   V(I64AtomicCompareExchange16U, Uint16) \
     122             :   V(I64AtomicCompareExchange32U, Uint32)
     123             : 
     124             : #define ATOMIC_STORE_OP_LIST(V) \
     125             :   V(I32AtomicStore, Uint32)     \
     126             :   V(I64AtomicStore, Uint64)     \
     127             :   V(I32AtomicStore8U, Uint8)    \
     128             :   V(I32AtomicStore16U, Uint16)  \
     129             :   V(I64AtomicStore8U, Uint8)    \
     130             :   V(I64AtomicStore16U, Uint16)  \
     131             :   V(I64AtomicStore32U, Uint32)
     132             : 
     133             : // Helpers for decoding different kinds of immediates which follow bytecodes.
     134             : template <Decoder::ValidateFlag validate>
     135             : struct LocalIndexImmediate {
     136             :   uint32_t index;
     137             :   ValueType type = kWasmStmt;
     138             :   uint32_t length;
     139             : 
     140    18146540 :   inline LocalIndexImmediate(Decoder* decoder, const byte* pc) {
     141    19960749 :     index = decoder->read_u32v<validate>(pc + 1, &length, "local index");
     142             :   }
     143             : };
     144             : 
     145             : template <Decoder::ValidateFlag validate>
     146             : struct ExceptionIndexImmediate {
     147             :   uint32_t index;
     148             :   const WasmException* exception = nullptr;
     149             :   uint32_t length;
     150             : 
     151        3534 :   inline ExceptionIndexImmediate(Decoder* decoder, const byte* pc) {
     152        5817 :     index = decoder->read_u32v<validate>(pc + 1, &length, "exception index");
     153             :   }
     154             : };
     155             : 
     156             : template <Decoder::ValidateFlag validate>
     157             : struct ImmI32Immediate {
     158             :   int32_t value;
     159             :   uint32_t length;
     160             :   inline ImmI32Immediate(Decoder* decoder, const byte* pc) {
     161    24121948 :     value = decoder->read_i32v<validate>(pc + 1, &length, "immi32");
     162             :   }
     163             : };
     164             : 
     165             : template <Decoder::ValidateFlag validate>
     166             : struct ImmI64Immediate {
     167             :   int64_t value;
     168             :   uint32_t length;
     169             :   inline ImmI64Immediate(Decoder* decoder, const byte* pc) {
     170      232523 :     value = decoder->read_i64v<validate>(pc + 1, &length, "immi64");
     171             :   }
     172             : };
     173             : 
     174             : template <Decoder::ValidateFlag validate>
     175             : struct ImmF32Immediate {
     176             :   float value;
     177             :   uint32_t length = 4;
     178      717908 :   inline ImmF32Immediate(Decoder* decoder, const byte* pc) {
     179             :     // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
     180     1435817 :     uint32_t tmp = decoder->read_u32<validate>(pc + 1, "immf32");
     181      717909 :     memcpy(&value, &tmp, sizeof(value));
     182      717909 :   }
     183             : };
     184             : 
     185             : template <Decoder::ValidateFlag validate>
     186             : struct ImmF64Immediate {
     187             :   double value;
     188             :   uint32_t length = 8;
     189      288907 :   inline ImmF64Immediate(Decoder* decoder, const byte* pc) {
     190             :     // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
     191      577819 :     uint64_t tmp = decoder->read_u64<validate>(pc + 1, "immf64");
     192      288912 :     memcpy(&value, &tmp, sizeof(value));
     193      288912 :   }
     194             : };
     195             : 
     196             : template <Decoder::ValidateFlag validate>
     197             : struct GlobalIndexImmediate {
     198             :   uint32_t index;
     199             :   ValueType type = kWasmStmt;
     200             :   const WasmGlobal* global = nullptr;
     201             :   uint32_t length;
     202             : 
     203      886163 :   inline GlobalIndexImmediate(Decoder* decoder, const byte* pc) {
     204      945071 :     index = decoder->read_u32v<validate>(pc + 1, &length, "global index");
     205             :   }
     206             : };
     207             : 
     208             : template <Decoder::ValidateFlag validate>
     209             : struct BlockTypeImmediate {
     210             :   uint32_t length = 1;
     211             :   ValueType type = kWasmStmt;
     212             :   uint32_t sig_index = 0;
     213             :   FunctionSig* sig = nullptr;
     214             : 
     215     1881138 :   inline BlockTypeImmediate(const WasmFeatures& enabled, Decoder* decoder,
     216     1881138 :                             const byte* pc) {
     217      499561 :     uint8_t val = decoder->read_u8<validate>(pc + 1, "block type");
     218     1881154 :     if (!decode_local_type(val, &type)) {
     219             :       // Handle multi-value blocks.
     220         301 :       if (!VALIDATE(enabled.mv)) {
     221          59 :         decoder->error(pc + 1, "invalid block type");
     222          58 :         return;
     223             :       }
     224         242 :       if (!VALIDATE(decoder->ok())) return;
     225             :       int32_t index =
     226       40613 :           decoder->read_i32v<validate>(pc + 1, &length, "block arity");
     227         221 :       if (!VALIDATE(length > 0 && index >= 0)) {
     228           0 :         decoder->error(pc + 1, "invalid block type index");
     229           0 :         return;
     230             :       }
     231       40613 :       sig_index = static_cast<uint32_t>(index);
     232             :     }
     233             :   }
     234             : 
     235             :   // Decode a byte representing a local type. Return {false} if the encoded
     236             :   // byte was invalid or the start of a type index.
     237     1881163 :   inline bool decode_local_type(uint8_t val, ValueType* result) {
     238     1881163 :     switch (static_cast<ValueTypeCode>(val)) {
     239             :       case kLocalVoid:
     240     1652612 :         *result = kWasmStmt;
     241     1652612 :         return true;
     242             :       case kLocalI32:
     243      180429 :         *result = kWasmI32;
     244      180429 :         return true;
     245             :       case kLocalI64:
     246        1812 :         *result = kWasmI64;
     247        1812 :         return true;
     248             :       case kLocalF32:
     249        2637 :         *result = kWasmF32;
     250        2637 :         return true;
     251             :       case kLocalF64:
     252        2738 :         *result = kWasmF64;
     253        2738 :         return true;
     254             :       case kLocalS128:
     255          43 :         *result = kWasmS128;
     256          43 :         return true;
     257             :       case kLocalAnyFunc:
     258           0 :         *result = kWasmAnyFunc;
     259           0 :         return true;
     260             :       case kLocalAnyRef:
     261         199 :         *result = kWasmAnyRef;
     262         199 :         return true;
     263             :       default:
     264       40693 :         *result = kWasmVar;
     265       40693 :         return false;
     266             :     }
     267             :   }
     268             : 
     269             :   uint32_t in_arity() const {
     270      414469 :     if (type != kWasmVar) return 0;
     271         257 :     return static_cast<uint32_t>(sig->parameter_count());
     272             :   }
     273             :   uint32_t out_arity() const {
     274      459376 :     if (type == kWasmStmt) return 0;
     275       28812 :     if (type != kWasmVar) return 1;
     276         281 :     return static_cast<uint32_t>(sig->return_count());
     277             :   }
     278             :   ValueType in_type(uint32_t index) {
     279             :     DCHECK_EQ(kWasmVar, type);
     280             :     return sig->GetParam(index);
     281             :   }
     282             :   ValueType out_type(uint32_t index) {
     283       27401 :     if (type == kWasmVar) return sig->GetReturn(index);
     284             :     DCHECK_NE(kWasmStmt, type);
     285             :     DCHECK_EQ(0, index);
     286             :     return type;
     287             :   }
     288             : };
     289             : 
     290             : template <Decoder::ValidateFlag validate>
     291             : struct BranchDepthImmediate {
     292             :   uint32_t depth;
     293             :   uint32_t length;
     294             :   inline BranchDepthImmediate(Decoder* decoder, const byte* pc) {
     295      779244 :     depth = decoder->read_u32v<validate>(pc + 1, &length, "branch depth");
     296             :   }
     297             : };
     298             : 
     299             : template <Decoder::ValidateFlag validate>
     300             : struct BranchOnExceptionImmediate {
     301             :   BranchDepthImmediate<validate> depth;
     302             :   ExceptionIndexImmediate<validate> index;
     303             :   uint32_t length = 0;
     304        1350 :   inline BranchOnExceptionImmediate(Decoder* decoder, const byte* pc)
     305             :       : depth(BranchDepthImmediate<validate>(decoder, pc)),
     306        2699 :         index(ExceptionIndexImmediate<validate>(decoder, pc + depth.length)) {
     307        1350 :     length = depth.length + index.length;
     308        1350 :   }
     309             : };
     310             : 
     311             : template <Decoder::ValidateFlag validate>
     312             : struct CallIndirectImmediate {
     313             :   uint32_t table_index;
     314             :   uint32_t sig_index;
     315             :   FunctionSig* sig = nullptr;
     316             :   uint32_t length = 0;
     317       50584 :   inline CallIndirectImmediate(const WasmFeatures enabled, Decoder* decoder,
     318       50584 :                                const byte* pc) {
     319       50584 :     uint32_t len = 0;
     320       59595 :     sig_index = decoder->read_u32v<validate>(pc + 1, &len, "signature index");
     321       59595 :     table_index = decoder->read_u8<validate>(pc + 1 + len, "table index");
     322        9011 :     if (!VALIDATE(table_index == 0 || enabled.anyref)) {
     323          62 :       decoder->errorf(pc + 1 + len, "expected table index 0, found %u",
     324             :                       table_index);
     325             :     }
     326       50583 :     length = 1 + len;
     327       50583 :   }
     328             : };
     329             : 
     330             : template <Decoder::ValidateFlag validate>
     331             : struct CallFunctionImmediate {
     332             :   uint32_t index;
     333             :   FunctionSig* sig = nullptr;
     334             :   uint32_t length;
     335      995864 :   inline CallFunctionImmediate(Decoder* decoder, const byte* pc) {
     336     1316180 :     index = decoder->read_u32v<validate>(pc + 1, &length, "function index");
     337             :   }
     338             : };
     339             : 
     340             : template <Decoder::ValidateFlag validate>
     341             : struct MemoryIndexImmediate {
     342             :   uint32_t index = 0;
     343             :   uint32_t length = 1;
     344         258 :   inline MemoryIndexImmediate() = default;
     345        3973 :   inline MemoryIndexImmediate(Decoder* decoder, const byte* pc) {
     346        7986 :     index = decoder->read_u8<validate>(pc + 1, "memory index");
     347        3925 :     if (!VALIDATE(index == 0)) {
     348         318 :       decoder->errorf(pc + 1, "expected memory index 0, found %u", index);
     349             :     }
     350        3925 :   }
     351             : };
     352             : 
     353             : template <Decoder::ValidateFlag validate>
     354             : struct TableIndexImmediate {
     355             :   uint32_t index = 0;
     356             :   unsigned length = 1;
     357         244 :   inline TableIndexImmediate() = default;
     358         342 :   inline TableIndexImmediate(Decoder* decoder, const byte* pc) {
     359        1580 :     index = decoder->read_u8<validate>(pc + 1, "table index");
     360         342 :   }
     361             : };
     362             : 
     363             : template <Decoder::ValidateFlag validate>
     364             : struct BranchTableImmediate {
     365             :   uint32_t table_count;
     366             :   const byte* start;
     367             :   const byte* table;
     368      242750 :   inline BranchTableImmediate(Decoder* decoder, const byte* pc) {
     369             :     DCHECK_EQ(kExprBrTable, decoder->read_u8<validate>(pc, "opcode"));
     370      242750 :     start = pc + 1;
     371      242750 :     uint32_t len = 0;
     372      242749 :     table_count = decoder->read_u32v<validate>(pc + 1, &len, "table count");
     373      242749 :     table = pc + 1 + len;
     374      242749 :   }
     375             : };
     376             : 
     377             : // A helper to iterate over a branch table.
     378             : template <Decoder::ValidateFlag validate>
     379             : class BranchTableIterator {
     380             :  public:
     381             :   uint32_t cur_index() { return index_; }
     382      794254 :   bool has_next() { return VALIDATE(decoder_->ok()) && index_ <= table_count_; }
     383     1708094 :   uint32_t next() {
     384             :     DCHECK(has_next());
     385     1708094 :     index_++;
     386             :     uint32_t length;
     387             :     uint32_t result =
     388     1708094 :         decoder_->read_u32v<validate>(pc_, &length, "branch table entry");
     389     1708092 :     pc_ += length;
     390     1708092 :     return result;
     391             :   }
     392             :   // length, including the length of the {BranchTableImmediate}, but not the
     393             :   // opcode.
     394       11643 :   uint32_t length() {
     395       32845 :     while (has_next()) next();
     396       15848 :     return static_cast<uint32_t>(pc_ - start_);
     397             :   }
     398             :   const byte* pc() { return pc_; }
     399             : 
     400             :   BranchTableIterator(Decoder* decoder,
     401             :                       const BranchTableImmediate<validate>& imm)
     402             :       : decoder_(decoder),
     403             :         start_(imm.start),
     404             :         pc_(imm.table),
     405      252691 :         table_count_(imm.table_count) {}
     406             : 
     407             :  private:
     408             :   Decoder* decoder_;
     409             :   const byte* start_;
     410             :   const byte* pc_;
     411             :   uint32_t index_ = 0;    // the current index.
     412             :   uint32_t table_count_;  // the count of entries, not including default.
     413             : };
     414             : 
     415             : template <Decoder::ValidateFlag validate>
     416             : struct MemoryAccessImmediate {
     417             :   uint32_t alignment;
     418             :   uint32_t offset;
     419             :   uint32_t length = 0;
     420     6770440 :   inline MemoryAccessImmediate(Decoder* decoder, const byte* pc,
     421     6770440 :                                uint32_t max_alignment) {
     422             :     uint32_t alignment_length;
     423     7266491 :     alignment =
     424             :         decoder->read_u32v<validate>(pc + 1, &alignment_length, "alignment");
     425      496051 :     if (!VALIDATE(alignment <= max_alignment)) {
     426        1132 :       decoder->errorf(pc + 1,
     427             :                       "invalid alignment; expected maximum alignment is %u, "
     428             :                       "actual alignment is %u",
     429             :                       max_alignment, alignment);
     430             :     }
     431             :     uint32_t offset_length;
     432    13541213 :     offset = decoder->read_u32v<validate>(pc + 1 + alignment_length,
     433             :                                           &offset_length, "offset");
     434     6770702 :     length = alignment_length + offset_length;
     435     6770702 :   }
     436             : };
     437             : 
     438             : // Immediate for SIMD lane operations.
     439             : template <Decoder::ValidateFlag validate>
     440             : struct SimdLaneImmediate {
     441             :   uint8_t lane;
     442             :   uint32_t length = 1;
     443             : 
     444         784 :   inline SimdLaneImmediate(Decoder* decoder, const byte* pc) {
     445        1568 :     lane = decoder->read_u8<validate>(pc + 2, "lane");
     446         784 :   }
     447             : };
     448             : 
     449             : // Immediate for SIMD shift operations.
     450             : template <Decoder::ValidateFlag validate>
     451             : struct SimdShiftImmediate {
     452             :   uint8_t shift;
     453             :   uint32_t length = 1;
     454             : 
     455        1272 :   inline SimdShiftImmediate(Decoder* decoder, const byte* pc) {
     456        2544 :     shift = decoder->read_u8<validate>(pc + 2, "shift");
     457        1272 :   }
     458             : };
     459             : 
     460             : // Immediate for SIMD S8x16 shuffle operations.
     461             : template <Decoder::ValidateFlag validate>
     462             : struct Simd8x16ShuffleImmediate {
     463             :   uint8_t shuffle[kSimd128Size] = {0};
     464             : 
     465       23889 :   inline Simd8x16ShuffleImmediate(Decoder* decoder, const byte* pc) {
     466      788337 :     for (uint32_t i = 0; i < kSimd128Size; ++i) {
     467      593952 :       shuffle[i] = decoder->read_u8<validate>(pc + 2 + i, "shuffle");
     468             :     }
     469       13233 :   }
     470             : };
     471             : 
     472             : template <Decoder::ValidateFlag validate>
     473             : struct MemoryInitImmediate {
     474             :   uint32_t data_segment_index = 0;
     475             :   MemoryIndexImmediate<validate> memory;
     476             :   unsigned length = 0;
     477             : 
     478         388 :   inline MemoryInitImmediate(Decoder* decoder, const byte* pc) {
     479         194 :     uint32_t len = 0;
     480         388 :     data_segment_index =
     481             :         decoder->read_i32v<validate>(pc + 2, &len, "data segment index");
     482         282 :     memory = MemoryIndexImmediate<validate>(decoder, pc + 1 + len);
     483         193 :     length = len + memory.length;
     484         193 :   }
     485             : };
     486             : 
     487             : template <Decoder::ValidateFlag validate>
     488             : struct DataDropImmediate {
     489             :   uint32_t index;
     490             :   unsigned length;
     491             : 
     492             :   inline DataDropImmediate(Decoder* decoder, const byte* pc) {
     493         176 :     index = decoder->read_i32v<validate>(pc + 2, &length, "data segment index");
     494             :   }
     495             : };
     496             : 
     497             : template <Decoder::ValidateFlag validate>
     498             : struct MemoryCopyImmediate {
     499             :   MemoryIndexImmediate<validate> memory_src;
     500             :   MemoryIndexImmediate<validate> memory_dst;
     501             :   unsigned length = 0;
     502             : 
     503         128 :   inline MemoryCopyImmediate(Decoder* decoder, const byte* pc) {
     504          64 :     memory_src = MemoryIndexImmediate<validate>(decoder, pc + 1);
     505          64 :     memory_dst =
     506          64 :         MemoryIndexImmediate<validate>(decoder, pc + 1 + memory_src.length);
     507          64 :     length = memory_src.length + memory_dst.length;
     508          64 :   }
     509             : };
     510             : 
     511             : template <Decoder::ValidateFlag validate>
     512             : struct TableInitImmediate {
     513             :   uint32_t elem_segment_index = 0;
     514             :   TableIndexImmediate<validate> table;
     515             :   unsigned length = 0;
     516             : 
     517         336 :   inline TableInitImmediate(Decoder* decoder, const byte* pc) {
     518         168 :     uint32_t len = 0;
     519         336 :     elem_segment_index =
     520             :         decoder->read_i32v<validate>(pc + 2, &len, "elem segment index");
     521         296 :     table = TableIndexImmediate<validate>(decoder, pc + 1 + len);
     522         168 :     length = len + table.length;
     523         168 :   }
     524             : };
     525             : 
     526             : template <Decoder::ValidateFlag validate>
     527             : struct ElemDropImmediate {
     528             :   uint32_t index;
     529             :   unsigned length;
     530             : 
     531             :   inline ElemDropImmediate(Decoder* decoder, const byte* pc) {
     532         122 :     index = decoder->read_i32v<validate>(pc + 2, &length, "elem segment index");
     533             :   }
     534             : };
     535             : 
     536             : template <Decoder::ValidateFlag validate>
     537             : struct TableCopyImmediate {
     538             :   TableIndexImmediate<validate> table_src;
     539             :   TableIndexImmediate<validate> table_dst;
     540             :   unsigned length = 0;
     541             : 
     542         152 :   inline TableCopyImmediate(Decoder* decoder, const byte* pc) {
     543          76 :     table_src = TableIndexImmediate<validate>(decoder, pc + 1);
     544          76 :     table_dst =
     545          76 :         TableIndexImmediate<validate>(decoder, pc + 1 + table_src.length);
     546          76 :     length = table_src.length + table_dst.length;
     547          76 :   }
     548             : };
     549             : 
     550             : // An entry on the value stack.
     551             : struct ValueBase {
     552             :   const byte* pc = nullptr;
     553             :   ValueType type = kWasmStmt;
     554             : 
     555     8175592 :   ValueBase(const byte* pc, ValueType type) : pc(pc), type(type) {}
     556             : };
     557             : 
     558             : template <typename Value>
     559             : struct Merge {
     560             :   uint32_t arity = 0;
     561             :   union {  // Either multiple values or a single value.
     562             :     Value* array;
     563             :     Value first;
     564             :   } vals = {nullptr};  // Initialize {array} with {nullptr}.
     565             : 
     566             :   // Tracks whether this merge was ever reached. Uses precise reachability, like
     567             :   // Reachability::kReachable.
     568             :   bool reached;
     569             : 
     570     1672191 :   Merge(bool reached = false) : reached(reached) {}
     571             : 
     572             :   Value& operator[](uint32_t i) {
     573             :     DCHECK_GT(arity, i);
     574      968018 :     return arity == 1 ? vals.first : vals.array[i];
     575             :   }
     576             : };
     577             : 
     578             : enum ControlKind : uint8_t {
     579             :   kControlIf,
     580             :   kControlIfElse,
     581             :   kControlBlock,
     582             :   kControlLoop,
     583             :   kControlTry,
     584             :   kControlTryCatch
     585             : };
     586             : 
     587             : enum Reachability : uint8_t {
     588             :   // reachable code.
     589             :   kReachable,
     590             :   // reachable code in unreachable block (implies normal validation).
     591             :   kSpecOnlyReachable,
     592             :   // code unreachable in its own block (implies polymorphic validation).
     593             :   kUnreachable
     594             : };
     595             : 
     596             : // An entry on the control stack (i.e. if, block, loop, or try).
     597             : template <typename Value>
     598             : struct ControlBase {
     599             :   ControlKind kind = kControlBlock;
     600             :   uint32_t stack_depth = 0;  // stack height at the beginning of the construct.
     601             :   const uint8_t* pc = nullptr;
     602             :   Reachability reachability = kReachable;
     603             : 
     604             :   // Values merged into the start or end of this control construct.
     605             :   Merge<Value> start_merge;
     606             :   Merge<Value> end_merge;
     607             : 
     608             :   MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ControlBase);
     609             : 
     610             :   ControlBase(ControlKind kind, uint32_t stack_depth, const uint8_t* pc,
     611             :               Reachability reachability)
     612             :       : kind(kind),
     613             :         stack_depth(stack_depth),
     614             :         pc(pc),
     615             :         reachability(reachability),
     616     1672191 :         start_merge(reachability == kReachable) {}
     617             : 
     618             :   // Check whether the current block is reachable.
     619             :   bool reachable() const { return reachability == kReachable; }
     620             : 
     621             :   // Check whether the rest of the block is unreachable.
     622             :   // Note that this is different from {!reachable()}, as there is also the
     623             :   // "indirect unreachable state", for which both {reachable()} and
     624             :   // {unreachable()} return false.
     625             :   bool unreachable() const { return reachability == kUnreachable; }
     626             : 
     627             :   // Return the reachability of new control structs started in this block.
     628             :   Reachability innerReachability() const {
     629      435783 :     return reachability == kReachable ? kReachable : kSpecOnlyReachable;
     630             :   }
     631             : 
     632       20953 :   bool is_if() const { return is_onearmed_if() || is_if_else(); }
     633             :   bool is_onearmed_if() const { return kind == kControlIf; }
     634             :   bool is_if_else() const { return kind == kControlIfElse; }
     635             :   bool is_block() const { return kind == kControlBlock; }
     636             :   bool is_loop() const { return kind == kControlLoop; }
     637             :   bool is_incomplete_try() const { return kind == kControlTry; }
     638             :   bool is_try_catch() const { return kind == kControlTryCatch; }
     639         776 :   bool is_try() const { return is_incomplete_try() || is_try_catch(); }
     640             : 
     641             :   inline Merge<Value>* br_merge() {
     642     1234233 :     return is_loop() ? &this->start_merge : &this->end_merge;
     643             :   }
     644             : };
     645             : 
     646             : // This is the list of callback functions that an interface for the
     647             : // WasmFullDecoder should implement.
     648             : // F(Name, args...)
     649             : #define INTERFACE_FUNCTIONS(F)                                                \
     650             :   /* General: */                                                              \
     651             :   F(StartFunction)                                                            \
     652             :   F(StartFunctionBody, Control* block)                                        \
     653             :   F(FinishFunction)                                                           \
     654             :   F(OnFirstError)                                                             \
     655             :   F(NextInstruction, WasmOpcode)                                              \
     656             :   /* Control: */                                                              \
     657             :   F(Block, Control* block)                                                    \
     658             :   F(Loop, Control* block)                                                     \
     659             :   F(Try, Control* block)                                                      \
     660             :   F(Catch, Control* block, Value* exception)                                  \
     661             :   F(If, const Value& cond, Control* if_block)                                 \
     662             :   F(FallThruTo, Control* c)                                                   \
     663             :   F(PopControl, Control* block)                                               \
     664             :   F(EndControl, Control* block)                                               \
     665             :   /* Instructions: */                                                         \
     666             :   F(UnOp, WasmOpcode opcode, const Value& value, Value* result)               \
     667             :   F(BinOp, WasmOpcode opcode, const Value& lhs, const Value& rhs,             \
     668             :     Value* result)                                                            \
     669             :   F(I32Const, Value* result, int32_t value)                                   \
     670             :   F(I64Const, Value* result, int64_t value)                                   \
     671             :   F(F32Const, Value* result, float value)                                     \
     672             :   F(F64Const, Value* result, double value)                                    \
     673             :   F(RefNull, Value* result)                                                   \
     674             :   F(Drop, const Value& value)                                                 \
     675             :   F(DoReturn, Vector<Value> values)                                           \
     676             :   F(GetLocal, Value* result, const LocalIndexImmediate<validate>& imm)        \
     677             :   F(SetLocal, const Value& value, const LocalIndexImmediate<validate>& imm)   \
     678             :   F(TeeLocal, const Value& value, Value* result,                              \
     679             :     const LocalIndexImmediate<validate>& imm)                                 \
     680             :   F(GetGlobal, Value* result, const GlobalIndexImmediate<validate>& imm)      \
     681             :   F(SetGlobal, const Value& value, const GlobalIndexImmediate<validate>& imm) \
     682             :   F(GetTable, const Value& index, Value* result,                              \
     683             :     const TableIndexImmediate<validate>& imm)                                 \
     684             :   F(SetTable, const Value& index, const Value& value,                         \
     685             :     const TableIndexImmediate<validate>& imm)                                 \
     686             :   F(Unreachable)                                                              \
     687             :   F(Select, const Value& cond, const Value& fval, const Value& tval,          \
     688             :     Value* result)                                                            \
     689             :   F(Br, Control* target)                                                      \
     690             :   F(BrIf, const Value& cond, uint32_t depth)                                  \
     691             :   F(BrTable, const BranchTableImmediate<validate>& imm, const Value& key)     \
     692             :   F(Else, Control* if_block)                                                  \
     693             :   F(LoadMem, LoadType type, const MemoryAccessImmediate<validate>& imm,       \
     694             :     const Value& index, Value* result)                                        \
     695             :   F(StoreMem, StoreType type, const MemoryAccessImmediate<validate>& imm,     \
     696             :     const Value& index, const Value& value)                                   \
     697             :   F(CurrentMemoryPages, Value* result)                                        \
     698             :   F(MemoryGrow, const Value& value, Value* result)                            \
     699             :   F(CallDirect, const CallFunctionImmediate<validate>& imm,                   \
     700             :     const Value args[], Value returns[])                                      \
     701             :   F(CallIndirect, const Value& index,                                         \
     702             :     const CallIndirectImmediate<validate>& imm, const Value args[],           \
     703             :     Value returns[])                                                          \
     704             :   F(ReturnCall, const CallFunctionImmediate<validate>& imm,                   \
     705             :     const Value args[])                                                       \
     706             :   F(ReturnCallIndirect, const Value& index,                                   \
     707             :     const CallIndirectImmediate<validate>& imm, const Value args[])           \
     708             :   F(SimdOp, WasmOpcode opcode, Vector<Value> args, Value* result)             \
     709             :   F(SimdLaneOp, WasmOpcode opcode, const SimdLaneImmediate<validate>& imm,    \
     710             :     const Vector<Value> inputs, Value* result)                                \
     711             :   F(SimdShiftOp, WasmOpcode opcode, const SimdShiftImmediate<validate>& imm,  \
     712             :     const Value& input, Value* result)                                        \
     713             :   F(Simd8x16ShuffleOp, const Simd8x16ShuffleImmediate<validate>& imm,         \
     714             :     const Value& input0, const Value& input1, Value* result)                  \
     715             :   F(Throw, const ExceptionIndexImmediate<validate>& imm,                      \
     716             :     const Vector<Value>& args)                                                \
     717             :   F(Rethrow, const Value& exception)                                          \
     718             :   F(BrOnException, const Value& exception,                                    \
     719             :     const ExceptionIndexImmediate<validate>& imm, uint32_t depth,             \
     720             :     Vector<Value> values)                                                     \
     721             :   F(AtomicOp, WasmOpcode opcode, Vector<Value> args,                          \
     722             :     const MemoryAccessImmediate<validate>& imm, Value* result)                \
     723             :   F(MemoryInit, const MemoryInitImmediate<validate>& imm, const Value& dst,   \
     724             :     const Value& src, const Value& size)                                      \
     725             :   F(DataDrop, const DataDropImmediate<validate>& imm)                         \
     726             :   F(MemoryCopy, const MemoryCopyImmediate<validate>& imm, const Value& dst,   \
     727             :     const Value& src, const Value& size)                                      \
     728             :   F(MemoryFill, const MemoryIndexImmediate<validate>& imm, const Value& dst,  \
     729             :     const Value& value, const Value& size)                                    \
     730             :   F(TableInit, const TableInitImmediate<validate>& imm, Vector<Value> args)   \
     731             :   F(ElemDrop, const ElemDropImmediate<validate>& imm)                         \
     732             :   F(TableCopy, const TableCopyImmediate<validate>& imm, Vector<Value> args)
     733             : 
     734             : // Generic Wasm bytecode decoder with utilities for decoding immediates,
     735             : // lengths, etc.
     736             : template <Decoder::ValidateFlag validate>
     737     6487114 : class WasmDecoder : public Decoder {
     738             :  public:
     739             :   WasmDecoder(const WasmModule* module, const WasmFeatures& enabled,
     740             :               WasmFeatures* detected, FunctionSig* sig, const byte* start,
     741             :               const byte* end, uint32_t buffer_offset = 0)
     742             :       : Decoder(start, end, buffer_offset),
     743             :         module_(module),
     744             :         enabled_(enabled),
     745             :         detected_(detected),
     746             :         sig_(sig),
     747     3243603 :         local_types_(nullptr) {}
     748             :   const WasmModule* module_;
     749             :   const WasmFeatures enabled_;
     750             :   WasmFeatures* detected_;
     751             :   FunctionSig* sig_;
     752             : 
     753             :   ZoneVector<ValueType>* local_types_;
     754             : 
     755             :   uint32_t total_locals() const {
     756             :     return local_types_ == nullptr
     757             :                ? 0
     758     2835691 :                : static_cast<uint32_t>(local_types_->size());
     759             :   }
     760             : 
     761     1626706 :   static bool DecodeLocals(const WasmFeatures& enabled, Decoder* decoder,
     762             :                            const FunctionSig* sig,
     763             :                            ZoneVector<ValueType>* type_list) {
     764             :     DCHECK_NOT_NULL(type_list);
     765             :     DCHECK_EQ(0, type_list->size());
     766             :     // Initialize from signature.
     767     1626706 :     if (sig != nullptr) {
     768     1258564 :       type_list->assign(sig->parameters().begin(), sig->parameters().end());
     769             :     }
     770             :     // Decode local declarations, if any.
     771             :     uint32_t entries = decoder->consume_u32v("local decls count");
     772     1627570 :     if (decoder->failed()) return false;
     773             : 
     774             :     TRACE("local decls count: %u\n", entries);
     775     1727271 :     while (entries-- > 0 && decoder->more()) {
     776             :       uint32_t count = decoder->consume_u32v("local count");
     777       50006 :       if (decoder->failed()) return false;
     778             : 
     779             :       DCHECK_LE(type_list->size(), kV8MaxWasmFunctionLocals);
     780       99826 :       if (count > kV8MaxWasmFunctionLocals - type_list->size()) {
     781          55 :         decoder->error(decoder->pc() - 1, "local count too large");
     782          55 :         return false;
     783             :       }
     784             :       byte code = decoder->consume_u8("local type");
     785       49858 :       if (decoder->failed()) return false;
     786             : 
     787             :       ValueType type;
     788       49858 :       switch (code) {
     789             :         case kLocalI32:
     790       23665 :           type = kWasmI32;
     791       23665 :           break;
     792             :         case kLocalI64:
     793       19097 :           type = kWasmI64;
     794       19097 :           break;
     795             :         case kLocalF32:
     796        1257 :           type = kWasmF32;
     797        1257 :           break;
     798             :         case kLocalF64:
     799        2094 :           type = kWasmF64;
     800        2094 :           break;
     801             :         case kLocalAnyRef:
     802          70 :           if (enabled.anyref) {
     803          70 :             type = kWasmAnyRef;
     804          70 :             break;
     805             :           }
     806           0 :           decoder->error(decoder->pc() - 1, "invalid local type");
     807           0 :           return false;
     808             :         case kLocalAnyFunc:
     809         120 :           if (enabled.anyref) {
     810         120 :             type = kWasmAnyFunc;
     811         120 :             break;
     812             :           }
     813           0 :           decoder->error(decoder->pc() - 1,
     814             :                          "local type 'anyfunc' is not enabled with "
     815             :                          "--experimental-wasm-anyref");
     816           0 :           return false;
     817             :         case kLocalExceptRef:
     818         203 :           if (enabled.eh) {
     819         203 :             type = kWasmExceptRef;
     820         203 :             break;
     821             :           }
     822           0 :           decoder->error(decoder->pc() - 1, "invalid local type");
     823           0 :           return false;
     824             :         case kLocalS128:
     825        3324 :           if (enabled.simd) {
     826        3316 :             type = kWasmS128;
     827        3316 :             break;
     828             :           }
     829             :           V8_FALLTHROUGH;
     830             :         default:
     831          38 :           decoder->error(decoder->pc() - 1, "invalid local type");
     832          38 :           return false;
     833             :       }
     834       49822 :       type_list->insert(type_list->end(), count, type);
     835             :     }
     836             :     DCHECK(decoder->ok());
     837             :     return true;
     838             :   }
     839             : 
     840        9653 :   static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc,
     841             :                                           uint32_t locals_count, Zone* zone) {
     842        9653 :     if (pc >= decoder->end()) return nullptr;
     843        9653 :     if (*pc != kExprLoop) return nullptr;
     844             : 
     845             :     // The number of locals_count is augmented by 2 so that 'locals_count - 2'
     846             :     // can be used to track mem_size, and 'locals_count - 1' to track mem_start.
     847        9653 :     BitVector* assigned = new (zone) BitVector(locals_count, zone);
     848             :     int depth = 0;
     849             :     // Iteratively process all AST nodes nested inside the loop.
     850     3185142 :     while (pc < decoder->end() && VALIDATE(decoder->ok())) {
     851     1597409 :       WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
     852             :       uint32_t length = 1;
     853     1597409 :       switch (opcode) {
     854             :         case kExprLoop:
     855             :         case kExprIf:
     856             :         case kExprBlock:
     857             :         case kExprTry:
     858       84734 :           length = OpcodeLength(decoder, pc);
     859       84736 :           depth++;
     860       84736 :           break;
     861             :         case kExprSetLocal:  // fallthru
     862             :         case kExprTeeLocal: {
     863             :           LocalIndexImmediate<validate> imm(decoder, pc);
     864      112864 :           if (assigned->length() > 0 &&
     865             :               imm.index < static_cast<uint32_t>(assigned->length())) {
     866             :             // Unverified code might have an out-of-bounds index.
     867      112863 :             assigned->Add(imm.index);
     868             :           }
     869      112864 :           length = 1 + imm.length;
     870             :           break;
     871             :         }
     872             :         case kExprMemoryGrow:
     873             :         case kExprCallFunction:
     874             :         case kExprCallIndirect:
     875             :         case kExprReturnCall:
     876             :         case kExprReturnCallIndirect:
     877             :           // Add instance cache nodes to the assigned set.
     878             :           // TODO(titzer): make this more clear.
     879       18325 :           assigned->Add(locals_count - 1);
     880       18325 :           length = OpcodeLength(decoder, pc);
     881       18325 :           break;
     882             :         case kExprEnd:
     883       84716 :           depth--;
     884       84716 :           break;
     885             :         default:
     886     1296771 :           length = OpcodeLength(decoder, pc);
     887     1296773 :           break;
     888             :       }
     889     1597414 :       if (depth <= 0) break;
     890     1587748 :       pc += length;
     891             :     }
     892        9651 :     return VALIDATE(decoder->ok()) ? assigned : nullptr;
     893             :   }
     894             : 
     895     1398786 :   inline bool Validate(const byte* pc, LocalIndexImmediate<validate>& imm) {
     896     2797572 :     if (!VALIDATE(imm.index < total_locals())) {
     897         625 :       errorf(pc + 1, "invalid local index: %u", imm.index);
     898         624 :       return false;
     899             :     }
     900     2796237 :     imm.type = local_types_ ? local_types_->at(imm.index) : kWasmStmt;
     901     1398161 :     return true;
     902             :   }
     903             : 
     904             :   inline bool Complete(const byte* pc, ExceptionIndexImmediate<validate>& imm) {
     905        2941 :     if (!VALIDATE(module_ != nullptr &&
     906             :                   imm.index < module_->exceptions.size())) {
     907             :       return false;
     908             :     }
     909        3572 :     imm.exception = &module_->exceptions[imm.index];
     910             :     return true;
     911             :   }
     912             : 
     913        1470 :   inline bool Validate(const byte* pc, ExceptionIndexImmediate<validate>& imm) {
     914        1470 :     if (!Complete(pc, imm)) {
     915           9 :       errorf(pc + 1, "Invalid exception index: %u", imm.index);
     916           9 :       return false;
     917             :     }
     918             :     return true;
     919             :   }
     920             : 
     921       55417 :   inline bool Validate(const byte* pc, GlobalIndexImmediate<validate>& imm) {
     922      110835 :     if (!VALIDATE(module_ != nullptr && imm.index < module_->globals.size())) {
     923          28 :       errorf(pc + 1, "invalid global index: %u", imm.index);
     924          28 :       return false;
     925             :     }
     926      110778 :     imm.global = &module_->globals[imm.index];
     927       55389 :     imm.type = imm.global->type;
     928       55389 :     return true;
     929             :   }
     930             : 
     931             :   inline bool CanReturnCall(FunctionSig* target_sig) {
     932         323 :     if (target_sig == nullptr) return false;
     933         322 :     size_t num_returns = sig_->return_count();
     934         322 :     if (num_returns != target_sig->return_count()) return false;
     935         961 :     for (size_t i = 0; i < num_returns; ++i) {
     936         323 :       if (sig_->GetReturn(i) != target_sig->GetReturn(i)) return false;
     937             :     }
     938             :     return true;
     939             :   }
     940             : 
     941             :   inline bool Complete(const byte* pc, CallFunctionImmediate<validate>& imm) {
     942      606311 :     if (!VALIDATE(module_ != nullptr &&
     943             :                   imm.index < module_->functions.size())) {
     944             :       return false;
     945             :     }
     946      611738 :     imm.sig = module_->functions[imm.index].sig;
     947             :     return true;
     948             :   }
     949             : 
     950      303144 :   inline bool Validate(const byte* pc, CallFunctionImmediate<validate>& imm) {
     951      303144 :     if (Complete(pc, imm)) {
     952             :       return true;
     953             :     }
     954          84 :     errorf(pc + 1, "invalid function index: %u", imm.index);
     955          84 :     return false;
     956             :   }
     957             : 
     958             :   inline bool Complete(const byte* pc, CallIndirectImmediate<validate>& imm) {
     959       15578 :     if (!VALIDATE(module_ != nullptr &&
     960             :                   imm.sig_index < module_->signatures.size())) {
     961             :       return false;
     962             :     }
     963       15978 :     imm.sig = module_->signatures[imm.sig_index];
     964             :     return true;
     965             :   }
     966             : 
     967        7905 :   inline bool Validate(const byte* pc, CallIndirectImmediate<validate>& imm) {
     968       15808 :     if (!VALIDATE(module_ != nullptr &&
     969             :                   imm.table_index < module_->tables.size())) {
     970          96 :       error("function table has to exist to execute call_indirect");
     971          96 :       return false;
     972             :     }
     973       15617 :     if (!VALIDATE(module_ != nullptr &&
     974             :                   module_->tables[imm.table_index].type == kWasmAnyFunc)) {
     975          20 :       error("table of call_indirect must be of type anyfunc");
     976          20 :       return false;
     977             :     }
     978        7789 :     if (!Complete(pc, imm)) {
     979          63 :       errorf(pc + 1, "invalid signature index: #%u", imm.sig_index);
     980          63 :       return false;
     981             :     }
     982             :     return true;
     983             :   }
     984             : 
     985             :   inline bool Validate(const byte* pc, BranchDepthImmediate<validate>& imm,
     986             :                        size_t control_depth) {
     987      309135 :     if (!VALIDATE(imm.depth < control_depth)) {
     988         659 :       errorf(pc + 1, "invalid branch depth: %u", imm.depth);
     989             :       return false;
     990             :     }
     991             :     return true;
     992             :   }
     993             : 
     994       12111 :   bool Validate(const byte* pc, BranchTableImmediate<validate>& imm,
     995             :                 size_t block_depth) {
     996       12111 :     if (!VALIDATE(imm.table_count < kV8MaxWasmFunctionSize)) {
     997          21 :       errorf(pc + 1, "invalid table count (> max function size): %u",
     998             :              imm.table_count);
     999             :       return false;
    1000             :     }
    1001       12090 :     return checkAvailable(imm.table_count);
    1002             :   }
    1003             : 
    1004         784 :   inline bool Validate(const byte* pc, WasmOpcode opcode,
    1005             :                        SimdLaneImmediate<validate>& imm) {
    1006             :     uint8_t num_lanes = 0;
    1007             :     switch (opcode) {
    1008             :       case kExprF32x4ExtractLane:
    1009             :       case kExprF32x4ReplaceLane:
    1010             :       case kExprI32x4ExtractLane:
    1011             :       case kExprI32x4ReplaceLane:
    1012             :         num_lanes = 4;
    1013             :         break;
    1014             :       case kExprI16x8ExtractLane:
    1015             :       case kExprI16x8ReplaceLane:
    1016             :         num_lanes = 8;
    1017             :         break;
    1018             :       case kExprI8x16ExtractLane:
    1019             :       case kExprI8x16ReplaceLane:
    1020             :         num_lanes = 16;
    1021             :         break;
    1022             :       default:
    1023           0 :         UNREACHABLE();
    1024             :         break;
    1025             :     }
    1026         784 :     if (!VALIDATE(imm.lane >= 0 && imm.lane < num_lanes)) {
    1027           0 :       error(pc_ + 2, "invalid lane index");
    1028             :       return false;
    1029             :     } else {
    1030             :       return true;
    1031             :     }
    1032             :   }
    1033             : 
    1034        1272 :   inline bool Validate(const byte* pc, WasmOpcode opcode,
    1035             :                        SimdShiftImmediate<validate>& imm) {
    1036             :     uint8_t max_shift = 0;
    1037             :     switch (opcode) {
    1038             :       case kExprI32x4Shl:
    1039             :       case kExprI32x4ShrS:
    1040             :       case kExprI32x4ShrU:
    1041             :         max_shift = 32;
    1042             :         break;
    1043             :       case kExprI16x8Shl:
    1044             :       case kExprI16x8ShrS:
    1045             :       case kExprI16x8ShrU:
    1046             :         max_shift = 16;
    1047             :         break;
    1048             :       case kExprI8x16Shl:
    1049             :       case kExprI8x16ShrS:
    1050             :       case kExprI8x16ShrU:
    1051             :         max_shift = 8;
    1052             :         break;
    1053             :       default:
    1054           0 :         UNREACHABLE();
    1055             :         break;
    1056             :     }
    1057        1272 :     if (!VALIDATE(imm.shift >= 0 && imm.shift < max_shift)) {
    1058           0 :       error(pc_ + 2, "invalid shift amount");
    1059             :       return false;
    1060             :     } else {
    1061             :       return true;
    1062             :     }
    1063             :   }
    1064             : 
    1065       13233 :   inline bool Validate(const byte* pc,
    1066             :                        Simd8x16ShuffleImmediate<validate>& imm) {
    1067       13233 :     uint8_t max_lane = 0;
    1068      436689 :     for (uint32_t i = 0; i < kSimd128Size; ++i) {
    1069      423456 :       max_lane = std::max(max_lane, imm.shuffle[i]);
    1070             :     }
    1071             :     // Shuffle indices must be in [0..31] for a 16 lane shuffle.
    1072       13233 :     if (!VALIDATE(max_lane <= 2 * kSimd128Size)) {
    1073           0 :       error(pc_ + 2, "invalid shuffle mask");
    1074             :       return false;
    1075             :     }
    1076             :     return true;
    1077             :   }
    1078             : 
    1079      414830 :   inline bool Complete(BlockTypeImmediate<validate>& imm) {
    1080      414830 :     if (imm.type != kWasmVar) return true;
    1081         531 :     if (!VALIDATE(module_ && imm.sig_index < module_->signatures.size())) {
    1082             :       return false;
    1083             :     }
    1084         514 :     imm.sig = module_->signatures[imm.sig_index];
    1085             :     return true;
    1086             :   }
    1087             : 
    1088      414827 :   inline bool Validate(BlockTypeImmediate<validate>& imm) {
    1089      414827 :     if (!Complete(imm)) {
    1090          34 :       errorf(pc_, "block type index %u out of bounds (%zu signatures)",
    1091             :              imm.sig_index, module_ ? module_->signatures.size() : 0);
    1092          17 :       return false;
    1093             :     }
    1094             :     return true;
    1095             :   }
    1096             : 
    1097             :   inline bool Validate(const byte* pc, MemoryIndexImmediate<validate>& imm) {
    1098         295 :     if (!VALIDATE(module_ != nullptr && module_->has_memory)) {
    1099           2 :       errorf(pc + 1, "memory instruction with no memory");
    1100             :       return false;
    1101             :     }
    1102             :     return true;
    1103             :   }
    1104             : 
    1105         105 :   inline bool Validate(MemoryInitImmediate<validate>& imm) {
    1106         105 :     if (!VALIDATE(module_ != nullptr &&
    1107             :                   imm.data_segment_index <
    1108             :                       module_->num_declared_data_segments)) {
    1109           1 :       errorf(pc_ + 2, "invalid data segment index: %u", imm.data_segment_index);
    1110           1 :       return false;
    1111             :     }
    1112         208 :     if (!Validate(pc_ + imm.length - imm.memory.length - 1, imm.memory))
    1113             :       return false;
    1114         104 :     return true;
    1115             :   }
    1116             : 
    1117          68 :   inline bool Validate(DataDropImmediate<validate>& imm) {
    1118          68 :     if (!VALIDATE(module_ != nullptr &&
    1119             :                   imm.index < module_->num_declared_data_segments)) {
    1120           1 :       errorf(pc_ + 2, "invalid data segment index: %u", imm.index);
    1121             :       return false;
    1122             :     }
    1123             :     return true;
    1124             :   }
    1125             : 
    1126          64 :   inline bool Validate(MemoryCopyImmediate<validate>& imm) {
    1127         128 :     if (!Validate(pc_ + 1, imm.memory_src)) return false;
    1128         126 :     if (!Validate(pc_ + 2, imm.memory_dst)) return false;
    1129             :     return true;
    1130             :   }
    1131             : 
    1132         338 :   inline bool Validate(const byte* pc, TableIndexImmediate<validate>& imm) {
    1133         675 :     if (!VALIDATE(module_ != nullptr && imm.index < module_->tables.size())) {
    1134           5 :       errorf(pc, "invalid table index: %u", imm.index);
    1135           5 :       return false;
    1136             :     }
    1137             :     return true;
    1138             :   }
    1139             : 
    1140          40 :   inline bool Validate(TableInitImmediate<validate>& imm) {
    1141          79 :     if (!VALIDATE(module_ != nullptr &&
    1142             :                   imm.elem_segment_index < module_->elem_segments.size())) {
    1143           3 :       errorf(pc_ + 2, "invalid element segment index: %u",
    1144             :              imm.elem_segment_index);
    1145           3 :       return false;
    1146             :     }
    1147          37 :     if (!Validate(pc_ + imm.length - imm.table.length - 1, imm.table))
    1148             :       return false;
    1149          37 :     return true;
    1150             :   }
    1151             : 
    1152          41 :   inline bool Validate(ElemDropImmediate<validate>& imm) {
    1153          81 :     if (!VALIDATE(module_ != nullptr &&
    1154             :                   imm.index < module_->elem_segments.size())) {
    1155           2 :       errorf(pc_ + 2, "invalid element segment index: %u", imm.index);
    1156           2 :       return false;
    1157             :     }
    1158             :     return true;
    1159             :   }
    1160             : 
    1161          76 :   inline bool Validate(TableCopyImmediate<validate>& imm) {
    1162          76 :     if (!Validate(pc_ + 1, imm.table_src)) return false;
    1163          75 :     if (!Validate(pc_ + 2, imm.table_dst)) return false;
    1164          75 :     return true;
    1165             :   }
    1166             : 
    1167     3408608 :   static uint32_t OpcodeLength(Decoder* decoder, const byte* pc) {
    1168     3408608 :     WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
    1169     3408608 :     switch (opcode) {
    1170             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1171             :       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1172             :       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1173             : #undef DECLARE_OPCODE_CASE
    1174             :       {
    1175      143375 :         MemoryAccessImmediate<validate> imm(decoder, pc, UINT32_MAX);
    1176      143375 :         return 1 + imm.length;
    1177             :       }
    1178             :       case kExprBr:
    1179             :       case kExprBrIf: {
    1180             :         BranchDepthImmediate<validate> imm(decoder, pc);
    1181       55965 :         return 1 + imm.length;
    1182             :       }
    1183             :       case kExprGetGlobal:
    1184             :       case kExprSetGlobal: {
    1185             :         GlobalIndexImmediate<validate> imm(decoder, pc);
    1186       22670 :         return 1 + imm.length;
    1187             :       }
    1188             :       case kExprGetTable:
    1189             :       case kExprSetTable: {
    1190           0 :         TableIndexImmediate<validate> imm(decoder, pc);
    1191           0 :         return 1 + imm.length;
    1192             :       }
    1193             :       case kExprCallFunction:
    1194             :       case kExprReturnCall: {
    1195             :         CallFunctionImmediate<validate> imm(decoder, pc);
    1196       20033 :         return 1 + imm.length;
    1197             :       }
    1198             :       case kExprCallIndirect:
    1199             :       case kExprReturnCallIndirect: {
    1200        1392 :         CallIndirectImmediate<validate> imm(kAllWasmFeatures, decoder, pc);
    1201        1392 :         return 1 + imm.length;
    1202             :       }
    1203             : 
    1204             :       case kExprTry:
    1205             :       case kExprIf:  // fall through
    1206             :       case kExprLoop:
    1207             :       case kExprBlock: {
    1208      107406 :         BlockTypeImmediate<validate> imm(kAllWasmFeatures, decoder, pc);
    1209      107408 :         return 1 + imm.length;
    1210             :       }
    1211             : 
    1212             :       case kExprThrow: {
    1213             :         ExceptionIndexImmediate<validate> imm(decoder, pc);
    1214         325 :         return 1 + imm.length;
    1215             :       }
    1216             : 
    1217             :       case kExprBrOnExn: {
    1218         204 :         BranchOnExceptionImmediate<validate> imm(decoder, pc);
    1219         203 :         return 1 + imm.length;
    1220             :       }
    1221             : 
    1222             :       case kExprSetLocal:
    1223             :       case kExprTeeLocal:
    1224             :       case kExprGetLocal: {
    1225             :         LocalIndexImmediate<validate> imm(decoder, pc);
    1226      478312 :         return 1 + imm.length;
    1227             :       }
    1228             :       case kExprBrTable: {
    1229        4294 :         BranchTableImmediate<validate> imm(decoder, pc);
    1230             :         BranchTableIterator<validate> iterator(decoder, imm);
    1231        4294 :         return 1 + iterator.length();
    1232             :       }
    1233             :       case kExprI32Const: {
    1234             :         ImmI32Immediate<validate> imm(decoder, pc);
    1235     1161210 :         return 1 + imm.length;
    1236             :       }
    1237             :       case kExprI64Const: {
    1238             :         ImmI64Immediate<validate> imm(decoder, pc);
    1239        2819 :         return 1 + imm.length;
    1240             :       }
    1241             :       case kExprRefNull: {
    1242             :         return 1;
    1243             :       }
    1244             :       case kExprMemoryGrow:
    1245             :       case kExprMemorySize: {
    1246          73 :         MemoryIndexImmediate<validate> imm(decoder, pc);
    1247          73 :         return 1 + imm.length;
    1248             :       }
    1249             :       case kExprF32Const:
    1250         566 :         return 5;
    1251             :       case kExprF64Const:
    1252        3757 :         return 9;
    1253             :       case kNumericPrefix: {
    1254             :         byte numeric_index =
    1255           0 :             decoder->read_u8<validate>(pc + 1, "numeric_index");
    1256             :         WasmOpcode opcode =
    1257         128 :             static_cast<WasmOpcode>(kNumericPrefix << 8 | numeric_index);
    1258         128 :         switch (opcode) {
    1259             :           case kExprI32SConvertSatF32:
    1260             :           case kExprI32UConvertSatF32:
    1261             :           case kExprI32SConvertSatF64:
    1262             :           case kExprI32UConvertSatF64:
    1263             :           case kExprI64SConvertSatF32:
    1264             :           case kExprI64UConvertSatF32:
    1265             :           case kExprI64SConvertSatF64:
    1266             :           case kExprI64UConvertSatF64:
    1267             :             return 2;
    1268             :           case kExprMemoryInit: {
    1269          16 :             MemoryInitImmediate<validate> imm(decoder, pc);
    1270          16 :             return 2 + imm.length;
    1271             :           }
    1272             :           case kExprDataDrop: {
    1273             :             DataDropImmediate<validate> imm(decoder, pc);
    1274           8 :             return 2 + imm.length;
    1275             :           }
    1276             :           case kExprMemoryCopy: {
    1277           0 :             MemoryCopyImmediate<validate> imm(decoder, pc);
    1278           0 :             return 2 + imm.length;
    1279             :           }
    1280             :           case kExprMemoryFill: {
    1281           0 :             MemoryIndexImmediate<validate> imm(decoder, pc + 1);
    1282           0 :             return 2 + imm.length;
    1283             :           }
    1284             :           case kExprTableInit: {
    1285          12 :             TableInitImmediate<validate> imm(decoder, pc);
    1286          12 :             return 2 + imm.length;
    1287             :           }
    1288             :           case kExprElemDrop: {
    1289             :             ElemDropImmediate<validate> imm(decoder, pc);
    1290           8 :             return 2 + imm.length;
    1291             :           }
    1292             :           case kExprTableCopy: {
    1293           0 :             TableCopyImmediate<validate> imm(decoder, pc);
    1294           0 :             return 2 + imm.length;
    1295             :           }
    1296             :           default:
    1297           0 :             decoder->error(pc, "invalid numeric opcode");
    1298           0 :             return 2;
    1299             :         }
    1300             :       }
    1301             :       case kSimdPrefix: {
    1302          32 :         byte simd_index = decoder->read_u8<validate>(pc + 1, "simd_index");
    1303             :         WasmOpcode opcode =
    1304       14114 :             static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
    1305       14114 :         switch (opcode) {
    1306             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1307             :           FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
    1308             : #undef DECLARE_OPCODE_CASE
    1309             :           return 2;
    1310             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1311             :           FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
    1312             : #undef DECLARE_OPCODE_CASE
    1313        1093 :           return 3;
    1314             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1315             :           FOREACH_SIMD_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1316             : #undef DECLARE_OPCODE_CASE
    1317             :           {
    1318           0 :             MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
    1319           0 :             return 2 + imm.length;
    1320             :           }
    1321             :           // Shuffles require a byte per lane, or 16 immediate bytes.
    1322             :           case kExprS8x16Shuffle:
    1323       10657 :             return 2 + kSimd128Size;
    1324             :           default:
    1325           1 :             decoder->error(pc, "invalid SIMD opcode");
    1326           1 :             return 2;
    1327             :         }
    1328             :       }
    1329             :       case kAtomicPrefix: {
    1330         109 :         byte atomic_index = decoder->read_u8<validate>(pc + 1, "atomic_index");
    1331             :         WasmOpcode opcode =
    1332         553 :             static_cast<WasmOpcode>(kAtomicPrefix << 8 | atomic_index);
    1333         553 :         switch (opcode) {
    1334             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1335             :           FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE)
    1336             : #undef DECLARE_OPCODE_CASE
    1337             :           {
    1338         553 :             MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
    1339         554 :             return 2 + imm.length;
    1340             :           }
    1341             :           default:
    1342           0 :             decoder->error(pc, "invalid Atomics opcode");
    1343           0 :             return 2;
    1344             :         }
    1345             :       }
    1346             :       default:
    1347             :         return 1;
    1348             :     }
    1349             :   }
    1350             : 
    1351     1984584 :   std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) {
    1352     1984584 :     WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
    1353             :     // Handle "simple" opcodes with a fixed signature first.
    1354     1984584 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    1355     1984584 :     if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode);
    1356     2336282 :     if (sig) return {sig->parameter_count(), sig->return_count()};
    1357             : 
    1358             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1359             :     // clang-format off
    1360     1632886 :     switch (opcode) {
    1361             :       case kExprSelect:
    1362          20 :         return {3, 1};
    1363             :       case kExprSetTable:
    1364             :       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1365       74496 :         return {2, 0};
    1366             :       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1367             :       case kExprGetTable:
    1368             :       case kExprTeeLocal:
    1369             :       case kExprMemoryGrow:
    1370       68553 :         return {1, 1};
    1371             :       case kExprSetLocal:
    1372             :       case kExprSetGlobal:
    1373             :       case kExprDrop:
    1374             :       case kExprBrIf:
    1375             :       case kExprBrTable:
    1376             :       case kExprIf:
    1377             :       case kExprRethrow:
    1378       76454 :         return {1, 0};
    1379             :       case kExprGetLocal:
    1380             :       case kExprGetGlobal:
    1381             :       case kExprI32Const:
    1382             :       case kExprI64Const:
    1383             :       case kExprF32Const:
    1384             :       case kExprF64Const:
    1385             :       case kExprRefNull:
    1386             :       case kExprMemorySize:
    1387      985332 :         return {0, 1};
    1388             :       case kExprCallFunction: {
    1389             :         CallFunctionImmediate<validate> imm(this, pc);
    1390             :         CHECK(Complete(pc, imm));
    1391        2767 :         return {imm.sig->parameter_count(), imm.sig->return_count()};
    1392             :       }
    1393             :       case kExprCallIndirect: {
    1394         264 :         CallIndirectImmediate<validate> imm(this->enabled_, this, pc);
    1395             :         CHECK(Complete(pc, imm));
    1396             :         // Indirect calls pop an additional argument for the table index.
    1397             :         return {imm.sig->parameter_count() + 1,
    1398         528 :                 imm.sig->return_count()};
    1399             :       }
    1400             :       case kExprThrow: {
    1401             :         ExceptionIndexImmediate<validate> imm(this, pc);
    1402             :         CHECK(Complete(pc, imm));
    1403             :         DCHECK_EQ(0, imm.exception->sig->return_count());
    1404         648 :         return {imm.exception->sig->parameter_count(), 0};
    1405             :       }
    1406             :       case kExprBr:
    1407             :       case kExprBlock:
    1408             :       case kExprLoop:
    1409             :       case kExprEnd:
    1410             :       case kExprElse:
    1411             :       case kExprTry:
    1412             :       case kExprCatch:
    1413             :       case kExprBrOnExn:
    1414             :       case kExprNop:
    1415             :       case kExprReturn:
    1416             :       case kExprReturnCall:
    1417             :       case kExprReturnCallIndirect:
    1418             :       case kExprUnreachable:
    1419      410160 :         return {0, 0};
    1420             :       case kNumericPrefix:
    1421             :       case kAtomicPrefix:
    1422             :       case kSimdPrefix: {
    1423       14516 :         opcode = static_cast<WasmOpcode>(opcode << 8 | *(pc + 1));
    1424       14516 :         switch (opcode) {
    1425             :           FOREACH_SIMD_1_OPERAND_1_PARAM_OPCODE(DECLARE_OPCODE_CASE)
    1426         852 :             return {1, 1};
    1427             :           FOREACH_SIMD_1_OPERAND_2_PARAM_OPCODE(DECLARE_OPCODE_CASE)
    1428             :           FOREACH_SIMD_MASK_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
    1429       10880 :             return {2, 1};
    1430             :           default: {
    1431        2784 :             sig = WasmOpcodes::Signature(opcode);
    1432        2784 :             if (sig) {
    1433        2784 :               return {sig->parameter_count(), sig->return_count()};
    1434             :             }
    1435             :           }
    1436             :         }
    1437             :         V8_FALLTHROUGH;
    1438             :       }
    1439             :       default:
    1440           0 :         V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x (%s)", opcode,
    1441             :                  WasmOpcodes::OpcodeName(opcode));
    1442             :         return {0, 0};
    1443             :     }
    1444             : #undef DECLARE_OPCODE_CASE
    1445             :     // clang-format on
    1446             :   }
    1447             : };
    1448             : 
    1449             : #define CALL_INTERFACE(name, ...) interface_.name(this, ##__VA_ARGS__)
    1450             : #define CALL_INTERFACE_IF_REACHABLE(name, ...)                 \
    1451             :   do {                                                         \
    1452             :     DCHECK(!control_.empty());                                 \
    1453             :     if (VALIDATE(this->ok()) && control_.back().reachable()) { \
    1454             :       interface_.name(this, ##__VA_ARGS__);                    \
    1455             :     }                                                          \
    1456             :   } while (false)
    1457             : #define CALL_INTERFACE_IF_PARENT_REACHABLE(name, ...)           \
    1458             :   do {                                                          \
    1459             :     DCHECK(!control_.empty());                                  \
    1460             :     if (VALIDATE(this->ok()) &&                                 \
    1461             :         (control_.size() == 1 || control_at(1)->reachable())) { \
    1462             :       interface_.name(this, ##__VA_ARGS__);                     \
    1463             :     }                                                           \
    1464             :   } while (false)
    1465             : 
    1466             : template <Decoder::ValidateFlag validate, typename Interface>
    1467     2977058 : class WasmFullDecoder : public WasmDecoder<validate> {
    1468             :   using Value = typename Interface::Value;
    1469             :   using Control = typename Interface::Control;
    1470             :   using MergeValues = Merge<Value>;
    1471             : 
    1472             :   // All Value types should be trivially copyable for performance. We push, pop,
    1473             :   // and store them in local variables.
    1474             :   ASSERT_TRIVIALLY_COPYABLE(Value);
    1475             : 
    1476             :  public:
    1477             :   template <typename... InterfaceArgs>
    1478      461149 :   WasmFullDecoder(Zone* zone, const WasmModule* module,
    1479             :                   const WasmFeatures& enabled, WasmFeatures* detected,
    1480             :                   const FunctionBody& body, InterfaceArgs&&... interface_args)
    1481             :       : WasmDecoder<validate>(module, enabled, detected, body.sig, body.start,
    1482             :                               body.end, body.offset),
    1483             :         zone_(zone),
    1484             :         interface_(std::forward<InterfaceArgs>(interface_args)...),
    1485             :         local_type_vec_(zone),
    1486             :         stack_(zone),
    1487             :         control_(zone),
    1488     3439958 :         args_(zone) {
    1489     1258649 :     this->local_types_ = &local_type_vec_;
    1490      460787 :   }
    1491             : 
    1492             :   Interface& interface() { return interface_; }
    1493             : 
    1494     1258407 :   bool Decode() {
    1495             :     DCHECK(stack_.empty());
    1496             :     DCHECK(control_.empty());
    1497             : 
    1498             :     base::ElapsedTimer decode_timer;
    1499             :     if (FLAG_trace_wasm_decode_time) {
    1500             :       decode_timer.Start();
    1501             :     }
    1502             : 
    1503     1258407 :     if (this->end_ < this->pc_) {
    1504           0 :       this->error("function body end < start");
    1505           0 :       return false;
    1506             :     }
    1507             : 
    1508             :     DCHECK_EQ(0, this->local_types_->size());
    1509     1258407 :     WasmDecoder<validate>::DecodeLocals(this->enabled_, this, this->sig_,
    1510             :                                         this->local_types_);
    1511     1089607 :     CALL_INTERFACE(StartFunction);
    1512     1258091 :     DecodeFunctionBody();
    1513     1088319 :     if (!this->failed()) CALL_INTERFACE(FinishFunction);
    1514             : 
    1515             :     // Generate a better error message whether the unterminated control
    1516             :     // structure is the function body block or an innner structure.
    1517     1257617 :     if (control_.size() > 1) {
    1518       11615 :       this->error(control_.back().pc, "unterminated control structure");
    1519     1246002 :     } else if (control_.size() == 1) {
    1520       49935 :       this->error("function body must end with \"end\" opcode");
    1521             :     }
    1522             : 
    1523     1257772 :     if (this->failed()) return this->TraceFailed();
    1524             : 
    1525             :     if (FLAG_trace_wasm_decode_time) {
    1526             :       double ms = decode_timer.Elapsed().InMillisecondsF();
    1527             :       PrintF("wasm-decode %s (%0.3f ms)\n\n",
    1528             :              VALIDATE(this->ok()) ? "ok" : "failed", ms);
    1529             :     } else {
    1530             :       TRACE("wasm-decode %s\n\n", VALIDATE(this->ok()) ? "ok" : "failed");
    1531             :     }
    1532             : 
    1533     1195598 :     return true;
    1534             :   }
    1535             : 
    1536             :   bool TraceFailed() {
    1537             :     TRACE("wasm-error module+%-6d func+%d: %s\n\n", this->error_.offset(),
    1538             :           this->GetBufferRelativeOffset(this->error_.offset()),
    1539             :           this->error_.message().c_str());
    1540             :     return false;
    1541             :   }
    1542             : 
    1543             :   const char* SafeOpcodeNameAt(const byte* pc) {
    1544       77931 :     if (pc >= this->end_) return "<end>";
    1545       64345 :     return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(*pc));
    1546             :   }
    1547             : 
    1548             :   inline Zone* zone() const { return zone_; }
    1549             : 
    1550             :   inline uint32_t num_locals() const {
    1551     1347995 :     return static_cast<uint32_t>(local_type_vec_.size());
    1552             :   }
    1553             : 
    1554             :   inline ValueType GetLocalType(uint32_t index) {
    1555     2582972 :     return local_type_vec_[index];
    1556             :   }
    1557             : 
    1558             :   inline WasmCodePosition position() {
    1559     2301965 :     int offset = static_cast<int>(this->pc_ - this->start_);
    1560             :     DCHECK_EQ(this->pc_ - this->start_, offset);  // overflows cannot happen
    1561             :     return offset;
    1562             :   }
    1563             : 
    1564             :   inline uint32_t control_depth() const {
    1565      411467 :     return static_cast<uint32_t>(control_.size());
    1566             :   }
    1567             : 
    1568             :   inline Control* control_at(uint32_t depth) {
    1569             :     DCHECK_GT(control_.size(), depth);
    1570      763368 :     return &control_.back() - depth;
    1571             :   }
    1572             : 
    1573             :   inline uint32_t stack_size() const {
    1574             :     DCHECK_GE(kMaxUInt32, stack_.size());
    1575     1689231 :     return static_cast<uint32_t>(stack_.size());
    1576             :   }
    1577             : 
    1578             :   inline Value* stack_value(uint32_t depth) {
    1579             :     DCHECK_LT(0, depth);
    1580             :     DCHECK_GE(stack_.size(), depth);
    1581             :     return &*(stack_.end() - depth);
    1582             :   }
    1583             : 
    1584             :  private:
    1585             :   Zone* zone_;
    1586             : 
    1587             :   Interface interface_;
    1588             : 
    1589             :   ZoneVector<ValueType> local_type_vec_;  // types of local variables.
    1590             :   ZoneVector<Value> stack_;               // stack of values.
    1591             :   ZoneVector<Control> control_;           // stack of blocks, loops, and ifs.
    1592             :   ZoneVector<Value> args_;                // parameters of current block or call
    1593             : 
    1594             :   static Value UnreachableValue(const uint8_t* pc) {
    1595             :     return Value{pc, kWasmVar};
    1596             :   }
    1597             : 
    1598             :   bool CheckHasMemory() {
    1599      451426 :     if (!VALIDATE(this->module_->has_memory)) {
    1600         196 :       this->error(this->pc_ - 1, "memory instruction with no memory");
    1601             :       return false;
    1602             :     }
    1603             :     return true;
    1604             :   }
    1605             : 
    1606             :   bool CheckHasSharedMemory() {
    1607       47477 :     if (!VALIDATE(this->module_->has_shared_memory)) {
    1608          22 :       this->error(this->pc_ - 1, "Atomic opcodes used without shared memory");
    1609             :       return false;
    1610             :     }
    1611             :     return true;
    1612             :   }
    1613             : 
    1614             :   class TraceLine {
    1615             :    public:
    1616             :     static constexpr int kMaxLen = 512;
    1617             :     ~TraceLine() {
    1618             :       if (!FLAG_trace_wasm_decoder) return;
    1619             :       PrintF("%.*s\n", len_, buffer_);
    1620             :     }
    1621             : 
    1622             :     // Appends a formatted string.
    1623             :     PRINTF_FORMAT(2, 3)
    1624             :     void Append(const char* format, ...) {
    1625             :       if (!FLAG_trace_wasm_decoder) return;
    1626             :       va_list va_args;
    1627             :       va_start(va_args, format);
    1628             :       size_t remaining_len = kMaxLen - len_;
    1629             :       Vector<char> remaining_msg_space(buffer_ + len_, remaining_len);
    1630             :       int len = VSNPrintF(remaining_msg_space, format, va_args);
    1631             :       va_end(va_args);
    1632             :       len_ += len < 0 ? remaining_len : len;
    1633             :     }
    1634             : 
    1635             :    private:
    1636             :     char buffer_[kMaxLen];
    1637             :     int len_ = 0;
    1638             :   };
    1639             : 
    1640             :   // Decodes the body of a function.
    1641     1257829 :   void DecodeFunctionBody() {
    1642             :     TRACE("wasm-decode %p...%p (module+%u, %d bytes)\n",
    1643             :           reinterpret_cast<const void*>(this->start()),
    1644             :           reinterpret_cast<const void*>(this->end()), this->pc_offset(),
    1645             :           static_cast<int>(this->end() - this->start()));
    1646             : 
    1647             :     // Set up initial function block.
    1648             :     {
    1649     1257829 :       auto* c = PushControl(kControlBlock);
    1650             :       InitMerge(&c->start_merge, 0, [](uint32_t) -> Value { UNREACHABLE(); });
    1651     2515514 :       InitMerge(&c->end_merge,
    1652     1257757 :                 static_cast<uint32_t>(this->sig_->return_count()),
    1653             :                 [&](uint32_t i) {
    1654      948115 :                   return Value{this->pc_, this->sig_->GetReturn(i)};
    1655      458266 :                 });
    1656      460439 :       CALL_INTERFACE(StartFunctionBody, c);
    1657             :     }
    1658             : 
    1659    26090223 :     while (this->pc_ < this->end_) {  // decoding loop.
    1660             :       uint32_t len = 1;
    1661    12415850 :       WasmOpcode opcode = static_cast<WasmOpcode>(*this->pc_);
    1662             : 
    1663             :       CALL_INTERFACE_IF_REACHABLE(NextInstruction, opcode);
    1664             : 
    1665             : #if DEBUG
    1666             :       TraceLine trace_msg;
    1667             : #define TRACE_PART(...) trace_msg.Append(__VA_ARGS__)
    1668             :       if (!WasmOpcodes::IsPrefixOpcode(opcode)) {
    1669             :         TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    1670             :                    WasmOpcodes::OpcodeName(opcode));
    1671             :       }
    1672             : #else
    1673             : #define TRACE_PART(...)
    1674             : #endif
    1675             : 
    1676    12415850 :       switch (opcode) {
    1677             : #define BUILD_SIMPLE_OPCODE(op, _, sig) \
    1678             :   case kExpr##op:                       \
    1679             :     BuildSimpleOperator_##sig(opcode);  \
    1680             :     break;
    1681             :         FOREACH_SIMPLE_OPCODE(BUILD_SIMPLE_OPCODE)
    1682             : #undef BUILD_SIMPLE_OPCODE
    1683             :         case kExprNop:
    1684             :           break;
    1685             :         case kExprBlock: {
    1686      353480 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1687      353467 :           if (!this->Validate(imm)) break;
    1688      353466 :           PopArgs(imm.sig);
    1689      353452 :           auto* block = PushControl(kControlBlock);
    1690      353476 :           SetBlockType(block, imm);
    1691      167332 :           CALL_INTERFACE_IF_REACHABLE(Block, block);
    1692      353442 :           PushMergeValues(block, &block->start_merge);
    1693      353452 :           len = 1 + imm.length;
    1694      353452 :           break;
    1695             :         }
    1696             :         case kExprRethrow: {
    1697         657 :           CHECK_PROTOTYPE_OPCODE(eh);
    1698             :           auto exception = Pop(0, kWasmExceptRef);
    1699         404 :           CALL_INTERFACE_IF_REACHABLE(Rethrow, exception);
    1700         658 :           EndControl();
    1701         657 :           break;
    1702             :         }
    1703             :         case kExprThrow: {
    1704         932 :           CHECK_PROTOTYPE_OPCODE(eh);
    1705         932 :           ExceptionIndexImmediate<validate> imm(this, this->pc_);
    1706         933 :           len = 1 + imm.length;
    1707         933 :           if (!this->Validate(this->pc_, imm)) break;
    1708         932 :           PopArgs(imm.exception->ToFunctionSig());
    1709        1159 :           CALL_INTERFACE_IF_REACHABLE(Throw, imm, VectorOf(args_));
    1710         933 :           EndControl();
    1711         930 :           break;
    1712             :         }
    1713             :         case kExprTry: {
    1714         889 :           CHECK_PROTOTYPE_OPCODE(eh);
    1715         889 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1716         890 :           if (!this->Validate(imm)) break;
    1717         891 :           PopArgs(imm.sig);
    1718         891 :           auto* try_block = PushControl(kControlTry);
    1719         889 :           SetBlockType(try_block, imm);
    1720         887 :           len = 1 + imm.length;
    1721         610 :           CALL_INTERFACE_IF_REACHABLE(Try, try_block);
    1722         888 :           PushMergeValues(try_block, &try_block->start_merge);
    1723         890 :           break;
    1724             :         }
    1725             :         case kExprCatch: {
    1726         776 :           CHECK_PROTOTYPE_OPCODE(eh);
    1727         776 :           if (!VALIDATE(!control_.empty())) {
    1728           0 :             this->error("catch does not match any try");
    1729           0 :             break;
    1730             :           }
    1731             :           Control* c = &control_.back();
    1732         776 :           if (!VALIDATE(c->is_try())) {
    1733           1 :             this->error("catch does not match any try");
    1734           1 :             break;
    1735             :           }
    1736         775 :           if (!VALIDATE(c->is_incomplete_try())) {
    1737           1 :             this->error("catch already present for try");
    1738           1 :             break;
    1739             :           }
    1740         774 :           c->kind = kControlTryCatch;
    1741         499 :           FallThruTo(c);
    1742        1546 :           stack_.erase(stack_.begin() + c->stack_depth, stack_.end());
    1743         773 :           c->reachability = control_at(1)->innerReachability();
    1744             :           auto* exception = Push(kWasmExceptRef);
    1745        1548 :           CALL_INTERFACE_IF_PARENT_REACHABLE(Catch, c, exception);
    1746             :           break;
    1747             :         }
    1748             :         case kExprBrOnExn: {
    1749         538 :           CHECK_PROTOTYPE_OPCODE(eh);
    1750         538 :           BranchOnExceptionImmediate<validate> imm(this, this->pc_);
    1751        1078 :           if (!this->Validate(this->pc_, imm.depth, control_.size())) break;
    1752         538 :           if (!this->Validate(this->pc_ + imm.depth.length, imm.index)) break;
    1753         529 :           Control* c = control_at(imm.depth.depth);
    1754             :           auto exception = Pop(0, kWasmExceptRef);
    1755         530 :           const WasmExceptionSig* sig = imm.index.exception->sig;
    1756             :           size_t value_count = sig->parameter_count();
    1757             :           // TODO(mstarzinger): This operand stack mutation is an ugly hack to
    1758             :           // make both type checking here as well as environment merging in the
    1759             :           // graph builder interface work out of the box. We should introduce
    1760             :           // special handling for both and do minimal/no stack mutation here.
    1761        1252 :           for (size_t i = 0; i < value_count; ++i) Push(sig->GetParam(i));
    1762         330 :           Vector<Value> values(stack_.data() + c->stack_depth, value_count);
    1763         530 :           if (!TypeCheckBranch(c)) break;
    1764         529 :           if (control_.back().reachable()) {
    1765         329 :             CALL_INTERFACE(BrOnException, exception, imm.index, imm.depth.depth,
    1766             :                            values);
    1767         530 :             c->br_merge()->reached = true;
    1768             :           }
    1769         530 :           len = 1 + imm.length;
    1770        1254 :           for (size_t i = 0; i < value_count; ++i) Pop();
    1771             :           auto* pexception = Push(kWasmExceptRef);
    1772         530 :           *pexception = exception;
    1773         530 :           break;
    1774             :         }
    1775             :         case kExprLoop: {
    1776       15804 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1777       15805 :           if (!this->Validate(imm)) break;
    1778       15803 :           PopArgs(imm.sig);
    1779       15800 :           auto* block = PushControl(kControlLoop);
    1780       15800 :           SetBlockType(&control_.back(), imm);
    1781       15799 :           len = 1 + imm.length;
    1782       10627 :           CALL_INTERFACE_IF_REACHABLE(Loop, block);
    1783       15795 :           PushMergeValues(block, &block->start_merge);
    1784       15797 :           break;
    1785             :         }
    1786             :         case kExprIf: {
    1787       44687 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1788       44684 :           if (!this->Validate(imm)) break;
    1789             :           auto cond = Pop(0, kWasmI32);
    1790       44671 :           PopArgs(imm.sig);
    1791       44671 :           if (!VALIDATE(this->ok())) break;
    1792       44148 :           auto* if_block = PushControl(kControlIf);
    1793       44151 :           SetBlockType(if_block, imm);
    1794       40627 :           CALL_INTERFACE_IF_REACHABLE(If, cond, if_block);
    1795       44150 :           len = 1 + imm.length;
    1796       44150 :           PushMergeValues(if_block, &if_block->start_merge);
    1797       44152 :           break;
    1798             :         }
    1799             :         case kExprElse: {
    1800       20953 :           if (!VALIDATE(!control_.empty())) {
    1801           0 :             this->error("else does not match any if");
    1802           0 :             break;
    1803             :           }
    1804             :           Control* c = &control_.back();
    1805       20953 :           if (!VALIDATE(c->is_if())) {
    1806           0 :             this->error(this->pc_, "else does not match an if");
    1807           0 :             break;
    1808             :           }
    1809       20953 :           if (c->is_if_else()) {
    1810           2 :             this->error(this->pc_, "else already present for if");
    1811           2 :             break;
    1812             :           }
    1813       20951 :           if (!TypeCheckFallThru(c)) break;
    1814       20714 :           c->kind = kControlIfElse;
    1815       37948 :           CALL_INTERFACE_IF_PARENT_REACHABLE(Else, c);
    1816       20711 :           if (c->reachable()) c->end_merge.reached = true;
    1817       20711 :           PushMergeValues(c, &c->start_merge);
    1818       20712 :           c->reachability = control_at(1)->innerReachability();
    1819       20712 :           break;
    1820             :         }
    1821             :         case kExprEnd: {
    1822     1602460 :           if (!VALIDATE(!control_.empty())) {
    1823           0 :             this->error("end does not match any if, try, or block");
    1824           0 :             break;
    1825             :           }
    1826             :           Control* c = &control_.back();
    1827     1602460 :           if (!VALIDATE(!c->is_incomplete_try())) {
    1828           1 :             this->error(this->pc_, "missing catch or catch-all in try");
    1829           1 :             break;
    1830             :           }
    1831     1602459 :           if (c->is_onearmed_if()) {
    1832       22062 :             if (!VALIDATE(c->end_merge.arity == c->start_merge.arity)) {
    1833         115 :               this->error(
    1834             :                   c->pc,
    1835             :                   "start-arity and end-arity of one-armed if must match");
    1836         115 :               break;
    1837             :             }
    1838             :           }
    1839             : 
    1840     1602344 :           if (!TypeCheckFallThru(c)) break;
    1841             : 
    1842     1595049 :           if (control_.size() == 1) {
    1843             :             // If at the last (implicit) control, check we are at end.
    1844     1196319 :             if (!VALIDATE(this->pc_ + 1 == this->end_)) {
    1845         192 :               this->error(this->pc_ + 1, "trailing code after function end");
    1846         191 :               break;
    1847             :             }
    1848             :             // The result of the block is the return value.
    1849             :             TRACE_PART("\n" TRACE_INST_FORMAT, startrel(this->pc_),
    1850             :                        "(implicit) return");
    1851     1060485 :             DoReturn();
    1852             :             control_.clear();
    1853             :             break;
    1854             :           }
    1855             : 
    1856      398730 :           PopControl(c);
    1857      398752 :           break;
    1858             :         }
    1859             :         case kExprSelect: {
    1860             :           auto cond = Pop(2, kWasmI32);
    1861             :           auto fval = Pop();
    1862        1406 :           auto tval = Pop(0, fval.type);
    1863        3542 :           auto* result = Push(tval.type == kWasmVar ? fval.type : tval.type);
    1864        1917 :           CALL_INTERFACE_IF_REACHABLE(Select, cond, fval, tval, result);
    1865             :           break;
    1866             :         }
    1867             :         case kExprBr: {
    1868       31110 :           BranchDepthImmediate<validate> imm(this, this->pc_);
    1869       62221 :           if (!this->Validate(this->pc_, imm, control_.size())) break;
    1870       30536 :           Control* c = control_at(imm.depth);
    1871       30536 :           if (!TypeCheckBranch(c)) break;
    1872       55566 :           if (imm.depth == control_.size() - 1) {
    1873         211 :             DoReturn();
    1874       27352 :           } else if (control_.back().reachable()) {
    1875       23053 :             CALL_INTERFACE(Br, c);
    1876       26810 :             c->br_merge()->reached = true;
    1877             :           }
    1878       27786 :           len = 1 + imm.length;
    1879       27786 :           EndControl();
    1880       27782 :           break;
    1881             :         }
    1882             :         case kExprBrIf: {
    1883      277816 :           BranchDepthImmediate<validate> imm(this, this->pc_);
    1884             :           auto cond = Pop(0, kWasmI32);
    1885      277795 :           if (this->failed()) break;
    1886      554970 :           if (!this->Validate(this->pc_, imm, control_.size())) break;
    1887      277400 :           Control* c = control_at(imm.depth);
    1888      277400 :           if (!TypeCheckBranch(c)) break;
    1889      277113 :           if (control_.back().reachable()) {
    1890      170698 :             CALL_INTERFACE(BrIf, cond, imm.depth);
    1891      276554 :             c->br_merge()->reached = true;
    1892             :           }
    1893      277130 :           len = 1 + imm.length;
    1894      277130 :           break;
    1895             :         }
    1896             :         case kExprBrTable: {
    1897       12310 :           BranchTableImmediate<validate> imm(this, this->pc_);
    1898             :           BranchTableIterator<validate> iterator(this, imm);
    1899             :           auto key = Pop(0, kWasmI32);
    1900       12306 :           if (this->failed()) break;
    1901       12111 :           if (!this->Validate(this->pc_, imm, control_.size())) break;
    1902             :           uint32_t br_arity = 0;
    1903       12072 :           std::vector<bool> br_targets(control_.size());
    1904      520031 :           while (iterator.has_next()) {
    1905             :             const uint32_t i = iterator.cur_index();
    1906             :             const byte* pos = iterator.pc();
    1907      508420 :             uint32_t target = iterator.next();
    1908     1016840 :             if (!VALIDATE(target < control_.size())) {
    1909         201 :               this->errorf(pos,
    1910             :                            "improper branch in br_table target %u (depth %u)",
    1911             :                            i, target);
    1912         201 :               break;
    1913             :             }
    1914             :             // Avoid redundant branch target checks.
    1915      508219 :             if (br_targets[target]) continue;
    1916             :             br_targets[target] = true;
    1917             :             // Check that label types match up.
    1918             :             Control* c = control_at(target);
    1919       28211 :             uint32_t arity = c->br_merge()->arity;
    1920       28211 :             if (i == 0) {
    1921             :               br_arity = arity;
    1922       16207 :             } else if (!VALIDATE(br_arity == arity)) {
    1923          76 :               this->errorf(pos,
    1924             :                            "inconsistent arity in br_table target %u"
    1925             :                            " (previous was %u, this one %u)",
    1926             :                            i, br_arity, arity);
    1927             :             }
    1928       28211 :             if (!TypeCheckBranch(c)) break;
    1929             :           }
    1930       12071 :           if (this->failed()) break;
    1931             : 
    1932       11535 :           if (control_.back().reachable()) {
    1933        9938 :             CALL_INTERFACE(BrTable, imm, key);
    1934             : 
    1935       68260 :             for (uint32_t depth = control_depth(); depth-- > 0;) {
    1936      114302 :               if (!br_targets[depth]) continue;
    1937       27167 :               control_at(depth)->br_merge()->reached = true;
    1938             :             }
    1939             :           }
    1940             : 
    1941       11535 :           len = 1 + iterator.length();
    1942       11536 :           EndControl();
    1943       11536 :           break;
    1944             :         }
    1945             :         case kExprReturn: {
    1946      342796 :           if (!TypeCheckReturn()) break;
    1947      233814 :           DoReturn();
    1948      342084 :           EndControl();
    1949      341951 :           break;
    1950             :         }
    1951             :         case kExprUnreachable: {
    1952      149774 :           CALL_INTERFACE_IF_REACHABLE(Unreachable);
    1953      259462 :           EndControl();
    1954      259477 :           break;
    1955             :         }
    1956             :         case kExprI32Const: {
    1957     3131177 :           ImmI32Immediate<validate> imm(this, this->pc_);
    1958             :           auto* value = Push(kWasmI32);
    1959     3018775 :           CALL_INTERFACE_IF_REACHABLE(I32Const, value, imm.value);
    1960     3133367 :           len = 1 + imm.length;
    1961             :           break;
    1962             :         }
    1963             :         case kExprI64Const: {
    1964      106211 :           ImmI64Immediate<validate> imm(this, this->pc_);
    1965             :           auto* value = Push(kWasmI64);
    1966       71827 :           CALL_INTERFACE_IF_REACHABLE(I64Const, value, imm.value);
    1967      106273 :           len = 1 + imm.length;
    1968             :           break;
    1969             :         }
    1970             :         case kExprF32Const: {
    1971      281867 :           ImmF32Immediate<validate> imm(this, this->pc_);
    1972             :           auto* value = Push(kWasmF32);
    1973      163234 :           CALL_INTERFACE_IF_REACHABLE(F32Const, value, imm.value);
    1974      281895 :           len = 1 + imm.length;
    1975             :           break;
    1976             :         }
    1977             :         case kExprF64Const: {
    1978      288335 :           ImmF64Immediate<validate> imm(this, this->pc_);
    1979             :           auto* value = Push(kWasmF64);
    1980      170662 :           CALL_INTERFACE_IF_REACHABLE(F64Const, value, imm.value);
    1981      288367 :           len = 1 + imm.length;
    1982             :           break;
    1983             :         }
    1984             :         case kExprRefNull: {
    1985         208 :           CHECK_PROTOTYPE_OPCODE(anyref);
    1986             :           auto* value = Push(kWasmNullRef);
    1987         280 :           CALL_INTERFACE_IF_REACHABLE(RefNull, value);
    1988             :           len = 1;
    1989             :           break;
    1990             :         }
    1991             :         case kExprGetLocal: {
    1992      861277 :           LocalIndexImmediate<validate> imm(this, this->pc_);
    1993      861471 :           if (!this->Validate(this->pc_, imm)) break;
    1994      861034 :           auto* value = Push(imm.type);
    1995      801340 :           CALL_INTERFACE_IF_REACHABLE(GetLocal, value, imm);
    1996      861222 :           len = 1 + imm.length;
    1997      861222 :           break;
    1998             :         }
    1999             :         case kExprSetLocal: {
    2000      436977 :           LocalIndexImmediate<validate> imm(this, this->pc_);
    2001      436977 :           if (!this->Validate(this->pc_, imm)) break;
    2002      873588 :           auto value = Pop(0, local_type_vec_[imm.index]);
    2003      425231 :           CALL_INTERFACE_IF_REACHABLE(SetLocal, value, imm);
    2004      436803 :           len = 1 + imm.length;
    2005      436803 :           break;
    2006             :         }
    2007             :         case kExprTeeLocal: {
    2008      100840 :           LocalIndexImmediate<validate> imm(this, this->pc_);
    2009      100837 :           if (!this->Validate(this->pc_, imm)) break;
    2010      201672 :           auto value = Pop(0, local_type_vec_[imm.index]);
    2011             :           auto* result = Push(value.type);
    2012       99360 :           CALL_INTERFACE_IF_REACHABLE(TeeLocal, value, result, imm);
    2013      100835 :           len = 1 + imm.length;
    2014      100835 :           break;
    2015             :         }
    2016             :         case kExprDrop: {
    2017             :           auto value = Pop();
    2018        1358 :           CALL_INTERFACE_IF_REACHABLE(Drop, value);
    2019             :           break;
    2020             :         }
    2021             :         case kExprGetGlobal: {
    2022       36800 :           GlobalIndexImmediate<validate> imm(this, this->pc_);
    2023       36804 :           len = 1 + imm.length;
    2024       36804 :           if (!this->Validate(this->pc_, imm)) break;
    2025       36775 :           auto* result = Push(imm.type);
    2026       35969 :           CALL_INTERFACE_IF_REACHABLE(GetGlobal, result, imm);
    2027             :           break;
    2028             :         }
    2029             :         case kExprSetGlobal: {
    2030       18617 :           GlobalIndexImmediate<validate> imm(this, this->pc_);
    2031       18617 :           len = 1 + imm.length;
    2032       18617 :           if (!this->Validate(this->pc_, imm)) break;
    2033       18617 :           if (!VALIDATE(imm.global->mutability)) {
    2034          29 :             this->errorf(this->pc_, "immutable global #%u cannot be assigned",
    2035             :                          imm.index);
    2036          29 :             break;
    2037             :           }
    2038       18588 :           auto value = Pop(0, imm.type);
    2039       17989 :           CALL_INTERFACE_IF_REACHABLE(SetGlobal, value, imm);
    2040             :           break;
    2041             :         }
    2042             :         case kExprGetTable: {
    2043          96 :           CHECK_PROTOTYPE_OPCODE(anyref);
    2044          96 :           TableIndexImmediate<validate> imm(this, this->pc_);
    2045          96 :           len = 1 + imm.length;
    2046          96 :           if (!this->Validate(this->pc_, imm)) break;
    2047             :           DCHECK_NOT_NULL(this->module_);
    2048             :           auto index = Pop(0, kWasmI32);
    2049         188 :           auto* result = Push(this->module_->tables[imm.index].type);
    2050         104 :           CALL_INTERFACE_IF_REACHABLE(GetTable, index, result, imm);
    2051             :           break;
    2052             :         }
    2053             :         case kExprSetTable: {
    2054          56 :           CHECK_PROTOTYPE_OPCODE(anyref);
    2055          56 :           TableIndexImmediate<validate> imm(this, this->pc_);
    2056          56 :           len = 1 + imm.length;
    2057          56 :           if (!this->Validate(this->pc_, imm)) break;
    2058         108 :           auto value = Pop(0, this->module_->tables[imm.index].type);
    2059             :           auto index = Pop(0, kWasmI32);
    2060          59 :           CALL_INTERFACE_IF_REACHABLE(SetTable, index, value, imm);
    2061             :           break;
    2062             :         }
    2063             : 
    2064             :         case kExprI32LoadMem8S:
    2065        4134 :           len = 1 + DecodeLoadMem(LoadType::kI32Load8S);
    2066        4134 :           break;
    2067             :         case kExprI32LoadMem8U:
    2068        1504 :           len = 1 + DecodeLoadMem(LoadType::kI32Load8U);
    2069        1502 :           break;
    2070             :         case kExprI32LoadMem16S:
    2071         422 :           len = 1 + DecodeLoadMem(LoadType::kI32Load16S);
    2072         422 :           break;
    2073             :         case kExprI32LoadMem16U:
    2074         650 :           len = 1 + DecodeLoadMem(LoadType::kI32Load16U);
    2075         650 :           break;
    2076             :         case kExprI32LoadMem:
    2077       85434 :           len = 1 + DecodeLoadMem(LoadType::kI32Load);
    2078       85193 :           break;
    2079             :         case kExprI64LoadMem8S:
    2080         436 :           len = 1 + DecodeLoadMem(LoadType::kI64Load8S);
    2081         436 :           break;
    2082             :         case kExprI64LoadMem8U:
    2083         357 :           len = 1 + DecodeLoadMem(LoadType::kI64Load8U);
    2084         357 :           break;
    2085             :         case kExprI64LoadMem16S:
    2086         400 :           len = 1 + DecodeLoadMem(LoadType::kI64Load16S);
    2087         400 :           break;
    2088             :         case kExprI64LoadMem16U:
    2089         393 :           len = 1 + DecodeLoadMem(LoadType::kI64Load16U);
    2090         393 :           break;
    2091             :         case kExprI64LoadMem32S:
    2092         418 :           len = 1 + DecodeLoadMem(LoadType::kI64Load32S);
    2093         418 :           break;
    2094             :         case kExprI64LoadMem32U:
    2095         414 :           len = 1 + DecodeLoadMem(LoadType::kI64Load32U);
    2096         414 :           break;
    2097             :         case kExprI64LoadMem:
    2098       84489 :           len = 1 + DecodeLoadMem(LoadType::kI64Load);
    2099       84490 :           break;
    2100             :         case kExprF32LoadMem:
    2101        2689 :           len = 1 + DecodeLoadMem(LoadType::kF32Load);
    2102        2689 :           break;
    2103             :         case kExprF64LoadMem:
    2104        3436 :           len = 1 + DecodeLoadMem(LoadType::kF64Load);
    2105        3437 :           break;
    2106             :         case kExprI32StoreMem8:
    2107        1859 :           len = 1 + DecodeStoreMem(StoreType::kI32Store8);
    2108        1859 :           break;
    2109             :         case kExprI32StoreMem16:
    2110         696 :           len = 1 + DecodeStoreMem(StoreType::kI32Store16);
    2111         695 :           break;
    2112             :         case kExprI32StoreMem:
    2113      160402 :           len = 1 + DecodeStoreMem(StoreType::kI32Store);
    2114      160446 :           break;
    2115             :         case kExprI64StoreMem8:
    2116         306 :           len = 1 + DecodeStoreMem(StoreType::kI64Store8);
    2117         306 :           break;
    2118             :         case kExprI64StoreMem16:
    2119         428 :           len = 1 + DecodeStoreMem(StoreType::kI64Store16);
    2120         428 :           break;
    2121             :         case kExprI64StoreMem32:
    2122         392 :           len = 1 + DecodeStoreMem(StoreType::kI64Store32);
    2123         392 :           break;
    2124             :         case kExprI64StoreMem:
    2125       96741 :           len = 1 + DecodeStoreMem(StoreType::kI64Store);
    2126       96728 :           break;
    2127             :         case kExprF32StoreMem:
    2128         703 :           len = 1 + DecodeStoreMem(StoreType::kF32Store);
    2129         703 :           break;
    2130             :         case kExprF64StoreMem:
    2131        1352 :           len = 1 + DecodeStoreMem(StoreType::kF64Store);
    2132        1352 :           break;
    2133             :         case kExprMemoryGrow: {
    2134        2705 :           if (!CheckHasMemory()) break;
    2135        2655 :           MemoryIndexImmediate<validate> imm(this, this->pc_);
    2136        2655 :           len = 1 + imm.length;
    2137             :           DCHECK_NOT_NULL(this->module_);
    2138        2655 :           if (!VALIDATE(this->module_->origin == kWasmOrigin)) {
    2139           1 :             this->error("grow_memory is not supported for asmjs modules");
    2140           1 :             break;
    2141             :           }
    2142             :           auto value = Pop(0, kWasmI32);
    2143             :           auto* result = Push(kWasmI32);
    2144        3151 :           CALL_INTERFACE_IF_REACHABLE(MemoryGrow, value, result);
    2145             :           break;
    2146             :         }
    2147             :         case kExprMemorySize: {
    2148         930 :           if (!CheckHasMemory()) break;
    2149         901 :           MemoryIndexImmediate<validate> imm(this, this->pc_);
    2150             :           auto* result = Push(kWasmI32);
    2151         902 :           len = 1 + imm.length;
    2152         952 :           CALL_INTERFACE_IF_REACHABLE(CurrentMemoryPages, result);
    2153             :           break;
    2154             :         }
    2155             :         case kExprCallFunction: {
    2156      302999 :           CallFunctionImmediate<validate> imm(this, this->pc_);
    2157      302948 :           len = 1 + imm.length;
    2158      302948 :           if (!this->Validate(this->pc_, imm)) break;
    2159             :           // TODO(clemensh): Better memory management.
    2160      302891 :           PopArgs(imm.sig);
    2161      302901 :           auto* returns = PushReturns(imm.sig);
    2162      188277 :           CALL_INTERFACE_IF_REACHABLE(CallDirect, imm, args_.data(), returns);
    2163             :           break;
    2164             :         }
    2165             :         case kExprCallIndirect: {
    2166        7791 :           CallIndirectImmediate<validate> imm(this->enabled_, this, this->pc_);
    2167        7790 :           len = 1 + imm.length;
    2168        7790 :           if (!this->Validate(this->pc_, imm)) break;
    2169             :           auto index = Pop(0, kWasmI32);
    2170        7627 :           PopArgs(imm.sig);
    2171        7626 :           auto* returns = PushReturns(imm.sig);
    2172        5648 :           CALL_INTERFACE_IF_REACHABLE(CallIndirect, index, imm, args_.data(),
    2173             :                                       returns);
    2174             :           break;
    2175             :         }
    2176             :         case kExprReturnCall: {
    2177         224 :           CHECK_PROTOTYPE_OPCODE(return_call);
    2178             : 
    2179         224 :           CallFunctionImmediate<validate> imm(this, this->pc_);
    2180         223 :           len = 1 + imm.length;
    2181         223 :           if (!this->Validate(this->pc_, imm)) break;
    2182         448 :           if (!this->CanReturnCall(imm.sig)) {
    2183           4 :             OPCODE_ERROR(opcode, "tail call return types mismatch");
    2184           4 :             break;
    2185             :           }
    2186             : 
    2187             :           PopArgs(imm.sig);
    2188             : 
    2189         212 :           CALL_INTERFACE_IF_REACHABLE(ReturnCall, imm, args_.data());
    2190         219 :           EndControl();
    2191         219 :           break;
    2192             :         }
    2193             :         case kExprReturnCallIndirect: {
    2194         115 :           CHECK_PROTOTYPE_OPCODE(return_call);
    2195         114 :           CallIndirectImmediate<validate> imm(this->enabled_, this, this->pc_);
    2196         114 :           len = 1 + imm.length;
    2197         114 :           if (!this->Validate(this->pc_, imm)) break;
    2198         198 :           if (!this->CanReturnCall(imm.sig)) {
    2199           0 :             OPCODE_ERROR(opcode, "tail call return types mismatch");
    2200           0 :             break;
    2201             :           }
    2202             :           auto index = Pop(0, kWasmI32);
    2203          99 :           PopArgs(imm.sig);
    2204          94 :           CALL_INTERFACE_IF_REACHABLE(ReturnCallIndirect, index, imm,
    2205             :                                       args_.data());
    2206          99 :           EndControl();
    2207          99 :           break;
    2208             :         }
    2209             :         case kNumericPrefix: {
    2210             :           ++len;
    2211             :           byte numeric_index =
    2212         564 :               this->template read_u8<validate>(this->pc_ + 1, "numeric index");
    2213         564 :           opcode = static_cast<WasmOpcode>(opcode << 8 | numeric_index);
    2214         564 :           if (opcode < kExprMemoryInit) {
    2215          98 :             CHECK_PROTOTYPE_OPCODE(sat_f2i_conversions);
    2216             :           } else {
    2217         466 :             CHECK_PROTOTYPE_OPCODE(bulk_memory);
    2218             :           }
    2219             :           TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    2220             :                      WasmOpcodes::OpcodeName(opcode));
    2221         555 :           len += DecodeNumericOpcode(opcode);
    2222         554 :           break;
    2223             :         }
    2224             :         case kSimdPrefix: {
    2225       19633 :           CHECK_PROTOTYPE_OPCODE(simd);
    2226             :           len++;
    2227             :           byte simd_index =
    2228       19633 :               this->template read_u8<validate>(this->pc_ + 1, "simd index");
    2229       19633 :           opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
    2230             :           TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    2231             :                      WasmOpcodes::OpcodeName(opcode));
    2232       19633 :           len += DecodeSimdOpcode(opcode);
    2233       19633 :           break;
    2234             :         }
    2235             :         case kAtomicPrefix: {
    2236       47477 :           CHECK_PROTOTYPE_OPCODE(threads);
    2237       47477 :           if (!CheckHasSharedMemory()) break;
    2238             :           len++;
    2239             :           byte atomic_index =
    2240       47455 :               this->template read_u8<validate>(this->pc_ + 1, "atomic index");
    2241       47570 :           opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_index);
    2242             :           TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    2243             :                      WasmOpcodes::OpcodeName(opcode));
    2244       47570 :           len += DecodeAtomicOpcode(opcode);
    2245       47920 :           break;
    2246             :         }
    2247             : // Note that prototype opcodes are not handled in the fastpath
    2248             : // above this switch, to avoid checking a feature flag.
    2249             : #define SIMPLE_PROTOTYPE_CASE(name, opc, sig) \
    2250             :   case kExpr##name: /* fallthrough */
    2251             :           FOREACH_SIMPLE_PROTOTYPE_OPCODE(SIMPLE_PROTOTYPE_CASE)
    2252             : #undef SIMPLE_PROTOTYPE_CASE
    2253         130 :           BuildSimplePrototypeOperator(opcode);
    2254         130 :           break;
    2255             :         default: {
    2256             :           // Deal with special asmjs opcodes.
    2257      200402 :           if (this->module_ != nullptr &&
    2258      100201 :               this->module_->origin == kAsmJsOrigin) {
    2259      100170 :             FunctionSig* sig = WasmOpcodes::AsmjsSignature(opcode);
    2260      100170 :             if (sig) {
    2261      100170 :               BuildSimpleOperator(opcode, sig);
    2262             :             }
    2263             :           } else {
    2264          31 :             this->error("Invalid opcode");
    2265          31 :             return;
    2266             :           }
    2267             :         }
    2268             :       }
    2269             : 
    2270             : #if DEBUG
    2271             :       if (FLAG_trace_wasm_decoder) {
    2272             :         TRACE_PART(" ");
    2273             :         for (Control& c : control_) {
    2274             :           switch (c.kind) {
    2275             :             case kControlIf:
    2276             :               TRACE_PART("I");
    2277             :               break;
    2278             :             case kControlBlock:
    2279             :               TRACE_PART("B");
    2280             :               break;
    2281             :             case kControlLoop:
    2282             :               TRACE_PART("L");
    2283             :               break;
    2284             :             case kControlTry:
    2285             :               TRACE_PART("T");
    2286             :               break;
    2287             :             default:
    2288             :               break;
    2289             :           }
    2290             :           if (c.start_merge.arity) TRACE_PART("%u-", c.start_merge.arity);
    2291             :           TRACE_PART("%u", c.end_merge.arity);
    2292             :           if (!c.reachable()) TRACE_PART("%c", c.unreachable() ? '*' : '#');
    2293             :         }
    2294             :         TRACE_PART(" | ");
    2295             :         for (size_t i = 0; i < stack_.size(); ++i) {
    2296             :           auto& val = stack_[i];
    2297             :           WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
    2298             :           if (WasmOpcodes::IsPrefixOpcode(opcode)) {
    2299             :             opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1));
    2300             :           }
    2301             :           TRACE_PART(" %c@%d:%s", ValueTypes::ShortNameOf(val.type),
    2302             :                      static_cast<int>(val.pc - this->start_),
    2303             :                      WasmOpcodes::OpcodeName(opcode));
    2304             :           // If the decoder failed, don't try to decode the immediates, as this
    2305             :           // can trigger a DCHECK failure.
    2306             :           if (this->failed()) continue;
    2307             :           switch (opcode) {
    2308             :             case kExprI32Const: {
    2309             :               ImmI32Immediate<Decoder::kNoValidate> imm(this, val.pc);
    2310             :               TRACE_PART("[%d]", imm.value);
    2311             :               break;
    2312             :             }
    2313             :             case kExprGetLocal:
    2314             :             case kExprSetLocal:
    2315             :             case kExprTeeLocal: {
    2316             :               LocalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
    2317             :               TRACE_PART("[%u]", imm.index);
    2318             :               break;
    2319             :             }
    2320             :             case kExprGetGlobal:
    2321             :             case kExprSetGlobal: {
    2322             :               GlobalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
    2323             :               TRACE_PART("[%u]", imm.index);
    2324             :               break;
    2325             :             }
    2326             :             default:
    2327             :               break;
    2328             :           }
    2329             :         }
    2330             :       }
    2331             : #endif
    2332    12416467 :       this->pc_ += len;
    2333             :     }  // end decode loop
    2334     1257906 :     if (!VALIDATE(this->pc_ == this->end_) && this->ok()) {
    2335           0 :       this->error("Beyond end of code");
    2336             :     }
    2337             :   }
    2338             : 
    2339      642550 :   void EndControl() {
    2340             :     DCHECK(!control_.empty());
    2341             :     auto* current = &control_.back();
    2342     1285100 :     stack_.erase(stack_.begin() + current->stack_depth, stack_.end());
    2343      315590 :     CALL_INTERFACE_IF_REACHABLE(EndControl, current);
    2344      642609 :     current->reachability = kUnreachable;
    2345      642609 :   }
    2346             : 
    2347             :   template<typename func>
    2348     2086128 :   void InitMerge(Merge<Value>* merge, uint32_t arity, func get_val) {
    2349     3343885 :     merge->arity = arity;
    2350     2086128 :     if (arity == 1) {
    2351      969499 :       merge->vals.first = get_val(0);
    2352     1116629 :     } else if (arity > 1) {
    2353        6196 :       merge->vals.array = zone_->NewArray<Value>(arity);
    2354       15526 :       for (uint32_t i = 0; i < arity; i++) {
    2355       12428 :         merge->vals.array[i] = get_val(i);
    2356             :       }
    2357             :     }
    2358     2086128 :   }
    2359             : 
    2360      414297 :   void SetBlockType(Control* c, BlockTypeImmediate<validate>& imm) {
    2361             :     DCHECK_EQ(imm.in_arity(), this->args_.size());
    2362      414297 :     const byte* pc = this->pc_;
    2363             :     Value* args = this->args_.data();
    2364      828594 :     InitMerge(&c->end_merge, imm.out_arity(), [pc, &imm](uint32_t i) {
    2365             :       return Value{pc, imm.out_type(i)};
    2366             :     });
    2367      828600 :     InitMerge(&c->start_merge, imm.in_arity(),
    2368         197 :               [args](uint32_t i) { return args[i]; });
    2369      414286 :   }
    2370             : 
    2371             :   // Pops arguments as required by signature into {args_}.
    2372             :   V8_INLINE void PopArgs(FunctionSig* sig) {
    2373      778614 :     int count = sig ? static_cast<int>(sig->parameter_count()) : 0;
    2374      778614 :     args_.resize(count, UnreachableValue(nullptr));
    2375     1497018 :     for (int i = count - 1; i >= 0; --i) {
    2376     1436254 :       args_[i] = Pop(i, sig->GetParam(i));
    2377             :     }
    2378             :   }
    2379             : 
    2380             :   ValueType GetReturnType(FunctionSig* sig) {
    2381             :     DCHECK_GE(1, sig->return_count());
    2382       89768 :     return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn();
    2383             :   }
    2384             : 
    2385     1672033 :   Control* PushControl(ControlKind kind) {
    2386             :     Reachability reachability =
    2387     3344066 :         control_.empty() ? kReachable : control_.back().innerReachability();
    2388     3344066 :     control_.emplace_back(kind, stack_size(), this->pc_, reachability);
    2389     1672056 :     return &control_.back();
    2390             :   }
    2391             : 
    2392      398728 :   void PopControl(Control* c) {
    2393             :     DCHECK_EQ(c, &control_.back());
    2394      555899 :     CALL_INTERFACE_IF_PARENT_REACHABLE(PopControl, c);
    2395             : 
    2396             :     // A loop just leaves the values on the stack.
    2397      398768 :     if (!c->is_loop()) PushMergeValues(c, &c->end_merge);
    2398             : 
    2399             :     bool parent_reached =
    2400      398773 :         c->reachable() || c->end_merge.reached || c->is_onearmed_if();
    2401             :     control_.pop_back();
    2402             :     // If the parent block was reachable before, but the popped control does not
    2403             :     // return to here, this block becomes "spec only reachable".
    2404      398768 :     if (!parent_reached && control_.back().reachable()) {
    2405       38264 :       control_.back().reachability = kSpecOnlyReachable;
    2406             :     }
    2407      398768 :   }
    2408             : 
    2409      184987 :   int DecodeLoadMem(LoadType type, int prefix_len = 0) {
    2410      185106 :     if (!CheckHasMemory()) return 0;
    2411      185047 :     MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
    2412      185047 :                                         type.size_log_2());
    2413             :     auto index = Pop(0, kWasmI32);
    2414             :     auto* result = Push(type.value_type());
    2415      172641 :     CALL_INTERFACE_IF_REACHABLE(LoadMem, type, imm, index, result);
    2416      185146 :     return imm.length;
    2417             :   }
    2418             : 
    2419      262804 :   int DecodeStoreMem(StoreType store, int prefix_len = 0) {
    2420      262990 :     if (!CheckHasMemory()) return 0;
    2421      262932 :     MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
    2422      262932 :                                         store.size_log_2());
    2423             :     auto value = Pop(1, store.value_type());
    2424             :     auto index = Pop(0, kWasmI32);
    2425      251707 :     CALL_INTERFACE_IF_REACHABLE(StoreMem, store, imm, index, value);
    2426      263200 :     return imm.length;
    2427             :   }
    2428             : 
    2429         360 :   uint32_t SimdExtractLane(WasmOpcode opcode, ValueType type) {
    2430         360 :     SimdLaneImmediate<validate> imm(this, this->pc_);
    2431         360 :     if (this->Validate(this->pc_, opcode, imm)) {
    2432           0 :       Value inputs[] = {Pop(0, kWasmS128)};
    2433             :       auto* result = Push(type);
    2434         360 :       CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
    2435             :                                   result);
    2436             :     }
    2437         360 :     return imm.length;
    2438             :   }
    2439             : 
    2440         424 :   uint32_t SimdReplaceLane(WasmOpcode opcode, ValueType type) {
    2441         424 :     SimdLaneImmediate<validate> imm(this, this->pc_);
    2442         424 :     if (this->Validate(this->pc_, opcode, imm)) {
    2443         424 :       Value inputs[2] = {UnreachableValue(this->pc_),
    2444           0 :                          UnreachableValue(this->pc_)};
    2445         424 :       inputs[1] = Pop(1, type);
    2446         424 :       inputs[0] = Pop(0, kWasmS128);
    2447             :       auto* result = Push(kWasmS128);
    2448         424 :       CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
    2449             :                                   result);
    2450             :     }
    2451         424 :     return imm.length;
    2452             :   }
    2453             : 
    2454        1272 :   uint32_t SimdShiftOp(WasmOpcode opcode) {
    2455        1272 :     SimdShiftImmediate<validate> imm(this, this->pc_);
    2456        1272 :     if (this->Validate(this->pc_, opcode, imm)) {
    2457             :       auto input = Pop(0, kWasmS128);
    2458             :       auto* result = Push(kWasmS128);
    2459        1272 :       CALL_INTERFACE_IF_REACHABLE(SimdShiftOp, opcode, imm, input, result);
    2460             :     }
    2461        1272 :     return imm.length;
    2462             :   }
    2463             : 
    2464       13233 :   uint32_t Simd8x16ShuffleOp() {
    2465       13233 :     Simd8x16ShuffleImmediate<validate> imm(this, this->pc_);
    2466       13233 :     if (this->Validate(this->pc_, imm)) {
    2467             :       auto input1 = Pop(1, kWasmS128);
    2468             :       auto input0 = Pop(0, kWasmS128);
    2469             :       auto* result = Push(kWasmS128);
    2470       13232 :       CALL_INTERFACE_IF_REACHABLE(Simd8x16ShuffleOp, imm, input0, input1,
    2471             :                                   result);
    2472             :     }
    2473       13233 :     return 16;
    2474             :   }
    2475             : 
    2476       19633 :   uint32_t DecodeSimdOpcode(WasmOpcode opcode) {
    2477             :     uint32_t len = 0;
    2478       19633 :     switch (opcode) {
    2479             :       case kExprF32x4ExtractLane: {
    2480          64 :         len = SimdExtractLane(opcode, kWasmF32);
    2481          64 :         break;
    2482             :       }
    2483             :       case kExprI32x4ExtractLane:
    2484             :       case kExprI16x8ExtractLane:
    2485             :       case kExprI8x16ExtractLane: {
    2486         296 :         len = SimdExtractLane(opcode, kWasmI32);
    2487         296 :         break;
    2488             :       }
    2489             :       case kExprF32x4ReplaceLane: {
    2490          64 :         len = SimdReplaceLane(opcode, kWasmF32);
    2491          64 :         break;
    2492             :       }
    2493             :       case kExprI32x4ReplaceLane:
    2494             :       case kExprI16x8ReplaceLane:
    2495             :       case kExprI8x16ReplaceLane: {
    2496         360 :         len = SimdReplaceLane(opcode, kWasmI32);
    2497         360 :         break;
    2498             :       }
    2499             :       case kExprI32x4Shl:
    2500             :       case kExprI32x4ShrS:
    2501             :       case kExprI32x4ShrU:
    2502             :       case kExprI16x8Shl:
    2503             :       case kExprI16x8ShrS:
    2504             :       case kExprI16x8ShrU:
    2505             :       case kExprI8x16Shl:
    2506             :       case kExprI8x16ShrS:
    2507             :       case kExprI8x16ShrU: {
    2508        1272 :         len = SimdShiftOp(opcode);
    2509        1272 :         break;
    2510             :       }
    2511             :       case kExprS8x16Shuffle: {
    2512       13233 :         len = Simd8x16ShuffleOp();
    2513       13233 :         break;
    2514             :       }
    2515             :       case kExprS128LoadMem:
    2516          16 :         len = DecodeLoadMem(LoadType::kS128Load, 1);
    2517          16 :         break;
    2518             :       case kExprS128StoreMem:
    2519           8 :         len = DecodeStoreMem(StoreType::kS128Store, 1);
    2520           8 :         break;
    2521             :       default: {
    2522        4320 :         FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2523        4320 :         if (!VALIDATE(sig != nullptr)) {
    2524           0 :           this->error("invalid simd opcode");
    2525           0 :           break;
    2526             :         }
    2527             :         PopArgs(sig);
    2528             :         auto* results =
    2529        4320 :             sig->return_count() == 0 ? nullptr : Push(GetReturnType(sig));
    2530        8640 :         CALL_INTERFACE_IF_REACHABLE(SimdOp, opcode, VectorOf(args_), results);
    2531             :       }
    2532             :     }
    2533       19633 :     return len;
    2534             :   }
    2535             : 
    2536       47547 :   uint32_t DecodeAtomicOpcode(WasmOpcode opcode) {
    2537             :     uint32_t len = 0;
    2538             :     ValueType ret_type;
    2539       47547 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2540       47487 :     if (sig != nullptr) {
    2541             :       MachineType memtype;
    2542       47487 :       switch (opcode) {
    2543             : #define CASE_ATOMIC_STORE_OP(Name, Type) \
    2544             :   case kExpr##Name: {                    \
    2545             :     memtype = MachineType::Type();       \
    2546             :     ret_type = kWasmStmt;                \
    2547             :     break;                               \
    2548             :   }
    2549         422 :         ATOMIC_STORE_OP_LIST(CASE_ATOMIC_STORE_OP)
    2550             : #undef CASE_ATOMIC_OP
    2551             : #define CASE_ATOMIC_OP(Name, Type) \
    2552             :   case kExpr##Name: {              \
    2553             :     memtype = MachineType::Type(); \
    2554             :     ret_type = GetReturnType(sig); \
    2555             :     break;                         \
    2556             :   }
    2557       42899 :         ATOMIC_OP_LIST(CASE_ATOMIC_OP)
    2558             : #undef CASE_ATOMIC_OP
    2559             :         default:
    2560           0 :           this->error("invalid atomic opcode");
    2561           0 :           return 0;
    2562             :       }
    2563             :       MemoryAccessImmediate<validate> imm(
    2564       47487 :           this, this->pc_ + 1, ElementSizeLog2Of(memtype.representation()));
    2565       47582 :       len += imm.length;
    2566             :       PopArgs(sig);
    2567       47885 :       auto result = ret_type == kWasmStmt ? nullptr : Push(GetReturnType(sig));
    2568       81510 :       CALL_INTERFACE_IF_REACHABLE(AtomicOp, opcode, VectorOf(args_), imm,
    2569             :                                   result);
    2570             :     } else {
    2571           0 :       this->error("invalid atomic opcode");
    2572             :     }
    2573             :     return len;
    2574             :   }
    2575             : 
    2576         555 :   unsigned DecodeNumericOpcode(WasmOpcode opcode) {
    2577             :     unsigned len = 0;
    2578         555 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2579         555 :     if (sig != nullptr) {
    2580         555 :       switch (opcode) {
    2581             :         case kExprI32SConvertSatF32:
    2582             :         case kExprI32UConvertSatF32:
    2583             :         case kExprI32SConvertSatF64:
    2584             :         case kExprI32UConvertSatF64:
    2585             :         case kExprI64SConvertSatF32:
    2586             :         case kExprI64UConvertSatF32:
    2587             :         case kExprI64SConvertSatF64:
    2588             :         case kExprI64UConvertSatF64:
    2589          96 :           BuildSimpleOperator(opcode, sig);
    2590          96 :           break;
    2591             :         case kExprMemoryInit: {
    2592         106 :           MemoryInitImmediate<validate> imm(this, this->pc_);
    2593         105 :           if (!this->Validate(imm)) break;
    2594         104 :           len += imm.length;
    2595             :           auto size = Pop(2, sig->GetParam(2));
    2596             :           auto src = Pop(1, sig->GetParam(1));
    2597             :           auto dst = Pop(0, sig->GetParam(0));
    2598         108 :           CALL_INTERFACE_IF_REACHABLE(MemoryInit, imm, dst, src, size);
    2599             :           break;
    2600             :         }
    2601             :         case kExprDataDrop: {
    2602          68 :           DataDropImmediate<validate> imm(this, this->pc_);
    2603          68 :           if (!this->Validate(imm)) break;
    2604          67 :           len += imm.length;
    2605          68 :           CALL_INTERFACE_IF_REACHABLE(DataDrop, imm);
    2606             :           break;
    2607             :         }
    2608             :         case kExprMemoryCopy: {
    2609          64 :           MemoryCopyImmediate<validate> imm(this, this->pc_);
    2610          64 :           if (!this->Validate(imm)) break;
    2611          63 :           len += imm.length;
    2612             :           auto size = Pop(2, sig->GetParam(2));
    2613             :           auto src = Pop(1, sig->GetParam(1));
    2614             :           auto dst = Pop(0, sig->GetParam(0));
    2615          64 :           CALL_INTERFACE_IF_REACHABLE(MemoryCopy, imm, dst, src, size);
    2616             :           break;
    2617             :         }
    2618             :         case kExprMemoryFill: {
    2619          64 :           MemoryIndexImmediate<validate> imm(this, this->pc_ + 1);
    2620         128 :           if (!this->Validate(this->pc_ + 1, imm)) break;
    2621          63 :           len += imm.length;
    2622             :           auto size = Pop(2, sig->GetParam(2));
    2623             :           auto value = Pop(1, sig->GetParam(1));
    2624             :           auto dst = Pop(0, sig->GetParam(0));
    2625          64 :           CALL_INTERFACE_IF_REACHABLE(MemoryFill, imm, dst, value, size);
    2626             :           break;
    2627             :         }
    2628             :         case kExprTableInit: {
    2629          40 :           TableInitImmediate<validate> imm(this, this->pc_);
    2630          40 :           if (!this->Validate(imm)) break;
    2631          37 :           len += imm.length;
    2632             :           PopArgs(sig);
    2633          64 :           CALL_INTERFACE_IF_REACHABLE(TableInit, imm, VectorOf(args_));
    2634             :           break;
    2635             :         }
    2636             :         case kExprElemDrop: {
    2637          41 :           ElemDropImmediate<validate> imm(this, this->pc_);
    2638          41 :           if (!this->Validate(imm)) break;
    2639          39 :           len += imm.length;
    2640          40 :           CALL_INTERFACE_IF_REACHABLE(ElemDrop, imm);
    2641             :           break;
    2642             :         }
    2643             :         case kExprTableCopy: {
    2644          76 :           TableCopyImmediate<validate> imm(this, this->pc_);
    2645          76 :           if (!this->Validate(imm)) break;
    2646          75 :           len += imm.length;
    2647             :           PopArgs(sig);
    2648         127 :           CALL_INTERFACE_IF_REACHABLE(TableCopy, imm, VectorOf(args_));
    2649             :           break;
    2650             :         }
    2651             :         default:
    2652           0 :           this->error("invalid numeric opcode");
    2653           0 :           break;
    2654             :       }
    2655             :     } else {
    2656           0 :       this->error("invalid numeric opcode");
    2657             :     }
    2658         554 :     return len;
    2659             :   }
    2660             : 
    2661     1294357 :   void DoReturn() {
    2662      794764 :     size_t return_count = this->sig_->return_count();
    2663             :     DCHECK_GE(stack_.size(), return_count);
    2664             :     Vector<Value> return_values =
    2665             :         return_count == 0
    2666             :             ? Vector<Value>{}
    2667      794764 :             : Vector<Value>{&*(stack_.end() - return_count), return_count};
    2668             : 
    2669     1294357 :     CALL_INTERFACE_IF_REACHABLE(DoReturn, return_values);
    2670     1294336 :   }
    2671             : 
    2672             :   inline Value* Push(ValueType type) {
    2673             :     DCHECK_NE(kWasmStmt, type);
    2674     7751582 :     stack_.emplace_back(this->pc_, type);
    2675             :     return &stack_.back();
    2676             :   }
    2677             : 
    2678      820558 :   void PushMergeValues(Control* c, Merge<Value>* merge) {
    2679             :     DCHECK_EQ(c, &control_.back());
    2680             :     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
    2681     1641116 :     stack_.erase(stack_.begin() + c->stack_depth, stack_.end());
    2682      820591 :     if (merge->arity == 1) {
    2683       18095 :       stack_.push_back(merge->vals.first);
    2684             :     } else {
    2685      803152 :       for (uint32_t i = 0; i < merge->arity; i++) {
    2686         329 :         stack_.push_back(merge->vals.array[i]);
    2687             :       }
    2688             :     }
    2689             :     DCHECK_EQ(c->stack_depth + merge->arity, stack_.size());
    2690      820590 :   }
    2691             : 
    2692      310500 :   Value* PushReturns(FunctionSig* sig) {
    2693             :     size_t return_count = sig->return_count();
    2694      310500 :     if (return_count == 0) return nullptr;
    2695             :     size_t old_size = stack_.size();
    2696      851920 :     for (size_t i = 0; i < return_count; ++i) {
    2697             :       Push(sig->GetReturn(i));
    2698             :     }
    2699      282048 :     return stack_.data() + old_size;
    2700             :   }
    2701             : 
    2702             :   V8_INLINE Value Pop(int index, ValueType expected) {
    2703             :     auto val = Pop();
    2704     6551009 :     if (!VALIDATE(ValueTypes::IsSubType(expected, val.type) ||
    2705             :                   val.type == kWasmVar || expected == kWasmVar)) {
    2706      103885 :       this->errorf(val.pc, "%s[%d] expected type %s, found %s of type %s",
    2707             :                    SafeOpcodeNameAt(this->pc_), index,
    2708             :                    ValueTypes::TypeName(expected), SafeOpcodeNameAt(val.pc),
    2709             :                    ValueTypes::TypeName(val.type));
    2710             :     }
    2711             :     return val;
    2712             :   }
    2713             : 
    2714             :   V8_INLINE Value Pop() {
    2715             :     DCHECK(!control_.empty());
    2716     6735395 :     uint32_t limit = control_.back().stack_depth;
    2717     6735395 :     if (stack_.size() <= limit) {
    2718             :       // Popping past the current control start in reachable code.
    2719       15868 :       if (!VALIDATE(control_.back().unreachable())) {
    2720       17209 :         this->errorf(this->pc_, "%s found empty stack",
    2721             :                      SafeOpcodeNameAt(this->pc_));
    2722             :       }
    2723       15140 :       return UnreachableValue(this->pc_);
    2724             :     }
    2725     6538711 :     auto val = stack_.back();
    2726             :     stack_.pop_back();
    2727     3141453 :     return val;
    2728             :   }
    2729             : 
    2730        6211 :   int startrel(const byte* ptr) { return static_cast<int>(ptr - this->start_); }
    2731             : 
    2732         499 :   void FallThruTo(Control* c) {
    2733             :     DCHECK_EQ(c, &control_.back());
    2734         774 :     if (!TypeCheckFallThru(c)) return;
    2735         775 :     if (!c->reachable()) return;
    2736             : 
    2737         270 :     if (!c->is_loop()) CALL_INTERFACE(FallThruTo, c);
    2738         377 :     c->end_merge.reached = true;
    2739             :   }
    2740             : 
    2741      948616 :   bool TypeCheckMergeValues(Control* c, Merge<Value>* merge) {
    2742             :     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
    2743             :     DCHECK_GE(stack_.size(), c->stack_depth + merge->arity);
    2744             :     // The computation of {stack_values} is only valid if {merge->arity} is >0.
    2745             :     DCHECK_LT(0, merge->arity);
    2746      948616 :     Value* stack_values = &*(stack_.end() - merge->arity);
    2747             :     // Typecheck the topmost {merge->arity} values on the stack.
    2748     2840118 :     for (uint32_t i = 0; i < merge->arity; ++i) {
    2749      950689 :       Value& val = stack_values[i];
    2750             :       Value& old = (*merge)[i];
    2751      950689 :       if (ValueTypes::IsSubType(old.type, val.type)) continue;
    2752             :       // If {val.type} is polymorphic, which results from unreachable, make
    2753             :       // it more specific by using the merge value's expected type.
    2754             :       // If it is not polymorphic, this is a type error.
    2755       28100 :       if (!VALIDATE(val.type == kWasmVar)) {
    2756        6306 :         this->errorf(this->pc_, "type error in merge[%u] (expected %s, got %s)",
    2757        1450 :                      i, ValueTypes::TypeName(old.type),
    2758             :                      ValueTypes::TypeName(val.type));
    2759        3406 :         return false;
    2760             :       }
    2761       23244 :       val.type = old.type;
    2762             :     }
    2763             : 
    2764             :     return true;
    2765             :   }
    2766             : 
    2767     1623808 :   bool TypeCheckFallThru(Control* c) {
    2768             :     DCHECK_EQ(c, &control_.back());
    2769             :     if (!validate) return true;
    2770     1623808 :     uint32_t expected = c->end_merge.arity;
    2771             :     DCHECK_GE(stack_.size(), c->stack_depth);
    2772     1623808 :     uint32_t actual = static_cast<uint32_t>(stack_.size()) - c->stack_depth;
    2773             :     // Fallthrus must match the arity of the control exactly.
    2774     1623808 :     if (!InsertUnreachablesIfNecessary(expected, actual) || actual > expected) {
    2775        8732 :       this->errorf(
    2776             :           this->pc_,
    2777             :           "expected %u elements on the stack for fallthru to @%d, found %u",
    2778             :           expected, startrel(c->pc), actual);
    2779        4364 :       return false;
    2780             :     }
    2781     1619747 :     if (expected == 0) return true;  // Fast path.
    2782             : 
    2783      938805 :     return TypeCheckMergeValues(c, &c->end_merge);
    2784             :   }
    2785             : 
    2786      336668 :   bool TypeCheckBranch(Control* c) {
    2787             :     // Branches must have at least the number of values expected; can have more.
    2788      336668 :     uint32_t expected = c->br_merge()->arity;
    2789      336668 :     if (expected == 0) return true;  // Fast path.
    2790             :     DCHECK_GE(stack_.size(), control_.back().stack_depth);
    2791             :     uint32_t actual =
    2792       17292 :         static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth;
    2793       11878 :     if (!InsertUnreachablesIfNecessary(expected, actual)) {
    2794        3690 :       this->errorf(this->pc_,
    2795             :                    "expected %u elements on the stack for br to @%d, found %u",
    2796             :                    expected, startrel(c->pc), actual);
    2797        1844 :       return false;
    2798             :     }
    2799       10030 :     return TypeCheckMergeValues(c, c->br_merge());
    2800             :   }
    2801             : 
    2802      342689 :   bool TypeCheckReturn() {
    2803             :     // Returns must have at least the number of values expected; can have more.
    2804      342689 :     uint32_t num_returns = static_cast<uint32_t>(this->sig_->return_count());
    2805             :     DCHECK_GE(stack_.size(), control_.back().stack_depth);
    2806             :     uint32_t actual =
    2807      451279 :         static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth;
    2808      342689 :     if (!InsertUnreachablesIfNecessary(num_returns, actual)) {
    2809         688 :       this->errorf(this->pc_,
    2810             :                    "expected %u elements on the stack for return, found %u",
    2811             :                    num_returns, actual);
    2812         688 :       return false;
    2813             :     }
    2814             : 
    2815             :     // Typecheck the topmost {num_returns} values on the stack.
    2816      342040 :     if (num_returns == 0) return true;
    2817             :     // This line requires num_returns > 0.
    2818             :     Value* stack_values = &*(stack_.end() - num_returns);
    2819      213732 :     for (uint32_t i = 0; i < num_returns; ++i) {
    2820       71342 :       auto& val = stack_values[i];
    2821       71342 :       ValueType expected_type = this->sig_->GetReturn(i);
    2822       71342 :       if (ValueTypes::IsSubType(expected_type, val.type)) continue;
    2823             :       // If {val.type} is polymorphic, which results from unreachable,
    2824             :       // make it more specific by using the return's expected type.
    2825             :       // If it is not polymorphic, this is a type error.
    2826         220 :       if (!VALIDATE(val.type == kWasmVar)) {
    2827         144 :         this->errorf(this->pc_,
    2828             :                      "type error in return[%u] (expected %s, got %s)", i,
    2829             :                      ValueTypes::TypeName(expected_type),
    2830             :                      ValueTypes::TypeName(val.type));
    2831         144 :         return false;
    2832             :       }
    2833          76 :       val.type = expected_type;
    2834             :     }
    2835             :     return true;
    2836             :   }
    2837             : 
    2838     1978402 :   inline bool InsertUnreachablesIfNecessary(uint32_t expected,
    2839             :                                             uint32_t actual) {
    2840     1978402 :     if (V8_LIKELY(actual >= expected)) {
    2841             :       return true;  // enough actual values are there.
    2842             :     }
    2843       27146 :     if (!VALIDATE(control_.back().unreachable())) {
    2844             :       // There aren't enough values on the stack.
    2845             :       return false;
    2846             :     }
    2847             :     // A slow path. When the actual number of values on the stack is less
    2848             :     // than the expected number of values and the current control is
    2849             :     // unreachable, insert unreachable values below the actual values.
    2850             :     // This simplifies {TypeCheckMergeValues}.
    2851       22641 :     auto pos = stack_.begin() + (stack_.size() - actual);
    2852       64703 :     stack_.insert(pos, expected - actual, UnreachableValue(this->pc_));
    2853       22639 :     return true;
    2854             :   }
    2855             : 
    2856       62066 :   void onFirstError() override {
    2857       62066 :     this->end_ = this->pc_;  // Terminate decoding loop.
    2858             :     TRACE(" !%s\n", this->error_.message().c_str());
    2859             :     CALL_INTERFACE(OnFirstError);
    2860       62066 :   }
    2861             : 
    2862         130 :   void BuildSimplePrototypeOperator(WasmOpcode opcode) {
    2863         130 :     if (WasmOpcodes::IsSignExtensionOpcode(opcode)) {
    2864          62 :       RET_ON_PROTOTYPE_OPCODE(se);
    2865             :     }
    2866         130 :     if (WasmOpcodes::IsAnyRefOpcode(opcode)) {
    2867          68 :       RET_ON_PROTOTYPE_OPCODE(anyref);
    2868             :     }
    2869         130 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2870         129 :     BuildSimpleOperator(opcode, sig);
    2871         130 :   }
    2872             : 
    2873      100395 :   void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
    2874      100395 :     switch (sig->parameter_count()) {
    2875             :       case 1: {
    2876             :         auto val = Pop(0, sig->GetParam(0));
    2877             :         auto* ret =
    2878       57610 :             sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
    2879       57112 :         CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, val, ret);
    2880             :         break;
    2881             :       }
    2882             :       case 2: {
    2883             :         auto rval = Pop(1, sig->GetParam(1));
    2884             :         auto lval = Pop(0, sig->GetParam(0));
    2885             :         auto* ret =
    2886       42785 :             sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
    2887       41285 :         CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, lval, rval, ret);
    2888             :         break;
    2889             :       }
    2890             :       default:
    2891           0 :         UNREACHABLE();
    2892             :     }
    2893      100396 :   }
    2894             : 
    2895      567390 :   void BuildSimpleOperator(WasmOpcode opcode, ValueType return_type,
    2896             :                            ValueType arg_type) {
    2897             :     auto val = Pop(0, arg_type);
    2898      567431 :     auto* ret = return_type == kWasmStmt ? nullptr : Push(return_type);
    2899      354925 :     CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, val, ret);
    2900      567484 :   }
    2901             : 
    2902     1735852 :   void BuildSimpleOperator(WasmOpcode opcode, ValueType return_type,
    2903             :                            ValueType lhs_type, ValueType rhs_type) {
    2904             :     auto rval = Pop(1, rhs_type);
    2905             :     auto lval = Pop(0, lhs_type);
    2906     1736012 :     auto* ret = return_type == kWasmStmt ? nullptr : Push(return_type);
    2907     1591334 :     CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, lval, rval, ret);
    2908     1735852 :   }
    2909             : 
    2910             : #define DEFINE_SIMPLE_SIG_OPERATOR(sig, ...)          \
    2911             :   void BuildSimpleOperator_##sig(WasmOpcode opcode) { \
    2912             :     BuildSimpleOperator(opcode, __VA_ARGS__);         \
    2913             :   }
    2914      260395 :   FOREACH_SIGNATURE(DEFINE_SIMPLE_SIG_OPERATOR)
    2915             : #undef DEFINE_SIMPLE_SIG_OPERATOR
    2916             : };
    2917             : 
    2918             : #undef CALL_INTERFACE
    2919             : #undef CALL_INTERFACE_IF_REACHABLE
    2920             : #undef CALL_INTERFACE_IF_PARENT_REACHABLE
    2921             : 
    2922             : class EmptyInterface {
    2923             :  public:
    2924             :   static constexpr Decoder::ValidateFlag validate = Decoder::kValidate;
    2925             :   using Value = ValueBase;
    2926             :   using Control = ControlBase<Value>;
    2927             :   using FullDecoder = WasmFullDecoder<validate, EmptyInterface>;
    2928             : 
    2929             : #define DEFINE_EMPTY_CALLBACK(name, ...) \
    2930             :   void name(FullDecoder* decoder, ##__VA_ARGS__) {}
    2931             :   INTERFACE_FUNCTIONS(DEFINE_EMPTY_CALLBACK)
    2932             : #undef DEFINE_EMPTY_CALLBACK
    2933             : };
    2934             : 
    2935             : #undef TRACE
    2936             : #undef TRACE_INST_FORMAT
    2937             : #undef VALIDATE
    2938             : #undef CHECK_PROTOTYPE_OPCODE
    2939             : #undef OPCODE_ERROR
    2940             : 
    2941             : }  // namespace wasm
    2942             : }  // namespace internal
    2943             : }  // namespace v8
    2944             : 
    2945             : #endif  // V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_

Generated by: LCOV version 1.10