LCOV - code coverage report
Current view: top level - src/wasm - function-body-decoder-impl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 985 1043 94.4 %
Date: 2019-03-21 Functions: 142 178 79.8 %

          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    18151840 :   inline LocalIndexImmediate(Decoder* decoder, const byte* pc) {
     141    19987104 :     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        1126 :   inline ExceptionIndexImmediate(Decoder* decoder, const byte* pc) {
     152        2217 :     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    23982835 :     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      215821 :     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      676398 :   inline ImmF32Immediate(Decoder* decoder, const byte* pc) {
     179             :     // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
     180     1352796 :     uint32_t tmp = decoder->read_u32<validate>(pc + 1, "immf32");
     181      676398 :     memcpy(&value, &tmp, sizeof(value));
     182      676398 :   }
     183             : };
     184             : 
     185             : template <Decoder::ValidateFlag validate>
     186             : struct ImmF64Immediate {
     187             :   double value;
     188             :   uint32_t length = 8;
     189      246594 :   inline ImmF64Immediate(Decoder* decoder, const byte* pc) {
     190             :     // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
     191      493190 :     uint64_t tmp = decoder->read_u64<validate>(pc + 1, "immf64");
     192      246596 :     memcpy(&value, &tmp, sizeof(value));
     193      246596 :   }
     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      888543 :   inline GlobalIndexImmediate(Decoder* decoder, const byte* pc) {
     204      949377 :     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     1844840 :   inline BlockTypeImmediate(const WasmFeatures& enabled, Decoder* decoder,
     216     1844840 :                             const byte* pc) {
     217      465591 :     uint8_t val = decoder->read_u8<validate>(pc + 1, "block type");
     218     1844844 :     if (!decode_local_type(val, &type)) {
     219             :       // Handle multi-value blocks.
     220         300 :       if (!VALIDATE(enabled.mv)) {
     221          65 :         decoder->error(pc + 1, "invalid block type");
     222          65 :         return;
     223             :       }
     224         235 :       if (!VALIDATE(decoder->ok())) return;
     225             :       int32_t index =
     226       40603 :           decoder->read_i32v<validate>(pc + 1, &length, "block arity");
     227         211 :       if (!VALIDATE(length > 0 && index >= 0)) {
     228           0 :         decoder->error(pc + 1, "invalid block type index");
     229           0 :         return;
     230             :       }
     231       40603 :       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     1844887 :   inline bool decode_local_type(uint8_t val, ValueType* result) {
     238     1844887 :     switch (static_cast<ValueTypeCode>(val)) {
     239             :       case kLocalVoid:
     240     1613365 :         *result = kWasmStmt;
     241     1613365 :         return true;
     242             :       case kLocalI32:
     243      183112 :         *result = kWasmI32;
     244      183112 :         return true;
     245             :       case kLocalI64:
     246        1980 :         *result = kWasmI64;
     247        1980 :         return true;
     248             :       case kLocalF32:
     249        2821 :         *result = kWasmF32;
     250        2821 :         return true;
     251             :       case kLocalF64:
     252        2850 :         *result = kWasmF64;
     253        2850 :         return true;
     254             :       case kLocalS128:
     255           8 :         *result = kWasmS128;
     256           8 :         return true;
     257             :       case kLocalAnyFunc:
     258           0 :         *result = kWasmAnyFunc;
     259           0 :         return true;
     260             :       case kLocalAnyRef:
     261          59 :         *result = kWasmAnyRef;
     262          59 :         return true;
     263             :       default:
     264       40692 :         *result = kWasmVar;
     265       40692 :         return false;
     266             :     }
     267             :   }
     268             : 
     269             :   uint32_t in_arity() const {
     270      381083 :     if (type != kWasmVar) return 0;
     271         267 :     return static_cast<uint32_t>(sig->parameter_count());
     272             :   }
     273             :   uint32_t out_arity() const {
     274      424880 :     if (type == kWasmStmt) return 0;
     275       32467 :     if (type != kWasmVar) return 1;
     276         291 :     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       31489 :     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      703518 :     depth = decoder->read_u32v<validate>(pc + 1, &length, "branch depth");
     296             :   }
     297             : };
     298             : 
     299             : template <Decoder::ValidateFlag validate>
     300             : struct CallIndirectImmediate {
     301             :   uint32_t table_index;
     302             :   uint32_t sig_index;
     303             :   FunctionSig* sig = nullptr;
     304             :   uint32_t length = 0;
     305       51091 :   inline CallIndirectImmediate(const WasmFeatures enabled, Decoder* decoder,
     306       51091 :                                const byte* pc) {
     307       51091 :     uint32_t len = 0;
     308       61009 :     sig_index = decoder->read_u32v<validate>(pc + 1, &len, "signature index");
     309       61015 :     table_index = decoder->read_u8<validate>(pc + 1 + len, "table index");
     310        9920 :     if (!VALIDATE(table_index == 0 || enabled.anyref)) {
     311          64 :       decoder->errorf(pc + 1 + len, "expected table index 0, found %u",
     312             :                       table_index);
     313             :     }
     314       51097 :     length = 1 + len;
     315       51097 :   }
     316             : };
     317             : 
     318             : template <Decoder::ValidateFlag validate>
     319             : struct CallFunctionImmediate {
     320             :   uint32_t index;
     321             :   FunctionSig* sig = nullptr;
     322             :   uint32_t length;
     323      956601 :   inline CallFunctionImmediate(Decoder* decoder, const byte* pc) {
     324     1239957 :     index = decoder->read_u32v<validate>(pc + 1, &length, "function index");
     325             :   }
     326             : };
     327             : 
     328             : template <Decoder::ValidateFlag validate>
     329             : struct MemoryIndexImmediate {
     330             :   uint32_t index = 0;
     331             :   uint32_t length = 1;
     332         236 :   inline MemoryIndexImmediate() = default;
     333        4841 :   inline MemoryIndexImmediate(Decoder* decoder, const byte* pc) {
     334        9722 :     index = decoder->read_u8<validate>(pc + 1, "memory index");
     335        4793 :     if (!VALIDATE(index == 0)) {
     336         344 :       decoder->errorf(pc + 1, "expected memory index 0, found %u", index);
     337             :     }
     338        4793 :   }
     339             : };
     340             : 
     341             : template <Decoder::ValidateFlag validate>
     342             : struct TableIndexImmediate {
     343             :   uint32_t index = 0;
     344             :   unsigned length = 1;
     345         142 :   inline TableIndexImmediate() = default;
     346         459 :   inline TableIndexImmediate(Decoder* decoder, const byte* pc) {
     347        1686 :     index = decoder->read_u8<validate>(pc + 1, "table index");
     348         459 :   }
     349             : };
     350             : 
     351             : template <Decoder::ValidateFlag validate>
     352             : struct BranchTableImmediate {
     353             :   uint32_t table_count;
     354             :   const byte* start;
     355             :   const byte* table;
     356      243657 :   inline BranchTableImmediate(Decoder* decoder, const byte* pc) {
     357             :     DCHECK_EQ(kExprBrTable, decoder->read_u8<validate>(pc, "opcode"));
     358      243657 :     start = pc + 1;
     359      243657 :     uint32_t len = 0;
     360      243654 :     table_count = decoder->read_u32v<validate>(pc + 1, &len, "table count");
     361      243654 :     table = pc + 1 + len;
     362      243654 :   }
     363             : };
     364             : 
     365             : // A helper to iterate over a branch table.
     366             : template <Decoder::ValidateFlag validate>
     367             : class BranchTableIterator {
     368             :  public:
     369             :   uint32_t cur_index() { return index_; }
     370      920462 :   bool has_next() { return VALIDATE(decoder_->ok()) && index_ <= table_count_; }
     371     1947531 :   uint32_t next() {
     372             :     DCHECK(has_next());
     373     1947531 :     index_++;
     374             :     uint32_t length;
     375             :     uint32_t result =
     376     1947531 :         decoder_->read_u32v<validate>(pc_, &length, "branch table entry");
     377     1947360 :     pc_ += length;
     378     1947360 :     return result;
     379             :   }
     380             :   // length, including the length of the {BranchTableImmediate}, but not the
     381             :   // opcode.
     382       12428 :   uint32_t length() {
     383       33633 :     while (has_next()) next();
     384       16636 :     return static_cast<uint32_t>(pc_ - start_);
     385             :   }
     386             :   const byte* pc() { return pc_; }
     387             : 
     388             :   BranchTableIterator(Decoder* decoder,
     389             :                       const BranchTableImmediate<validate>& imm)
     390             :       : decoder_(decoder),
     391             :         start_(imm.start),
     392             :         pc_(imm.table),
     393      254266 :         table_count_(imm.table_count) {}
     394             : 
     395             :  private:
     396             :   Decoder* decoder_;
     397             :   const byte* start_;
     398             :   const byte* pc_;
     399             :   uint32_t index_ = 0;    // the current index.
     400             :   uint32_t table_count_;  // the count of entries, not including default.
     401             : };
     402             : 
     403             : template <Decoder::ValidateFlag validate>
     404             : struct MemoryAccessImmediate {
     405             :   uint32_t alignment;
     406             :   uint32_t offset;
     407             :   uint32_t length = 0;
     408     6784201 :   inline MemoryAccessImmediate(Decoder* decoder, const byte* pc,
     409     6784201 :                                uint32_t max_alignment) {
     410             :     uint32_t alignment_length;
     411     7294062 :     alignment =
     412             :         decoder->read_u32v<validate>(pc + 1, &alignment_length, "alignment");
     413      509861 :     if (!VALIDATE(alignment <= max_alignment)) {
     414        1246 :       decoder->errorf(pc + 1,
     415             :                       "invalid alignment; expected maximum alignment is %u, "
     416             :                       "actual alignment is %u",
     417             :                       max_alignment, alignment);
     418             :     }
     419             :     uint32_t offset_length;
     420    13568541 :     offset = decoder->read_u32v<validate>(pc + 1 + alignment_length,
     421             :                                           &offset_length, "offset");
     422     6784278 :     length = alignment_length + offset_length;
     423     6784278 :   }
     424             : };
     425             : 
     426             : // Immediate for SIMD lane operations.
     427             : template <Decoder::ValidateFlag validate>
     428             : struct SimdLaneImmediate {
     429             :   uint8_t lane;
     430             :   uint32_t length = 1;
     431             : 
     432         676 :   inline SimdLaneImmediate(Decoder* decoder, const byte* pc) {
     433        1352 :     lane = decoder->read_u8<validate>(pc + 2, "lane");
     434         676 :   }
     435             : };
     436             : 
     437             : // Immediate for SIMD shift operations.
     438             : template <Decoder::ValidateFlag validate>
     439             : struct SimdShiftImmediate {
     440             :   uint8_t shift;
     441             :   uint32_t length = 1;
     442             : 
     443        1272 :   inline SimdShiftImmediate(Decoder* decoder, const byte* pc) {
     444        2544 :     shift = decoder->read_u8<validate>(pc + 2, "shift");
     445        1272 :   }
     446             : };
     447             : 
     448             : // Immediate for SIMD S8x16 shuffle operations.
     449             : template <Decoder::ValidateFlag validate>
     450             : struct Simd8x16ShuffleImmediate {
     451             :   uint8_t shuffle[kSimd128Size] = {0};
     452             : 
     453       27025 :   inline Simd8x16ShuffleImmediate(Decoder* decoder, const byte* pc) {
     454      891825 :     for (uint32_t i = 0; i < kSimd128Size; ++i) {
     455      669216 :       shuffle[i] = decoder->read_u8<validate>(pc + 2 + i, "shuffle");
     456             :     }
     457       14801 :   }
     458             : };
     459             : 
     460             : template <Decoder::ValidateFlag validate>
     461             : struct MemoryInitImmediate {
     462             :   uint32_t data_segment_index = 0;
     463             :   MemoryIndexImmediate<validate> memory;
     464             :   unsigned length = 0;
     465             : 
     466         340 :   inline MemoryInitImmediate(Decoder* decoder, const byte* pc) {
     467         170 :     uint32_t len = 0;
     468         340 :     data_segment_index =
     469             :         decoder->read_i32v<validate>(pc + 2, &len, "data segment index");
     470         258 :     memory = MemoryIndexImmediate<validate>(decoder, pc + 1 + len);
     471         170 :     length = len + memory.length;
     472         170 :   }
     473             : };
     474             : 
     475             : template <Decoder::ValidateFlag validate>
     476             : struct DataDropImmediate {
     477             :   uint32_t index;
     478             :   unsigned length;
     479             : 
     480             :   inline DataDropImmediate(Decoder* decoder, const byte* pc) {
     481         124 :     index = decoder->read_i32v<validate>(pc + 2, &length, "data segment index");
     482             :   }
     483             : };
     484             : 
     485             : template <Decoder::ValidateFlag validate>
     486             : struct MemoryCopyImmediate {
     487             :   MemoryIndexImmediate<validate> memory_src;
     488             :   MemoryIndexImmediate<validate> memory_dst;
     489             :   unsigned length = 0;
     490             : 
     491         132 :   inline MemoryCopyImmediate(Decoder* decoder, const byte* pc) {
     492          66 :     memory_src = MemoryIndexImmediate<validate>(decoder, pc + 1);
     493          66 :     memory_dst =
     494          66 :         MemoryIndexImmediate<validate>(decoder, pc + 1 + memory_src.length);
     495          66 :     length = memory_src.length + memory_dst.length;
     496          66 :   }
     497             : };
     498             : 
     499             : template <Decoder::ValidateFlag validate>
     500             : struct TableInitImmediate {
     501             :   uint32_t elem_segment_index = 0;
     502             :   TableIndexImmediate<validate> table;
     503             :   unsigned length = 0;
     504             : 
     505         112 :   inline TableInitImmediate(Decoder* decoder, const byte* pc) {
     506          56 :     uint32_t len = 0;
     507         112 :     elem_segment_index =
     508             :         decoder->read_i32v<validate>(pc + 2, &len, "elem segment index");
     509          56 :     table = TableIndexImmediate<validate>(decoder, pc + 1 + len);
     510          56 :     length = len + table.length;
     511          56 :   }
     512             : };
     513             : 
     514             : template <Decoder::ValidateFlag validate>
     515             : struct ElemDropImmediate {
     516             :   uint32_t index;
     517             :   unsigned length;
     518             : 
     519             :   inline ElemDropImmediate(Decoder* decoder, const byte* pc) {
     520          70 :     index = decoder->read_i32v<validate>(pc + 2, &length, "elem segment index");
     521             :   }
     522             : };
     523             : 
     524             : template <Decoder::ValidateFlag validate>
     525             : struct TableCopyImmediate {
     526             :   TableIndexImmediate<validate> table_src;
     527             :   TableIndexImmediate<validate> table_dst;
     528             :   unsigned length = 0;
     529             : 
     530         172 :   inline TableCopyImmediate(Decoder* decoder, const byte* pc) {
     531          86 :     table_src = TableIndexImmediate<validate>(decoder, pc + 1);
     532          86 :     table_dst =
     533          86 :         TableIndexImmediate<validate>(decoder, pc + 1 + table_src.length);
     534          86 :     length = table_src.length + table_dst.length;
     535          86 :   }
     536             : };
     537             : 
     538             : // An entry on the value stack.
     539             : struct ValueBase {
     540             :   const byte* pc = nullptr;
     541             :   ValueType type = kWasmStmt;
     542             : 
     543     7583527 :   ValueBase(const byte* pc, ValueType type) : pc(pc), type(type) {}
     544             : };
     545             : 
     546             : template <typename Value>
     547             : struct Merge {
     548             :   uint32_t arity = 0;
     549             :   union {  // Either multiple values or a single value.
     550             :     Value* array;
     551             :     Value first;
     552             :   } vals = {nullptr};  // Initialize {array} with {nullptr}.
     553             : 
     554             :   // Tracks whether this merge was ever reached. Uses precise reachability, like
     555             :   // Reachability::kReachable.
     556             :   bool reached;
     557             : 
     558     1647087 :   Merge(bool reached = false) : reached(reached) {}
     559             : 
     560             :   Value& operator[](uint32_t i) {
     561             :     DCHECK_GT(arity, i);
     562     1015047 :     return arity == 1 ? vals.first : vals.array[i];
     563             :   }
     564             : };
     565             : 
     566             : enum ControlKind : uint8_t {
     567             :   kControlIf,
     568             :   kControlIfElse,
     569             :   kControlBlock,
     570             :   kControlLoop,
     571             :   kControlTry,
     572             :   kControlTryCatch
     573             : };
     574             : 
     575             : enum Reachability : uint8_t {
     576             :   // reachable code.
     577             :   kReachable,
     578             :   // reachable code in unreachable block (implies normal validation).
     579             :   kSpecOnlyReachable,
     580             :   // code unreachable in its own block (implies polymorphic validation).
     581             :   kUnreachable
     582             : };
     583             : 
     584             : // An entry on the control stack (i.e. if, block, loop, or try).
     585             : template <typename Value>
     586             : struct ControlBase {
     587             :   ControlKind kind = kControlBlock;
     588             :   uint32_t stack_depth = 0;  // stack height at the beginning of the construct.
     589             :   const uint8_t* pc = nullptr;
     590             :   Reachability reachability = kReachable;
     591             : 
     592             :   // Values merged into the start or end of this control construct.
     593             :   Merge<Value> start_merge;
     594             :   Merge<Value> end_merge;
     595             : 
     596             :   MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ControlBase);
     597             : 
     598             :   ControlBase(ControlKind kind, uint32_t stack_depth, const uint8_t* pc,
     599             :               Reachability reachability)
     600             :       : kind(kind),
     601             :         stack_depth(stack_depth),
     602             :         pc(pc),
     603             :         reachability(reachability),
     604     1647087 :         start_merge(reachability == kReachable) {}
     605             : 
     606             :   // Check whether the current block is reachable.
     607             :   bool reachable() const { return reachability == kReachable; }
     608             : 
     609             :   // Check whether the rest of the block is unreachable.
     610             :   // Note that this is different from {!reachable()}, as there is also the
     611             :   // "indirect unreachable state", for which both {reachable()} and
     612             :   // {unreachable()} return false.
     613             :   bool unreachable() const { return reachability == kUnreachable; }
     614             : 
     615             :   // Return the reachability of new control structs started in this block.
     616             :   Reachability innerReachability() const {
     617      402835 :     return reachability == kReachable ? kReachable : kSpecOnlyReachable;
     618             :   }
     619             : 
     620       21660 :   bool is_if() const { return is_onearmed_if() || is_if_else(); }
     621             :   bool is_onearmed_if() const { return kind == kControlIf; }
     622             :   bool is_if_else() const { return kind == kControlIfElse; }
     623             :   bool is_block() const { return kind == kControlBlock; }
     624             :   bool is_loop() const { return kind == kControlLoop; }
     625             :   bool is_incomplete_try() const { return kind == kControlTry; }
     626             :   bool is_try_catch() const { return kind == kControlTryCatch; }
     627         549 :   bool is_try() const { return is_incomplete_try() || is_try_catch(); }
     628             : 
     629             :   inline Merge<Value>* br_merge() {
     630     1265406 :     return is_loop() ? &this->start_merge : &this->end_merge;
     631             :   }
     632             : };
     633             : 
     634             : // This is the list of callback functions that an interface for the
     635             : // WasmFullDecoder should implement.
     636             : // F(Name, args...)
     637             : #define INTERFACE_FUNCTIONS(F)                                                \
     638             :   /* General: */                                                              \
     639             :   F(StartFunction)                                                            \
     640             :   F(StartFunctionBody, Control* block)                                        \
     641             :   F(FinishFunction)                                                           \
     642             :   F(OnFirstError)                                                             \
     643             :   F(NextInstruction, WasmOpcode)                                              \
     644             :   /* Control: */                                                              \
     645             :   F(Block, Control* block)                                                    \
     646             :   F(Loop, Control* block)                                                     \
     647             :   F(Try, Control* block)                                                      \
     648             :   F(Catch, Control* block, Value* exception)                                  \
     649             :   F(If, const Value& cond, Control* if_block)                                 \
     650             :   F(FallThruTo, Control* c)                                                   \
     651             :   F(PopControl, Control* block)                                               \
     652             :   F(EndControl, Control* block)                                               \
     653             :   /* Instructions: */                                                         \
     654             :   F(UnOp, WasmOpcode opcode, const Value& value, Value* result)               \
     655             :   F(BinOp, WasmOpcode opcode, const Value& lhs, const Value& rhs,             \
     656             :     Value* result)                                                            \
     657             :   F(I32Const, Value* result, int32_t value)                                   \
     658             :   F(I64Const, Value* result, int64_t value)                                   \
     659             :   F(F32Const, Value* result, float value)                                     \
     660             :   F(F64Const, Value* result, double value)                                    \
     661             :   F(RefNull, Value* result)                                                   \
     662             :   F(Drop, const Value& value)                                                 \
     663             :   F(DoReturn, Vector<Value> values)                                           \
     664             :   F(GetLocal, Value* result, const LocalIndexImmediate<validate>& imm)        \
     665             :   F(SetLocal, const Value& value, const LocalIndexImmediate<validate>& imm)   \
     666             :   F(TeeLocal, const Value& value, Value* result,                              \
     667             :     const LocalIndexImmediate<validate>& imm)                                 \
     668             :   F(GetGlobal, Value* result, const GlobalIndexImmediate<validate>& imm)      \
     669             :   F(SetGlobal, const Value& value, const GlobalIndexImmediate<validate>& imm) \
     670             :   F(GetTable, const Value& index, Value* result,                              \
     671             :     const TableIndexImmediate<validate>& imm)                                 \
     672             :   F(SetTable, const Value& index, const Value& value,                         \
     673             :     const TableIndexImmediate<validate>& imm)                                 \
     674             :   F(Unreachable)                                                              \
     675             :   F(Select, const Value& cond, const Value& fval, const Value& tval,          \
     676             :     Value* result)                                                            \
     677             :   F(Br, Control* target)                                                      \
     678             :   F(BrIf, const Value& cond, uint32_t depth)                                  \
     679             :   F(BrTable, const BranchTableImmediate<validate>& imm, const Value& key)     \
     680             :   F(Else, Control* if_block)                                                  \
     681             :   F(LoadMem, LoadType type, const MemoryAccessImmediate<validate>& imm,       \
     682             :     const Value& index, Value* result)                                        \
     683             :   F(StoreMem, StoreType type, const MemoryAccessImmediate<validate>& imm,     \
     684             :     const Value& index, const Value& value)                                   \
     685             :   F(CurrentMemoryPages, Value* result)                                        \
     686             :   F(MemoryGrow, const Value& value, Value* result)                            \
     687             :   F(CallDirect, const CallFunctionImmediate<validate>& imm,                   \
     688             :     const Value args[], Value returns[])                                      \
     689             :   F(CallIndirect, const Value& index,                                         \
     690             :     const CallIndirectImmediate<validate>& imm, const Value args[],           \
     691             :     Value returns[])                                                          \
     692             :   F(ReturnCall, const CallFunctionImmediate<validate>& imm,                   \
     693             :     const Value args[])                                                       \
     694             :   F(ReturnCallIndirect, const Value& index,                                   \
     695             :     const CallIndirectImmediate<validate>& imm, const Value args[])           \
     696             :   F(SimdOp, WasmOpcode opcode, Vector<Value> args, Value* result)             \
     697             :   F(SimdLaneOp, WasmOpcode opcode, const SimdLaneImmediate<validate>& imm,    \
     698             :     const Vector<Value> inputs, Value* result)                                \
     699             :   F(SimdShiftOp, WasmOpcode opcode, const SimdShiftImmediate<validate>& imm,  \
     700             :     const Value& input, Value* result)                                        \
     701             :   F(Simd8x16ShuffleOp, const Simd8x16ShuffleImmediate<validate>& imm,         \
     702             :     const Value& input0, const Value& input1, Value* result)                  \
     703             :   F(Throw, const ExceptionIndexImmediate<validate>& imm,                      \
     704             :     const Vector<Value>& args)                                                \
     705             :   F(Rethrow, const Value& exception)                                          \
     706             :   F(BrOnException, const Value& exception,                                    \
     707             :     const ExceptionIndexImmediate<validate>& imm, uint32_t depth,             \
     708             :     Vector<Value> values)                                                     \
     709             :   F(AtomicOp, WasmOpcode opcode, Vector<Value> args,                          \
     710             :     const MemoryAccessImmediate<validate>& imm, Value* result)                \
     711             :   F(MemoryInit, const MemoryInitImmediate<validate>& imm, const Value& dst,   \
     712             :     const Value& src, const Value& size)                                      \
     713             :   F(DataDrop, const DataDropImmediate<validate>& imm)                         \
     714             :   F(MemoryCopy, const MemoryCopyImmediate<validate>& imm, const Value& dst,   \
     715             :     const Value& src, const Value& size)                                      \
     716             :   F(MemoryFill, const MemoryIndexImmediate<validate>& imm, const Value& dst,  \
     717             :     const Value& value, const Value& size)                                    \
     718             :   F(TableInit, const TableInitImmediate<validate>& imm, Vector<Value> args)   \
     719             :   F(ElemDrop, const ElemDropImmediate<validate>& imm)                         \
     720             :   F(TableCopy, const TableCopyImmediate<validate>& imm, Vector<Value> args)
     721             : 
     722             : // Generic Wasm bytecode decoder with utilities for decoding immediates,
     723             : // lengths, etc.
     724             : template <Decoder::ValidateFlag validate>
     725     6493894 : class WasmDecoder : public Decoder {
     726             :  public:
     727             :   WasmDecoder(const WasmModule* module, const WasmFeatures& enabled,
     728             :               WasmFeatures* detected, FunctionSig* sig, const byte* start,
     729             :               const byte* end, uint32_t buffer_offset = 0)
     730             :       : Decoder(start, end, buffer_offset),
     731             :         module_(module),
     732             :         enabled_(enabled),
     733             :         detected_(detected),
     734             :         sig_(sig),
     735     3247277 :         local_types_(nullptr) {}
     736             :   const WasmModule* module_;
     737             :   const WasmFeatures enabled_;
     738             :   WasmFeatures* detected_;
     739             :   FunctionSig* sig_;
     740             : 
     741             :   ZoneVector<ValueType>* local_types_;
     742             : 
     743             :   uint32_t total_locals() const {
     744             :     return local_types_ == nullptr
     745             :                ? 0
     746     2878211 :                : static_cast<uint32_t>(local_types_->size());
     747             :   }
     748             : 
     749     1633731 :   static bool DecodeLocals(const WasmFeatures& enabled, Decoder* decoder,
     750             :                            const FunctionSig* sig,
     751             :                            ZoneVector<ValueType>* type_list) {
     752             :     DCHECK_NOT_NULL(type_list);
     753             :     DCHECK_EQ(0, type_list->size());
     754             :     // Initialize from signature.
     755     1633731 :     if (sig != nullptr) {
     756     1266897 :       type_list->assign(sig->parameters().begin(), sig->parameters().end());
     757             :     }
     758             :     // Decode local declarations, if any.
     759             :     uint32_t entries = decoder->consume_u32v("local decls count");
     760     1634502 :     if (decoder->failed()) return false;
     761             : 
     762             :     TRACE("local decls count: %u\n", entries);
     763     1735324 :     while (entries-- > 0 && decoder->more()) {
     764             :       uint32_t count = decoder->consume_u32v("local count");
     765       50634 :       if (decoder->failed()) return false;
     766             : 
     767             :       DCHECK_LE(type_list->size(), kV8MaxWasmFunctionLocals);
     768      101074 :       if (count > kV8MaxWasmFunctionLocals - type_list->size()) {
     769          59 :         decoder->error(decoder->pc() - 1, "local count too large");
     770          59 :         return false;
     771             :       }
     772             :       byte code = decoder->consume_u8("local type");
     773       50479 :       if (decoder->failed()) return false;
     774             : 
     775             :       ValueType type;
     776       50479 :       switch (code) {
     777             :         case kLocalI32:
     778       24048 :           type = kWasmI32;
     779       24048 :           break;
     780             :         case kLocalI64:
     781       19358 :           type = kWasmI64;
     782       19358 :           break;
     783             :         case kLocalF32:
     784        1400 :           type = kWasmF32;
     785        1400 :           break;
     786             :         case kLocalF64:
     787        2237 :           type = kWasmF64;
     788        2237 :           break;
     789             :         case kLocalAnyRef:
     790          34 :           if (enabled.anyref) {
     791          34 :             type = kWasmAnyRef;
     792          34 :             break;
     793             :           }
     794           0 :           decoder->error(decoder->pc() - 1, "invalid local type");
     795           0 :           return false;
     796             :         case kLocalAnyFunc:
     797          64 :           if (enabled.anyref) {
     798          64 :             type = kWasmAnyFunc;
     799          64 :             break;
     800             :           }
     801           0 :           decoder->error(decoder->pc() - 1,
     802             :                          "local type 'anyfunc' is not enabled with "
     803             :                          "--experimental-wasm-anyref");
     804           0 :           return false;
     805             :         case kLocalExceptRef:
     806         137 :           if (enabled.eh) {
     807         137 :             type = kWasmExceptRef;
     808         137 :             break;
     809             :           }
     810           0 :           decoder->error(decoder->pc() - 1, "invalid local type");
     811           0 :           return false;
     812             :         case kLocalS128:
     813        3164 :           if (enabled.simd) {
     814        3156 :             type = kWasmS128;
     815        3156 :             break;
     816             :           }
     817             :           V8_FALLTHROUGH;
     818             :         default:
     819          45 :           decoder->error(decoder->pc() - 1, "invalid local type");
     820          38 :           return false;
     821             :       }
     822       50434 :       type_list->insert(type_list->end(), count, type);
     823             :     }
     824             :     DCHECK(decoder->ok());
     825             :     return true;
     826             :   }
     827             : 
     828        9267 :   static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc,
     829             :                                           uint32_t locals_count, Zone* zone) {
     830        9267 :     if (pc >= decoder->end()) return nullptr;
     831        9267 :     if (*pc != kExprLoop) return nullptr;
     832             : 
     833             :     // The number of locals_count is augmented by 2 so that 'locals_count - 2'
     834             :     // can be used to track mem_size, and 'locals_count - 1' to track mem_start.
     835        9269 :     BitVector* assigned = new (zone) BitVector(locals_count, zone);
     836             :     int depth = 0;
     837             :     // Iteratively process all AST nodes nested inside the loop.
     838     3177944 :     while (pc < decoder->end() && VALIDATE(decoder->ok())) {
     839     1593617 :       WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
     840             :       uint32_t length = 1;
     841     1593617 :       switch (opcode) {
     842             :         case kExprLoop:
     843             :         case kExprIf:
     844             :         case kExprBlock:
     845             :         case kExprTry:
     846       84081 :           length = OpcodeLength(decoder, pc);
     847       84079 :           depth++;
     848       84079 :           break;
     849             :         case kExprSetLocal:  // fallthru
     850             :         case kExprTeeLocal: {
     851             :           LocalIndexImmediate<validate> imm(decoder, pc);
     852      112693 :           if (assigned->length() > 0 &&
     853             :               imm.index < static_cast<uint32_t>(assigned->length())) {
     854             :             // Unverified code might have an out-of-bounds index.
     855      112692 :             assigned->Add(imm.index);
     856             :           }
     857      112693 :           length = 1 + imm.length;
     858             :           break;
     859             :         }
     860             :         case kExprMemoryGrow:
     861             :         case kExprCallFunction:
     862             :         case kExprCallIndirect:
     863             :         case kExprReturnCall:
     864             :         case kExprReturnCallIndirect:
     865             :           // Add instance cache nodes to the assigned set.
     866             :           // TODO(titzer): make this more clear.
     867       18251 :           assigned->Add(locals_count - 1);
     868       18251 :           length = OpcodeLength(decoder, pc);
     869       18252 :           break;
     870             :         case kExprEnd:
     871       84068 :           depth--;
     872       84068 :           break;
     873             :         default:
     874     1294523 :           length = OpcodeLength(decoder, pc);
     875     1294521 :           break;
     876             :       }
     877     1593613 :       if (depth <= 0) break;
     878     1584336 :       pc += length;
     879             :     }
     880        9268 :     return VALIDATE(decoder->ok()) ? assigned : nullptr;
     881             :   }
     882             : 
     883     1420867 :   inline bool Validate(const byte* pc, LocalIndexImmediate<validate>& imm) {
     884     2841734 :     if (!VALIDATE(imm.index < total_locals())) {
     885         697 :       errorf(pc + 1, "invalid local index: %u", imm.index);
     886         697 :       return false;
     887             :     }
     888     2840252 :     imm.type = local_types_ ? local_types_->at(imm.index) : kWasmStmt;
     889     1420170 :     return true;
     890             :   }
     891             : 
     892             :   inline bool Complete(const byte* pc, ExceptionIndexImmediate<validate>& imm) {
     893        2166 :     if (!VALIDATE(module_ != nullptr &&
     894             :                   imm.index < module_->exceptions.size())) {
     895             :       return false;
     896             :     }
     897        2172 :     imm.exception = &module_->exceptions[imm.index];
     898             :     return true;
     899             :   }
     900             : 
     901        1083 :   inline bool Validate(const byte* pc, ExceptionIndexImmediate<validate>& imm) {
     902        1083 :     if (!Complete(pc, imm)) {
     903           9 :       errorf(pc + 1, "Invalid exception index: %u", imm.index);
     904           9 :       return false;
     905             :     }
     906             :     return true;
     907             :   }
     908             : 
     909       57352 :   inline bool Validate(const byte* pc, GlobalIndexImmediate<validate>& imm) {
     910      114704 :     if (!VALIDATE(module_ != nullptr && imm.index < module_->globals.size())) {
     911          32 :       errorf(pc + 1, "invalid global index: %u", imm.index);
     912          32 :       return false;
     913             :     }
     914      114640 :     imm.global = &module_->globals[imm.index];
     915       57320 :     imm.type = imm.global->type;
     916       57320 :     return true;
     917             :   }
     918             : 
     919             :   inline bool CanReturnCall(FunctionSig* target_sig) {
     920         396 :     if (target_sig == nullptr) return false;
     921         396 :     size_t num_returns = sig_->return_count();
     922         396 :     if (num_returns != target_sig->return_count()) return false;
     923        1180 :     for (size_t i = 0; i < num_returns; ++i) {
     924         396 :       if (sig_->GetReturn(i) != target_sig->GetReturn(i)) return false;
     925             :     }
     926             :     return true;
     927             :   }
     928             : 
     929             :   inline bool Complete(const byte* pc, CallFunctionImmediate<validate>& imm) {
     930      532418 :     if (!VALIDATE(module_ != nullptr &&
     931             :                   imm.index < module_->functions.size())) {
     932             :       return false;
     933             :     }
     934      537042 :     imm.sig = module_->functions[imm.index].sig;
     935             :     return true;
     936             :   }
     937             : 
     938      266205 :   inline bool Validate(const byte* pc, CallFunctionImmediate<validate>& imm) {
     939      266205 :     if (Complete(pc, imm)) {
     940             :       return true;
     941             :     }
     942          96 :     errorf(pc + 1, "invalid function index: %u", imm.index);
     943          96 :     return false;
     944             :   }
     945             : 
     946             :   inline bool Complete(const byte* pc, CallIndirectImmediate<validate>& imm) {
     947       17542 :     if (!VALIDATE(module_ != nullptr &&
     948             :                   imm.sig_index < module_->signatures.size())) {
     949             :       return false;
     950             :     }
     951       17900 :     imm.sig = module_->signatures[imm.sig_index];
     952             :     return true;
     953             :   }
     954             : 
     955        8893 :   inline bool Validate(const byte* pc, CallIndirectImmediate<validate>& imm) {
     956       17780 :     if (!VALIDATE(module_ != nullptr &&
     957             :                   imm.table_index < module_->tables.size())) {
     958         102 :       error("function table has to exist to execute call_indirect");
     959         102 :       return false;
     960             :     }
     961       17579 :     if (!VALIDATE(module_ != nullptr &&
     962             :                   module_->tables[imm.table_index].type == kWasmAnyFunc)) {
     963          20 :       error("table of call_indirect must be of type anyfunc");
     964          20 :       return false;
     965             :     }
     966        8771 :     if (!Complete(pc, imm)) {
     967          70 :       errorf(pc + 1, "invalid signature index: #%u", imm.sig_index);
     968          70 :       return false;
     969             :     }
     970             :     return true;
     971             :   }
     972             : 
     973             :   inline bool Validate(const byte* pc, BranchDepthImmediate<validate>& imm,
     974             :                        size_t control_depth) {
     975      272322 :     if (!VALIDATE(imm.depth < control_depth)) {
     976         686 :       errorf(pc + 1, "invalid branch depth: %u", imm.depth);
     977             :       return false;
     978             :     }
     979             :     return true;
     980             :   }
     981             : 
     982       12984 :   bool Validate(const byte* pc, BranchTableImmediate<validate>& imm,
     983             :                 size_t block_depth) {
     984       12984 :     if (!VALIDATE(imm.table_count < kV8MaxWasmFunctionSize)) {
     985          24 :       errorf(pc + 1, "invalid table count (> max function size): %u",
     986             :              imm.table_count);
     987             :       return false;
     988             :     }
     989       12960 :     return checkAvailable(imm.table_count);
     990             :   }
     991             : 
     992         676 :   inline bool Validate(const byte* pc, WasmOpcode opcode,
     993             :                        SimdLaneImmediate<validate>& imm) {
     994             :     uint8_t num_lanes = 0;
     995             :     switch (opcode) {
     996             :       case kExprF32x4ExtractLane:
     997             :       case kExprF32x4ReplaceLane:
     998             :       case kExprI32x4ExtractLane:
     999             :       case kExprI32x4ReplaceLane:
    1000             :         num_lanes = 4;
    1001             :         break;
    1002             :       case kExprI16x8ExtractLane:
    1003             :       case kExprI16x8ReplaceLane:
    1004             :         num_lanes = 8;
    1005             :         break;
    1006             :       case kExprI8x16ExtractLane:
    1007             :       case kExprI8x16ReplaceLane:
    1008             :         num_lanes = 16;
    1009             :         break;
    1010             :       default:
    1011           0 :         UNREACHABLE();
    1012             :         break;
    1013             :     }
    1014         676 :     if (!VALIDATE(imm.lane >= 0 && imm.lane < num_lanes)) {
    1015           0 :       error(pc_ + 2, "invalid lane index");
    1016             :       return false;
    1017             :     } else {
    1018             :       return true;
    1019             :     }
    1020             :   }
    1021             : 
    1022        1272 :   inline bool Validate(const byte* pc, WasmOpcode opcode,
    1023             :                        SimdShiftImmediate<validate>& imm) {
    1024             :     uint8_t max_shift = 0;
    1025             :     switch (opcode) {
    1026             :       case kExprI32x4Shl:
    1027             :       case kExprI32x4ShrS:
    1028             :       case kExprI32x4ShrU:
    1029             :         max_shift = 32;
    1030             :         break;
    1031             :       case kExprI16x8Shl:
    1032             :       case kExprI16x8ShrS:
    1033             :       case kExprI16x8ShrU:
    1034             :         max_shift = 16;
    1035             :         break;
    1036             :       case kExprI8x16Shl:
    1037             :       case kExprI8x16ShrS:
    1038             :       case kExprI8x16ShrU:
    1039             :         max_shift = 8;
    1040             :         break;
    1041             :       default:
    1042           0 :         UNREACHABLE();
    1043             :         break;
    1044             :     }
    1045        1272 :     if (!VALIDATE(imm.shift >= 0 && imm.shift < max_shift)) {
    1046           0 :       error(pc_ + 2, "invalid shift amount");
    1047             :       return false;
    1048             :     } else {
    1049             :       return true;
    1050             :     }
    1051             :   }
    1052             : 
    1053       14801 :   inline bool Validate(const byte* pc,
    1054             :                        Simd8x16ShuffleImmediate<validate>& imm) {
    1055       14801 :     uint8_t max_lane = 0;
    1056      488433 :     for (uint32_t i = 0; i < kSimd128Size; ++i) {
    1057      473632 :       max_lane = std::max(max_lane, imm.shuffle[i]);
    1058             :     }
    1059             :     // Shuffle indices must be in [0..31] for a 16 lane shuffle.
    1060       14801 :     if (!VALIDATE(max_lane <= 2 * kSimd128Size)) {
    1061           0 :       error(pc_ + 2, "invalid shuffle mask");
    1062             :       return false;
    1063             :     }
    1064             :     return true;
    1065             :   }
    1066             : 
    1067      381511 :   inline bool Complete(BlockTypeImmediate<validate>& imm) {
    1068      381511 :     if (imm.type != kWasmVar) return true;
    1069         551 :     if (!VALIDATE(module_ && imm.sig_index < module_->signatures.size())) {
    1070             :       return false;
    1071             :     }
    1072         534 :     imm.sig = module_->signatures[imm.sig_index];
    1073             :     return true;
    1074             :   }
    1075             : 
    1076      381512 :   inline bool Validate(BlockTypeImmediate<validate>& imm) {
    1077      381512 :     if (!Complete(imm)) {
    1078          34 :       errorf(pc_, "block type index %u out of bounds (%zu signatures)",
    1079             :              imm.sig_index, module_ ? module_->signatures.size() : 0);
    1080          17 :       return false;
    1081             :     }
    1082             :     return true;
    1083             :   }
    1084             : 
    1085             :   inline bool Validate(const byte* pc, MemoryIndexImmediate<validate>& imm) {
    1086         278 :     if (!VALIDATE(module_ != nullptr && module_->has_memory)) {
    1087           2 :       errorf(pc + 1, "memory instruction with no memory");
    1088             :       return false;
    1089             :     }
    1090             :     return true;
    1091             :   }
    1092             : 
    1093          82 :   inline bool Validate(MemoryInitImmediate<validate>& imm) {
    1094          82 :     if (!VALIDATE(module_ != nullptr &&
    1095             :                   imm.data_segment_index <
    1096             :                       module_->num_declared_data_segments)) {
    1097           1 :       errorf(pc_ + 2, "invalid data segment index: %u", imm.data_segment_index);
    1098           1 :       return false;
    1099             :     }
    1100         162 :     if (!Validate(pc_ + imm.length - imm.memory.length - 1, imm.memory))
    1101             :       return false;
    1102          81 :     return true;
    1103             :   }
    1104             : 
    1105          42 :   inline bool Validate(DataDropImmediate<validate>& imm) {
    1106          42 :     if (!VALIDATE(module_ != nullptr &&
    1107             :                   imm.index < module_->num_declared_data_segments)) {
    1108           1 :       errorf(pc_ + 2, "invalid data segment index: %u", imm.index);
    1109             :       return false;
    1110             :     }
    1111             :     return true;
    1112             :   }
    1113             : 
    1114          66 :   inline bool Validate(MemoryCopyImmediate<validate>& imm) {
    1115         132 :     if (!Validate(pc_ + 1, imm.memory_src)) return false;
    1116         130 :     if (!Validate(pc_ + 2, imm.memory_dst)) return false;
    1117             :     return true;
    1118             :   }
    1119             : 
    1120         455 :   inline bool Validate(const byte* pc, TableIndexImmediate<validate>& imm) {
    1121         909 :     if (!VALIDATE(module_ != nullptr && imm.index < module_->tables.size())) {
    1122           5 :       errorf(pc, "invalid table index: %u", imm.index);
    1123           5 :       return false;
    1124             :     }
    1125             :     return true;
    1126             :   }
    1127             : 
    1128          56 :   inline bool Validate(TableInitImmediate<validate>& imm) {
    1129         111 :     if (!VALIDATE(module_ != nullptr &&
    1130             :                   imm.elem_segment_index < module_->elem_segments.size())) {
    1131           3 :       errorf(pc_ + 2, "invalid element segment index: %u",
    1132             :              imm.elem_segment_index);
    1133           3 :       return false;
    1134             :     }
    1135          53 :     if (!Validate(pc_ + imm.length - imm.table.length - 1, imm.table))
    1136             :       return false;
    1137          53 :     return true;
    1138             :   }
    1139             : 
    1140          35 :   inline bool Validate(ElemDropImmediate<validate>& imm) {
    1141          69 :     if (!VALIDATE(module_ != nullptr &&
    1142             :                   imm.index < module_->elem_segments.size())) {
    1143           2 :       errorf(pc_ + 2, "invalid element segment index: %u", imm.index);
    1144           2 :       return false;
    1145             :     }
    1146             :     return true;
    1147             :   }
    1148             : 
    1149          86 :   inline bool Validate(TableCopyImmediate<validate>& imm) {
    1150          86 :     if (!Validate(pc_ + 1, imm.table_src)) return false;
    1151          85 :     if (!Validate(pc_ + 2, imm.table_dst)) return false;
    1152          85 :     return true;
    1153             :   }
    1154             : 
    1155     3400267 :   static uint32_t OpcodeLength(Decoder* decoder, const byte* pc) {
    1156     3400267 :     WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
    1157     3400267 :     switch (opcode) {
    1158             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1159             :       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1160             :       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1161             : #undef DECLARE_OPCODE_CASE
    1162             :       {
    1163      143250 :         MemoryAccessImmediate<validate> imm(decoder, pc, UINT32_MAX);
    1164      143250 :         return 1 + imm.length;
    1165             :       }
    1166             :       case kExprBr:
    1167             :       case kExprBrIf: {
    1168             :         BranchDepthImmediate<validate> imm(decoder, pc);
    1169       55689 :         return 1 + imm.length;
    1170             :       }
    1171             :       case kExprGetGlobal:
    1172             :       case kExprSetGlobal: {
    1173             :         GlobalIndexImmediate<validate> imm(decoder, pc);
    1174       23772 :         return 1 + imm.length;
    1175             :       }
    1176             :       case kExprGetTable:
    1177             :       case kExprSetTable: {
    1178           0 :         TableIndexImmediate<validate> imm(decoder, pc);
    1179           0 :         return 1 + imm.length;
    1180             :       }
    1181             :       case kExprCallFunction:
    1182             :       case kExprReturnCall: {
    1183             :         CallFunctionImmediate<validate> imm(decoder, pc);
    1184       19664 :         return 1 + imm.length;
    1185             :       }
    1186             :       case kExprCallIndirect:
    1187             :       case kExprReturnCallIndirect: {
    1188        1297 :         CallIndirectImmediate<validate> imm(kAllWasmFeatures, decoder, pc);
    1189        1297 :         return 1 + imm.length;
    1190             :       }
    1191             : 
    1192             :       case kExprTry:
    1193             :       case kExprIf:  // fall through
    1194             :       case kExprLoop:
    1195             :       case kExprBlock: {
    1196      106188 :         BlockTypeImmediate<validate> imm(kAllWasmFeatures, decoder, pc);
    1197      106190 :         return 1 + imm.length;
    1198             :       }
    1199             : 
    1200             :       case kExprThrow: {
    1201             :         ExceptionIndexImmediate<validate> imm(decoder, pc);
    1202          13 :         return 1 + imm.length;
    1203             :       }
    1204             : 
    1205             :       case kExprBrOnExn: {
    1206             :         BranchDepthImmediate<validate> imm_br(decoder, pc);
    1207           9 :         ExceptionIndexImmediate<validate> imm_idx(decoder, pc + imm_br.length);
    1208           9 :         return 1 + imm_br.length + imm_idx.length;
    1209             :       }
    1210             : 
    1211             :       case kExprSetLocal:
    1212             :       case kExprTeeLocal:
    1213             :       case kExprGetLocal: {
    1214             :         LocalIndexImmediate<validate> imm(decoder, pc);
    1215      475467 :         return 1 + imm.length;
    1216             :       }
    1217             :       case kExprBrTable: {
    1218        4294 :         BranchTableImmediate<validate> imm(decoder, pc);
    1219             :         BranchTableIterator<validate> iterator(decoder, imm);
    1220        4294 :         return 1 + iterator.length();
    1221             :       }
    1222             :       case kExprI32Const: {
    1223             :         ImmI32Immediate<validate> imm(decoder, pc);
    1224     1160187 :         return 1 + imm.length;
    1225             :       }
    1226             :       case kExprI64Const: {
    1227             :         ImmI64Immediate<validate> imm(decoder, pc);
    1228        2728 :         return 1 + imm.length;
    1229             :       }
    1230             :       case kExprRefNull: {
    1231             :         return 1;
    1232             :       }
    1233             :       case kExprMemoryGrow:
    1234             :       case kExprMemorySize: {
    1235          72 :         MemoryIndexImmediate<validate> imm(decoder, pc);
    1236          72 :         return 1 + imm.length;
    1237             :       }
    1238             :       case kExprF32Const:
    1239         544 :         return 5;
    1240             :       case kExprF64Const:
    1241        3661 :         return 9;
    1242             :       case kNumericPrefix: {
    1243             :         byte numeric_index =
    1244           0 :             decoder->read_u8<validate>(pc + 1, "numeric_index");
    1245             :         WasmOpcode opcode =
    1246         108 :             static_cast<WasmOpcode>(kNumericPrefix << 8 | numeric_index);
    1247         108 :         switch (opcode) {
    1248             :           case kExprI32SConvertSatF32:
    1249             :           case kExprI32UConvertSatF32:
    1250             :           case kExprI32SConvertSatF64:
    1251             :           case kExprI32UConvertSatF64:
    1252             :           case kExprI64SConvertSatF32:
    1253             :           case kExprI64UConvertSatF32:
    1254             :           case kExprI64SConvertSatF64:
    1255             :           case kExprI64UConvertSatF64:
    1256             :             return 2;
    1257             :           case kExprMemoryInit: {
    1258          16 :             MemoryInitImmediate<validate> imm(decoder, pc);
    1259          16 :             return 2 + imm.length;
    1260             :           }
    1261             :           case kExprDataDrop: {
    1262             :             DataDropImmediate<validate> imm(decoder, pc);
    1263           8 :             return 2 + imm.length;
    1264             :           }
    1265             :           case kExprMemoryCopy: {
    1266           0 :             MemoryCopyImmediate<validate> imm(decoder, pc);
    1267           0 :             return 2 + imm.length;
    1268             :           }
    1269             :           case kExprMemoryFill: {
    1270           0 :             MemoryIndexImmediate<validate> imm(decoder, pc + 1);
    1271           0 :             return 2 + imm.length;
    1272             :           }
    1273             :           case kExprTableInit: {
    1274           0 :             TableInitImmediate<validate> imm(decoder, pc);
    1275           0 :             return 2 + imm.length;
    1276             :           }
    1277             :           case kExprElemDrop: {
    1278             :             ElemDropImmediate<validate> imm(decoder, pc);
    1279           0 :             return 2 + imm.length;
    1280             :           }
    1281             :           case kExprTableCopy: {
    1282           0 :             TableCopyImmediate<validate> imm(decoder, pc);
    1283           0 :             return 2 + imm.length;
    1284             :           }
    1285             :           default:
    1286           0 :             decoder->error(pc, "invalid numeric opcode");
    1287           0 :             return 2;
    1288             :         }
    1289             :       }
    1290             :       case kSimdPrefix: {
    1291          32 :         byte simd_index = decoder->read_u8<validate>(pc + 1, "simd_index");
    1292             :         WasmOpcode opcode =
    1293       15234 :             static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
    1294       15234 :         switch (opcode) {
    1295             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1296             :           FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
    1297             : #undef DECLARE_OPCODE_CASE
    1298             :           return 2;
    1299             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1300             :           FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
    1301             : #undef DECLARE_OPCODE_CASE
    1302         913 :           return 3;
    1303             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1304             :           FOREACH_SIMD_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1305             : #undef DECLARE_OPCODE_CASE
    1306             :           {
    1307           0 :             MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
    1308           0 :             return 2 + imm.length;
    1309             :           }
    1310             :           // Shuffles require a byte per lane, or 16 immediate bytes.
    1311             :           case kExprS8x16Shuffle:
    1312       12225 :             return 2 + kSimd128Size;
    1313             :           default:
    1314           1 :             decoder->error(pc, "invalid SIMD opcode");
    1315           1 :             return 2;
    1316             :         }
    1317             :       }
    1318             :       case kAtomicPrefix: {
    1319          74 :         byte atomic_index = decoder->read_u8<validate>(pc + 1, "atomic_index");
    1320             :         WasmOpcode opcode =
    1321         490 :             static_cast<WasmOpcode>(kAtomicPrefix << 8 | atomic_index);
    1322         490 :         switch (opcode) {
    1323             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1324             :           FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE)
    1325             : #undef DECLARE_OPCODE_CASE
    1326             :           {
    1327         490 :             MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
    1328         492 :             return 2 + imm.length;
    1329             :           }
    1330             :           default:
    1331           0 :             decoder->error(pc, "invalid Atomics opcode");
    1332           0 :             return 2;
    1333             :         }
    1334             :       }
    1335             :       default:
    1336             :         return 1;
    1337             :     }
    1338             :   }
    1339             : 
    1340     1979600 :   std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) {
    1341     1979600 :     WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
    1342             :     // Handle "simple" opcodes with a fixed signature first.
    1343     1979600 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    1344     1979600 :     if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode);
    1345     2330830 :     if (sig) return {sig->parameter_count(), sig->return_count()};
    1346             : 
    1347             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1348             :     // clang-format off
    1349     1628370 :     switch (opcode) {
    1350             :       case kExprSelect:
    1351          20 :         return {3, 1};
    1352             :       case kExprSetTable:
    1353             :       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1354       74496 :         return {2, 0};
    1355             :       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1356             :       case kExprGetTable:
    1357             :       case kExprTeeLocal:
    1358             :       case kExprMemoryGrow:
    1359       68533 :         return {1, 1};
    1360             :       case kExprSetLocal:
    1361             :       case kExprSetGlobal:
    1362             :       case kExprDrop:
    1363             :       case kExprBrIf:
    1364             :       case kExprBrTable:
    1365             :       case kExprIf:
    1366             :       case kExprRethrow:
    1367       75258 :         return {1, 0};
    1368             :       case kExprGetLocal:
    1369             :       case kExprGetGlobal:
    1370             :       case kExprI32Const:
    1371             :       case kExprI64Const:
    1372             :       case kExprF32Const:
    1373             :       case kExprF64Const:
    1374             :       case kExprRefNull:
    1375             :       case kExprMemorySize:
    1376      984202 :         return {0, 1};
    1377             :       case kExprCallFunction: {
    1378             :         CallFunctionImmediate<validate> imm(this, pc);
    1379             :         CHECK(Complete(pc, imm));
    1380        2396 :         return {imm.sig->parameter_count(), imm.sig->return_count()};
    1381             :       }
    1382             :       case kExprCallIndirect: {
    1383         248 :         CallIndirectImmediate<validate> imm(this->enabled_, this, pc);
    1384             :         CHECK(Complete(pc, imm));
    1385             :         // Indirect calls pop an additional argument for the table index.
    1386             :         return {imm.sig->parameter_count() + 1,
    1387         496 :                 imm.sig->return_count()};
    1388             :       }
    1389             :       case kExprThrow: {
    1390             :         ExceptionIndexImmediate<validate> imm(this, pc);
    1391             :         CHECK(Complete(pc, imm));
    1392             :         DCHECK_EQ(0, imm.exception->sig->return_count());
    1393          24 :         return {imm.exception->sig->parameter_count(), 0};
    1394             :       }
    1395             :       case kExprBr:
    1396             :       case kExprBlock:
    1397             :       case kExprLoop:
    1398             :       case kExprEnd:
    1399             :       case kExprElse:
    1400             :       case kExprTry:
    1401             :       case kExprCatch:
    1402             :       case kExprBrOnExn:
    1403             :       case kExprNop:
    1404             :       case kExprReturn:
    1405             :       case kExprReturnCall:
    1406             :       case kExprReturnCallIndirect:
    1407             :       case kExprUnreachable:
    1408      407617 :         return {0, 0};
    1409             :       case kNumericPrefix:
    1410             :       case kAtomicPrefix:
    1411             :       case kSimdPrefix: {
    1412       15588 :         opcode = static_cast<WasmOpcode>(opcode << 8 | *(pc + 1));
    1413       15588 :         switch (opcode) {
    1414             :           FOREACH_SIMD_1_OPERAND_1_PARAM_OPCODE(DECLARE_OPCODE_CASE)
    1415         720 :             return {1, 1};
    1416             :           FOREACH_SIMD_1_OPERAND_2_PARAM_OPCODE(DECLARE_OPCODE_CASE)
    1417             :           FOREACH_SIMD_MASK_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
    1418       12400 :             return {2, 1};
    1419             :           default: {
    1420        2468 :             sig = WasmOpcodes::Signature(opcode);
    1421        2468 :             if (sig) {
    1422        2468 :               return {sig->parameter_count(), sig->return_count()};
    1423             :             }
    1424             :           }
    1425             :         }
    1426             :         V8_FALLTHROUGH;
    1427             :       }
    1428             :       default:
    1429           0 :         V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x (%s)", opcode,
    1430             :                  WasmOpcodes::OpcodeName(opcode));
    1431             :         return {0, 0};
    1432             :     }
    1433             : #undef DECLARE_OPCODE_CASE
    1434             :     // clang-format on
    1435             :   }
    1436             : };
    1437             : 
    1438             : #define CALL_INTERFACE(name, ...) interface_.name(this, ##__VA_ARGS__)
    1439             : #define CALL_INTERFACE_IF_REACHABLE(name, ...)                 \
    1440             :   do {                                                         \
    1441             :     DCHECK(!control_.empty());                                 \
    1442             :     if (VALIDATE(this->ok()) && control_.back().reachable()) { \
    1443             :       interface_.name(this, ##__VA_ARGS__);                    \
    1444             :     }                                                          \
    1445             :   } while (false)
    1446             : #define CALL_INTERFACE_IF_PARENT_REACHABLE(name, ...)           \
    1447             :   do {                                                          \
    1448             :     DCHECK(!control_.empty());                                  \
    1449             :     if (VALIDATE(this->ok()) &&                                 \
    1450             :         (control_.size() == 1 || control_at(1)->reachable())) { \
    1451             :       interface_.name(this, ##__VA_ARGS__);                     \
    1452             :     }                                                           \
    1453             :   } while (false)
    1454             : 
    1455             : template <Decoder::ValidateFlag validate, typename Interface>
    1456     3126270 : class WasmFullDecoder : public WasmDecoder<validate> {
    1457             :   using Value = typename Interface::Value;
    1458             :   using Control = typename Interface::Control;
    1459             :   using MergeValues = Merge<Value>;
    1460             : 
    1461             :   // All Value types should be trivially copyable for performance. We push, pop,
    1462             :   // and store them in local variables.
    1463             :   ASSERT_TRIVIALLY_COPYABLE(Value);
    1464             : 
    1465             :  public:
    1466             :   template <typename... InterfaceArgs>
    1467      595039 :   WasmFullDecoder(Zone* zone, const WasmModule* module,
    1468             :                   const WasmFeatures& enabled, WasmFeatures* detected,
    1469             :                   const FunctionBody& body, InterfaceArgs&&... interface_args)
    1470             :       : WasmDecoder<validate>(module, enabled, detected, body.sig, body.start,
    1471             :                               body.end, body.offset),
    1472             :         zone_(zone),
    1473             :         interface_(std::forward<InterfaceArgs>(interface_args)...),
    1474             :         local_type_vec_(zone),
    1475             :         stack_(zone),
    1476             :         control_(zone),
    1477     3724589 :         args_(zone) {
    1478     1266834 :     this->local_types_ = &local_type_vec_;
    1479      594196 :   }
    1480             : 
    1481             :   Interface& interface() { return interface_; }
    1482             : 
    1483     1266580 :   bool Decode() {
    1484             :     DCHECK(stack_.empty());
    1485             :     DCHECK(control_.empty());
    1486             : 
    1487             :     base::ElapsedTimer decode_timer;
    1488             :     if (FLAG_trace_wasm_decode_time) {
    1489             :       decode_timer.Start();
    1490             :     }
    1491             : 
    1492     1266580 :     if (this->end_ < this->pc_) {
    1493           0 :       this->error("function body end < start");
    1494           0 :       return false;
    1495             :     }
    1496             : 
    1497             :     DCHECK_EQ(0, this->local_types_->size());
    1498     1266580 :     WasmDecoder<validate>::DecodeLocals(this->enabled_, this, this->sig_,
    1499             :                                         this->local_types_);
    1500     1099073 :     CALL_INTERFACE(StartFunction);
    1501     1266557 :     DecodeFunctionBody();
    1502     1097496 :     if (!this->failed()) CALL_INTERFACE(FinishFunction);
    1503             : 
    1504             :     // Generate a better error message whether the unterminated control
    1505             :     // structure is the function body block or an innner structure.
    1506     1265711 :     if (control_.size() > 1) {
    1507       13163 :       this->error(control_.back().pc, "unterminated control structure");
    1508     1252548 :     } else if (control_.size() == 1) {
    1509       53216 :       this->error("function body must end with \"end\" opcode");
    1510             :     }
    1511             : 
    1512     1265751 :     if (this->failed()) return this->TraceFailed();
    1513             : 
    1514             :     if (FLAG_trace_wasm_decode_time) {
    1515             :       double ms = decode_timer.Elapsed().InMillisecondsF();
    1516             :       PrintF("wasm-decode %s (%0.3f ms)\n\n",
    1517             :              VALIDATE(this->ok()) ? "ok" : "failed", ms);
    1518             :     } else {
    1519             :       TRACE("wasm-decode %s\n\n", VALIDATE(this->ok()) ? "ok" : "failed");
    1520             :     }
    1521             : 
    1522     1198789 :     return true;
    1523             :   }
    1524             : 
    1525             :   bool TraceFailed() {
    1526             :     TRACE("wasm-error module+%-6d func+%d: %s\n\n", this->error_.offset(),
    1527             :           this->GetBufferRelativeOffset(this->error_.offset()),
    1528             :           this->error_.message().c_str());
    1529             :     return false;
    1530             :   }
    1531             : 
    1532             :   const char* SafeOpcodeNameAt(const byte* pc) {
    1533       81114 :     if (pc >= this->end_) return "<end>";
    1534       67068 :     return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(*pc));
    1535             :   }
    1536             : 
    1537             :   inline Zone* zone() const { return zone_; }
    1538             : 
    1539             :   inline uint32_t num_locals() const {
    1540     1356658 :     return static_cast<uint32_t>(local_type_vec_.size());
    1541             :   }
    1542             : 
    1543             :   inline ValueType GetLocalType(uint32_t index) {
    1544     2713872 :     return local_type_vec_[index];
    1545             :   }
    1546             : 
    1547             :   inline WasmCodePosition position() {
    1548     1657130 :     int offset = static_cast<int>(this->pc_ - this->start_);
    1549             :     DCHECK_EQ(this->pc_ - this->start_, offset);  // overflows cannot happen
    1550             :     return offset;
    1551             :   }
    1552             : 
    1553             :   inline uint32_t control_depth() const {
    1554      374944 :     return static_cast<uint32_t>(control_.size());
    1555             :   }
    1556             : 
    1557             :   inline Control* control_at(uint32_t depth) {
    1558             :     DCHECK_GT(control_.size(), depth);
    1559      691493 :     return &control_.back() - depth;
    1560             :   }
    1561             : 
    1562             :   inline uint32_t stack_size() const {
    1563             :     DCHECK_GE(kMaxUInt32, stack_.size());
    1564     1663401 :     return static_cast<uint32_t>(stack_.size());
    1565             :   }
    1566             : 
    1567             :   inline Value* stack_value(uint32_t depth) {
    1568             :     DCHECK_LT(0, depth);
    1569             :     DCHECK_GE(stack_.size(), depth);
    1570             :     return &*(stack_.end() - depth);
    1571             :   }
    1572             : 
    1573             :  private:
    1574             :   Zone* zone_;
    1575             : 
    1576             :   Interface interface_;
    1577             : 
    1578             :   ZoneVector<ValueType> local_type_vec_;  // types of local variables.
    1579             :   ZoneVector<Value> stack_;               // stack of values.
    1580             :   ZoneVector<Control> control_;           // stack of blocks, loops, and ifs.
    1581             :   ZoneVector<Value> args_;                // parameters of current block or call
    1582             : 
    1583             :   static Value UnreachableValue(const uint8_t* pc) {
    1584             :     return Value{pc, kWasmVar};
    1585             :   }
    1586             : 
    1587             :   bool CheckHasMemory() {
    1588      466886 :     if (!VALIDATE(this->module_->has_memory)) {
    1589         216 :       this->error(this->pc_ - 1, "memory instruction with no memory");
    1590             :       return false;
    1591             :     }
    1592             :     return true;
    1593             :   }
    1594             : 
    1595             :   bool CheckHasSharedMemory() {
    1596       47365 :     if (!VALIDATE(this->module_->has_shared_memory)) {
    1597          24 :       this->error(this->pc_ - 1, "Atomic opcodes used without shared memory");
    1598             :       return false;
    1599             :     }
    1600             :     return true;
    1601             :   }
    1602             : 
    1603             :   class TraceLine {
    1604             :    public:
    1605             :     static constexpr int kMaxLen = 512;
    1606             :     ~TraceLine() {
    1607             :       if (!FLAG_trace_wasm_decoder) return;
    1608             :       PrintF("%.*s\n", len_, buffer_);
    1609             :     }
    1610             : 
    1611             :     // Appends a formatted string.
    1612             :     PRINTF_FORMAT(2, 3)
    1613             :     void Append(const char* format, ...) {
    1614             :       if (!FLAG_trace_wasm_decoder) return;
    1615             :       va_list va_args;
    1616             :       va_start(va_args, format);
    1617             :       size_t remaining_len = kMaxLen - len_;
    1618             :       Vector<char> remaining_msg_space(buffer_ + len_, remaining_len);
    1619             :       int len = VSNPrintF(remaining_msg_space, format, va_args);
    1620             :       va_end(va_args);
    1621             :       len_ += len < 0 ? remaining_len : len;
    1622             :     }
    1623             : 
    1624             :    private:
    1625             :     char buffer_[kMaxLen];
    1626             :     int len_ = 0;
    1627             :   };
    1628             : 
    1629             :   // Decodes the body of a function.
    1630     1266001 :   void DecodeFunctionBody() {
    1631             :     TRACE("wasm-decode %p...%p (module+%u, %d bytes)\n",
    1632             :           reinterpret_cast<const void*>(this->start()),
    1633             :           reinterpret_cast<const void*>(this->end()), this->pc_offset(),
    1634             :           static_cast<int>(this->end() - this->start()));
    1635             : 
    1636             :     // Set up initial function block.
    1637             :     {
    1638     1266001 :       auto* c = PushControl(kControlBlock);
    1639             :       InitMerge(&c->start_merge, 0, [](uint32_t) -> Value { UNREACHABLE(); });
    1640     2532160 :       InitMerge(&c->end_merge,
    1641     1266080 :                 static_cast<uint32_t>(this->sig_->return_count()),
    1642             :                 [&](uint32_t i) {
    1643      992855 :                   return Value{this->pc_, this->sig_->GetReturn(i)};
    1644      516510 :                 });
    1645      593741 :       CALL_INTERFACE(StartFunctionBody, c);
    1646             :     }
    1647             : 
    1648    24960108 :     while (this->pc_ < this->end_) {  // decoding loop.
    1649             :       uint32_t len = 1;
    1650    11846965 :       WasmOpcode opcode = static_cast<WasmOpcode>(*this->pc_);
    1651             : 
    1652             :       CALL_INTERFACE_IF_REACHABLE(NextInstruction, opcode);
    1653             : 
    1654             : #if DEBUG
    1655             :       TraceLine trace_msg;
    1656             : #define TRACE_PART(...) trace_msg.Append(__VA_ARGS__)
    1657             :       if (!WasmOpcodes::IsPrefixOpcode(opcode)) {
    1658             :         TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    1659             :                    WasmOpcodes::OpcodeName(opcode));
    1660             :       }
    1661             : #else
    1662             : #define TRACE_PART(...)
    1663             : #endif
    1664             : 
    1665    11846965 :       switch (opcode) {
    1666             : #define BUILD_SIMPLE_OPCODE(op, _, sig) \
    1667             :   case kExpr##op:                       \
    1668             :     BuildSimpleOperator_##sig(opcode);  \
    1669             :     break;
    1670             :         FOREACH_SIMPLE_OPCODE(BUILD_SIMPLE_OPCODE)
    1671             : #undef BUILD_SIMPLE_OPCODE
    1672             :         case kExprNop:
    1673             :           break;
    1674             :         case kExprBlock: {
    1675      318113 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1676      318110 :           if (!this->Validate(imm)) break;
    1677      318108 :           PopArgs(imm.sig);
    1678      318098 :           auto* block = PushControl(kControlBlock);
    1679      318119 :           SetBlockType(block, imm);
    1680       59953 :           CALL_INTERFACE_IF_REACHABLE(Block, block);
    1681      318104 :           PushMergeValues(block, &block->start_merge);
    1682      318117 :           len = 1 + imm.length;
    1683      318117 :           break;
    1684             :         }
    1685             :         case kExprRethrow: {
    1686         451 :           CHECK_PROTOTYPE_OPCODE(eh);
    1687             :           auto exception = Pop(0, kWasmExceptRef);
    1688         448 :           CALL_INTERFACE_IF_REACHABLE(Rethrow, exception);
    1689         450 :           EndControl();
    1690         450 :           break;
    1691             :         }
    1692             :         case kExprThrow: {
    1693         688 :           CHECK_PROTOTYPE_OPCODE(eh);
    1694         688 :           ExceptionIndexImmediate<validate> imm(this, this->pc_);
    1695         691 :           len = 1 + imm.length;
    1696         691 :           if (!this->Validate(this->pc_, imm)) break;
    1697         690 :           PopArgs(imm.exception->ToFunctionSig());
    1698        1212 :           CALL_INTERFACE_IF_REACHABLE(Throw, imm, VectorOf(args_));
    1699         689 :           EndControl();
    1700         689 :           break;
    1701             :         }
    1702             :         case kExprTry: {
    1703         793 :           CHECK_PROTOTYPE_OPCODE(eh);
    1704         793 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1705         793 :           if (!this->Validate(imm)) break;
    1706         793 :           PopArgs(imm.sig);
    1707         793 :           auto* try_block = PushControl(kControlTry);
    1708         792 :           SetBlockType(try_block, imm);
    1709         791 :           len = 1 + imm.length;
    1710         777 :           CALL_INTERFACE_IF_REACHABLE(Try, try_block);
    1711         790 :           PushMergeValues(try_block, &try_block->start_merge);
    1712         790 :           break;
    1713             :         }
    1714             :         case kExprCatch: {
    1715         549 :           CHECK_PROTOTYPE_OPCODE(eh);
    1716         549 :           if (!VALIDATE(!control_.empty())) {
    1717           0 :             this->error("catch does not match any try");
    1718           0 :             break;
    1719             :           }
    1720             :           Control* c = &control_.back();
    1721         549 :           if (!VALIDATE(c->is_try())) {
    1722           1 :             this->error("catch does not match any try");
    1723           1 :             break;
    1724             :           }
    1725         548 :           if (!VALIDATE(c->is_incomplete_try())) {
    1726           1 :             this->error("catch already present for try");
    1727           1 :             break;
    1728             :           }
    1729         547 :           c->kind = kControlTryCatch;
    1730         535 :           FallThruTo(c);
    1731        1094 :           stack_.erase(stack_.begin() + c->stack_depth, stack_.end());
    1732         547 :           c->reachability = control_at(1)->innerReachability();
    1733             :           auto* exception = Push(kWasmExceptRef);
    1734        1092 :           CALL_INTERFACE_IF_PARENT_REACHABLE(Catch, c, exception);
    1735             :           break;
    1736             :         }
    1737             :         case kExprBrOnExn: {
    1738         393 :           CHECK_PROTOTYPE_OPCODE(eh);
    1739         393 :           BranchDepthImmediate<validate> imm_br(this, this->pc_);
    1740         786 :           if (!this->Validate(this->pc_, imm_br, control_.size())) break;
    1741             :           ExceptionIndexImmediate<validate> imm_idx(this,
    1742         392 :                                                     this->pc_ + imm_br.length);
    1743         392 :           if (!this->Validate(this->pc_ + imm_br.length, imm_idx)) break;
    1744         384 :           Control* c = control_at(imm_br.depth);
    1745             :           auto exception = Pop(0, kWasmExceptRef);
    1746         384 :           const WasmExceptionSig* sig = imm_idx.exception->sig;
    1747             :           size_t value_count = sig->parameter_count();
    1748             :           // TODO(mstarzinger): This operand stack mutation is an ugly hack to
    1749             :           // make both type checking here as well as environment merging in the
    1750             :           // graph builder interface work out of the box. We should introduce
    1751             :           // special handling for both and do minimal/no stack mutation here.
    1752         882 :           for (size_t i = 0; i < value_count; ++i) Push(sig->GetParam(i));
    1753         376 :           Vector<Value> values(stack_.data() + c->stack_depth, value_count);
    1754         384 :           if (!TypeCheckBranch(c)) break;
    1755         384 :           if (control_.back().reachable()) {
    1756         376 :             CALL_INTERFACE(BrOnException, exception, imm_idx, imm_br.depth,
    1757             :                            values);
    1758         384 :             c->br_merge()->reached = true;
    1759             :           }
    1760         384 :           len = 1 + imm_br.length + imm_idx.length;
    1761         882 :           for (size_t i = 0; i < value_count; ++i) Pop();
    1762             :           auto* pexception = Push(kWasmExceptRef);
    1763         384 :           *pexception = exception;
    1764         384 :           break;
    1765             :         }
    1766             :         case kExprLoop: {
    1767       16791 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1768       16787 :           if (!this->Validate(imm)) break;
    1769       16788 :           PopArgs(imm.sig);
    1770       16789 :           auto* block = PushControl(kControlLoop);
    1771       16793 :           SetBlockType(&control_.back(), imm);
    1772       16792 :           len = 1 + imm.length;
    1773       11620 :           CALL_INTERFACE_IF_REACHABLE(Loop, block);
    1774       16787 :           PushMergeValues(block, &block->start_merge);
    1775       16785 :           break;
    1776             :         }
    1777             :         case kExprIf: {
    1778       45835 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1779       45837 :           if (!this->Validate(imm)) break;
    1780             :           auto cond = Pop(0, kWasmI32);
    1781       45820 :           PopArgs(imm.sig);
    1782       45818 :           if (!VALIDATE(this->ok())) break;
    1783       45220 :           auto* if_block = PushControl(kControlIf);
    1784       45233 :           SetBlockType(if_block, imm);
    1785       41848 :           CALL_INTERFACE_IF_REACHABLE(If, cond, if_block);
    1786       45237 :           len = 1 + imm.length;
    1787       45237 :           PushMergeValues(if_block, &if_block->start_merge);
    1788       45239 :           break;
    1789             :         }
    1790             :         case kExprElse: {
    1791       21660 :           if (!VALIDATE(!control_.empty())) {
    1792           0 :             this->error("else does not match any if");
    1793           0 :             break;
    1794             :           }
    1795             :           Control* c = &control_.back();
    1796       21660 :           if (!VALIDATE(c->is_if())) {
    1797           0 :             this->error(this->pc_, "else does not match an if");
    1798           0 :             break;
    1799             :           }
    1800       21660 :           if (c->is_if_else()) {
    1801           2 :             this->error(this->pc_, "else already present for if");
    1802           2 :             break;
    1803             :           }
    1804       21658 :           if (!TypeCheckFallThru(c)) break;
    1805       21401 :           c->kind = kControlIfElse;
    1806       39418 :           CALL_INTERFACE_IF_PARENT_REACHABLE(Else, c);
    1807       21396 :           if (c->reachable()) c->end_merge.reached = true;
    1808       21396 :           PushMergeValues(c, &c->start_merge);
    1809       21395 :           c->reachability = control_at(1)->innerReachability();
    1810       21395 :           break;
    1811             :         }
    1812             :         case kExprEnd: {
    1813     1570884 :           if (!VALIDATE(!control_.empty())) {
    1814           0 :             this->error("end does not match any if, try, or block");
    1815           0 :             break;
    1816             :           }
    1817             :           Control* c = &control_.back();
    1818     1570884 :           if (!VALIDATE(!c->is_incomplete_try())) {
    1819           1 :             this->error(this->pc_, "missing catch or catch-all in try");
    1820           1 :             break;
    1821             :           }
    1822     1570883 :           if (c->is_onearmed_if()) {
    1823       22284 :             if (!VALIDATE(c->end_merge.arity == c->start_merge.arity)) {
    1824         129 :               this->error(
    1825             :                   c->pc,
    1826             :                   "start-arity and end-arity of one-armed if must match");
    1827         129 :               break;
    1828             :             }
    1829             :           }
    1830             : 
    1831     1570754 :           if (!TypeCheckFallThru(c)) break;
    1832             : 
    1833     1563202 :           if (control_.size() == 1) {
    1834             :             // If at the last (implicit) control, check we are at end.
    1835     1199523 :             if (!VALIDATE(this->pc_ + 1 == this->end_)) {
    1836          86 :               this->error(this->pc_ + 1, "trailing code after function end");
    1837          85 :               break;
    1838             :             }
    1839             :             // The result of the block is the return value.
    1840             :             TRACE_PART("\n" TRACE_INST_FORMAT, startrel(this->pc_),
    1841             :                        "(implicit) return");
    1842     1065057 :             DoReturn();
    1843             :             control_.clear();
    1844             :             break;
    1845             :           }
    1846             : 
    1847      363679 :           PopControl(c);
    1848      363671 :           break;
    1849             :         }
    1850             :         case kExprSelect: {
    1851             :           auto cond = Pop(2, kWasmI32);
    1852             :           auto fval = Pop();
    1853        1294 :           auto tval = Pop(0, fval.type);
    1854        4249 :           auto* result = Push(tval.type == kWasmVar ? fval.type : tval.type);
    1855        2628 :           CALL_INTERFACE_IF_REACHABLE(Select, cond, fval, tval, result);
    1856             :           break;
    1857             :         }
    1858             :         case kExprBr: {
    1859       32578 :           BranchDepthImmediate<validate> imm(this, this->pc_);
    1860       65158 :           if (!this->Validate(this->pc_, imm, control_.size())) break;
    1861       31990 :           Control* c = control_at(imm.depth);
    1862       31990 :           if (!TypeCheckBranch(c)) break;
    1863       57912 :           if (imm.depth == control_.size() - 1) {
    1864         264 :             DoReturn();
    1865       28472 :           } else if (control_.back().reachable()) {
    1866       22741 :             CALL_INTERFACE(Br, c);
    1867       27849 :             c->br_merge()->reached = true;
    1868             :           }
    1869       28952 :           len = 1 + imm.length;
    1870       28952 :           EndControl();
    1871       28955 :           break;
    1872             :         }
    1873             :         case kExprBrIf: {
    1874      239696 :           BranchDepthImmediate<validate> imm(this, this->pc_);
    1875             :           auto cond = Pop(0, kWasmI32);
    1876      239692 :           if (this->failed()) break;
    1877      478701 :           if (!this->Validate(this->pc_, imm, control_.size())) break;
    1878      239255 :           Control* c = control_at(imm.depth);
    1879      239255 :           if (!TypeCheckBranch(c)) break;
    1880      238909 :           if (control_.back().reachable()) {
    1881      132368 :             CALL_INTERFACE(BrIf, cond, imm.depth);
    1882      238225 :             c->br_merge()->reached = true;
    1883             :           }
    1884      238911 :           len = 1 + imm.length;
    1885      238911 :           break;
    1886             :         }
    1887             :         case kExprBrTable: {
    1888       13220 :           BranchTableImmediate<validate> imm(this, this->pc_);
    1889             :           BranchTableIterator<validate> iterator(this, imm);
    1890             :           auto key = Pop(0, kWasmI32);
    1891       13207 :           if (this->failed()) break;
    1892       12982 :           if (!this->Validate(this->pc_, imm, control_.size())) break;
    1893             :           uint32_t br_arity = 0;
    1894       12940 :           std::vector<bool> br_targets(control_.size());
    1895      645521 :           while (iterator.has_next()) {
    1896             :             const uint32_t i = iterator.cur_index();
    1897             :             const byte* pos = iterator.pc();
    1898      633121 :             uint32_t target = iterator.next();
    1899     1266216 :             if (!VALIDATE(target < control_.size())) {
    1900         234 :               this->errorf(pos,
    1901             :                            "improper branch in br_table target %u (depth %u)",
    1902             :                            i, target);
    1903         234 :               break;
    1904             :             }
    1905             :             // Avoid redundant branch target checks.
    1906      632874 :             if (br_targets[target]) continue;
    1907             :             br_targets[target] = true;
    1908             :             // Check that label types match up.
    1909             :             Control* c = control_at(target);
    1910       29439 :             uint32_t arity = c->br_merge()->arity;
    1911       29439 :             if (i == 0) {
    1912             :               br_arity = arity;
    1913       16576 :             } else if (!VALIDATE(br_arity == arity)) {
    1914          84 :               this->errorf(pos,
    1915             :                            "inconsistent arity in br_table target %u"
    1916             :                            " (previous was %u, this one %u)",
    1917             :                            i, br_arity, arity);
    1918             :             }
    1919       29439 :             if (!TypeCheckBranch(c)) break;
    1920             :           }
    1921       12927 :           if (this->failed()) break;
    1922             : 
    1923       12335 :           if (control_.back().reachable()) {
    1924       10620 :             CALL_INTERFACE(BrTable, imm, key);
    1925             : 
    1926       70670 :             for (uint32_t depth = control_depth(); depth-- > 0;) {
    1927      117752 :               if (!br_targets[depth]) continue;
    1928       28194 :               control_at(depth)->br_merge()->reached = true;
    1929             :             }
    1930             :           }
    1931             : 
    1932       12338 :           len = 1 + iterator.length();
    1933       12327 :           EndControl();
    1934       12325 :           break;
    1935             :         }
    1936             :         case kExprReturn: {
    1937      303474 :           if (!TypeCheckReturn()) break;
    1938      194436 :           DoReturn();
    1939      302578 :           EndControl();
    1940      302535 :           break;
    1941             :         }
    1942             :         case kExprUnreachable: {
    1943      110768 :           CALL_INTERFACE_IF_REACHABLE(Unreachable);
    1944      220350 :           EndControl();
    1945      220354 :           break;
    1946             :         }
    1947             :         case kExprI32Const: {
    1948     3065136 :           ImmI32Immediate<validate> imm(this, this->pc_);
    1949             :           auto* value = Push(kWasmI32);
    1950     2953058 :           CALL_INTERFACE_IF_REACHABLE(I32Const, value, imm.value);
    1951     3066453 :           len = 1 + imm.length;
    1952             :           break;
    1953             :         }
    1954             :         case kExprI64Const: {
    1955       97967 :           ImmI64Immediate<validate> imm(this, this->pc_);
    1956             :           auto* value = Push(kWasmI64);
    1957       63812 :           CALL_INTERFACE_IF_REACHABLE(I64Const, value, imm.value);
    1958       98113 :           len = 1 + imm.length;
    1959             :           break;
    1960             :         }
    1961             :         case kExprF32Const: {
    1962      240356 :           ImmF32Immediate<validate> imm(this, this->pc_);
    1963             :           auto* value = Push(kWasmF32);
    1964      121721 :           CALL_INTERFACE_IF_REACHABLE(F32Const, value, imm.value);
    1965      240360 :           len = 1 + imm.length;
    1966             :           break;
    1967             :         }
    1968             :         case kExprF64Const: {
    1969      246019 :           ImmF64Immediate<validate> imm(this, this->pc_);
    1970             :           auto* value = Push(kWasmF64);
    1971      128346 :           CALL_INTERFACE_IF_REACHABLE(F64Const, value, imm.value);
    1972      246024 :           len = 1 + imm.length;
    1973             :           break;
    1974             :         }
    1975             :         case kExprRefNull: {
    1976         146 :           CHECK_PROTOTYPE_OPCODE(anyref);
    1977             :           auto* value = Push(kWasmNullRef);
    1978         146 :           CALL_INTERFACE_IF_REACHABLE(RefNull, value);
    1979             :           len = 1;
    1980             :           break;
    1981             :         }
    1982             :         case kExprGetLocal: {
    1983      876662 :           LocalIndexImmediate<validate> imm(this, this->pc_);
    1984      876865 :           if (!this->Validate(this->pc_, imm)) break;
    1985      876528 :           auto* value = Push(imm.type);
    1986      817862 :           CALL_INTERFACE_IF_REACHABLE(GetLocal, value, imm);
    1987      876727 :           len = 1 + imm.length;
    1988      876727 :           break;
    1989             :         }
    1990             :         case kExprSetLocal: {
    1991      442832 :           LocalIndexImmediate<validate> imm(this, this->pc_);
    1992      442833 :           if (!this->Validate(this->pc_, imm)) break;
    1993      885280 :           auto value = Pop(0, local_type_vec_[imm.index]);
    1994      431299 :           CALL_INTERFACE_IF_REACHABLE(SetLocal, value, imm);
    1995      442632 :           len = 1 + imm.length;
    1996      442632 :           break;
    1997             :         }
    1998             :         case kExprTeeLocal: {
    1999      101463 :           LocalIndexImmediate<validate> imm(this, this->pc_);
    2000      101460 :           if (!this->Validate(this->pc_, imm)) break;
    2001      202920 :           auto value = Pop(0, local_type_vec_[imm.index]);
    2002             :           auto* result = Push(value.type);
    2003      100002 :           CALL_INTERFACE_IF_REACHABLE(TeeLocal, value, result, imm);
    2004      101461 :           len = 1 + imm.length;
    2005      101461 :           break;
    2006             :         }
    2007             :         case kExprDrop: {
    2008             :           auto value = Pop();
    2009        3294 :           CALL_INTERFACE_IF_REACHABLE(Drop, value);
    2010             :           break;
    2011             :         }
    2012             :         case kExprGetGlobal: {
    2013       38576 :           GlobalIndexImmediate<validate> imm(this, this->pc_);
    2014       38578 :           len = 1 + imm.length;
    2015       38578 :           if (!this->Validate(this->pc_, imm)) break;
    2016       38547 :           auto* result = Push(imm.type);
    2017       38000 :           CALL_INTERFACE_IF_REACHABLE(GetGlobal, result, imm);
    2018             :           break;
    2019             :         }
    2020             :         case kExprSetGlobal: {
    2021       18779 :           GlobalIndexImmediate<validate> imm(this, this->pc_);
    2022       18779 :           len = 1 + imm.length;
    2023       18779 :           if (!this->Validate(this->pc_, imm)) break;
    2024       18779 :           if (!VALIDATE(imm.global->mutability)) {
    2025          33 :             this->errorf(this->pc_, "immutable global #%u cannot be assigned",
    2026             :                          imm.index);
    2027          33 :             break;
    2028             :           }
    2029       18746 :           auto value = Pop(0, imm.type);
    2030       18298 :           CALL_INTERFACE_IF_REACHABLE(SetGlobal, value, imm);
    2031             :           break;
    2032             :         }
    2033             :         case kExprGetTable: {
    2034         155 :           CHECK_PROTOTYPE_OPCODE(anyref);
    2035         155 :           TableIndexImmediate<validate> imm(this, this->pc_);
    2036         155 :           len = 1 + imm.length;
    2037         155 :           if (!this->Validate(this->pc_, imm)) break;
    2038             :           DCHECK_NOT_NULL(this->module_);
    2039             :           auto index = Pop(0, kWasmI32);
    2040         306 :           auto* result = Push(this->module_->tables[imm.index].type);
    2041         163 :           CALL_INTERFACE_IF_REACHABLE(GetTable, index, result, imm);
    2042             :           break;
    2043             :         }
    2044             :         case kExprSetTable: {
    2045          76 :           CHECK_PROTOTYPE_OPCODE(anyref);
    2046          76 :           TableIndexImmediate<validate> imm(this, this->pc_);
    2047          76 :           len = 1 + imm.length;
    2048          76 :           if (!this->Validate(this->pc_, imm)) break;
    2049         148 :           auto value = Pop(0, this->module_->tables[imm.index].type);
    2050             :           auto index = Pop(0, kWasmI32);
    2051          80 :           CALL_INTERFACE_IF_REACHABLE(SetTable, index, value, imm);
    2052             :           break;
    2053             :         }
    2054             : 
    2055             :         case kExprI32LoadMem8S:
    2056        3249 :           len = 1 + DecodeLoadMem(LoadType::kI32Load8S);
    2057        3249 :           break;
    2058             :         case kExprI32LoadMem8U:
    2059        2052 :           len = 1 + DecodeLoadMem(LoadType::kI32Load8U);
    2060        2052 :           break;
    2061             :         case kExprI32LoadMem16S:
    2062         498 :           len = 1 + DecodeLoadMem(LoadType::kI32Load16S);
    2063         498 :           break;
    2064             :         case kExprI32LoadMem16U:
    2065         815 :           len = 1 + DecodeLoadMem(LoadType::kI32Load16U);
    2066         816 :           break;
    2067             :         case kExprI32LoadMem:
    2068       86623 :           len = 1 + DecodeLoadMem(LoadType::kI32Load);
    2069       86516 :           break;
    2070             :         case kExprI64LoadMem8S:
    2071         522 :           len = 1 + DecodeLoadMem(LoadType::kI64Load8S);
    2072         523 :           break;
    2073             :         case kExprI64LoadMem8U:
    2074         418 :           len = 1 + DecodeLoadMem(LoadType::kI64Load8U);
    2075         417 :           break;
    2076             :         case kExprI64LoadMem16S:
    2077         475 :           len = 1 + DecodeLoadMem(LoadType::kI64Load16S);
    2078         475 :           break;
    2079             :         case kExprI64LoadMem16U:
    2080         464 :           len = 1 + DecodeLoadMem(LoadType::kI64Load16U);
    2081         466 :           break;
    2082             :         case kExprI64LoadMem32S:
    2083         499 :           len = 1 + DecodeLoadMem(LoadType::kI64Load32S);
    2084         497 :           break;
    2085             :         case kExprI64LoadMem32U:
    2086         490 :           len = 1 + DecodeLoadMem(LoadType::kI64Load32U);
    2087         489 :           break;
    2088             :         case kExprI64LoadMem:
    2089       89860 :           len = 1 + DecodeLoadMem(LoadType::kI64Load);
    2090       89858 :           break;
    2091             :         case kExprF32LoadMem:
    2092        2873 :           len = 1 + DecodeLoadMem(LoadType::kF32Load);
    2093        2875 :           break;
    2094             :         case kExprF64LoadMem:
    2095        3862 :           len = 1 + DecodeLoadMem(LoadType::kF64Load);
    2096        3863 :           break;
    2097             :         case kExprI32StoreMem8:
    2098        2426 :           len = 1 + DecodeStoreMem(StoreType::kI32Store8);
    2099        2428 :           break;
    2100             :         case kExprI32StoreMem16:
    2101         881 :           len = 1 + DecodeStoreMem(StoreType::kI32Store16);
    2102         882 :           break;
    2103             :         case kExprI32StoreMem:
    2104      160514 :           len = 1 + DecodeStoreMem(StoreType::kI32Store);
    2105      160458 :           break;
    2106             :         case kExprI64StoreMem8:
    2107         352 :           len = 1 + DecodeStoreMem(StoreType::kI64Store8);
    2108         352 :           break;
    2109             :         case kExprI64StoreMem16:
    2110         512 :           len = 1 + DecodeStoreMem(StoreType::kI64Store16);
    2111         512 :           break;
    2112             :         case kExprI64StoreMem32:
    2113         463 :           len = 1 + DecodeStoreMem(StoreType::kI64Store32);
    2114         463 :           break;
    2115             :         case kExprI64StoreMem:
    2116      102098 :           len = 1 + DecodeStoreMem(StoreType::kI64Store);
    2117      102076 :           break;
    2118             :         case kExprF32StoreMem:
    2119         805 :           len = 1 + DecodeStoreMem(StoreType::kF32Store);
    2120         805 :           break;
    2121             :         case kExprF64StoreMem:
    2122        1725 :           len = 1 + DecodeStoreMem(StoreType::kF64Store);
    2123        1725 :           break;
    2124             :         case kExprMemoryGrow: {
    2125        3397 :           if (!CheckHasMemory()) break;
    2126        3341 :           MemoryIndexImmediate<validate> imm(this, this->pc_);
    2127        3341 :           len = 1 + imm.length;
    2128             :           DCHECK_NOT_NULL(this->module_);
    2129        3341 :           if (!VALIDATE(this->module_->origin == kWasmOrigin)) {
    2130           1 :             this->error("grow_memory is not supported for asmjs modules");
    2131           1 :             break;
    2132             :           }
    2133             :           auto value = Pop(0, kWasmI32);
    2134             :           auto* result = Push(kWasmI32);
    2135        3846 :           CALL_INTERFACE_IF_REACHABLE(MemoryGrow, value, result);
    2136             :           break;
    2137             :         }
    2138             :         case kExprMemorySize: {
    2139        1134 :           if (!CheckHasMemory()) break;
    2140        1102 :           MemoryIndexImmediate<validate> imm(this, this->pc_);
    2141             :           auto* result = Push(kWasmI32);
    2142        1102 :           len = 1 + imm.length;
    2143        1152 :           CALL_INTERFACE_IF_REACHABLE(CurrentMemoryPages, result);
    2144             :           break;
    2145             :         }
    2146             :         case kExprCallFunction: {
    2147      266038 :           CallFunctionImmediate<validate> imm(this, this->pc_);
    2148      265950 :           len = 1 + imm.length;
    2149      265950 :           if (!this->Validate(this->pc_, imm)) break;
    2150             :           // TODO(clemensh): Better memory management.
    2151      265879 :           PopArgs(imm.sig);
    2152      265917 :           auto* returns = PushReturns(imm.sig);
    2153      151621 :           CALL_INTERFACE_IF_REACHABLE(CallDirect, imm, args_.data(), returns);
    2154             :           break;
    2155             :         }
    2156             :         case kExprCallIndirect: {
    2157        8736 :           CallIndirectImmediate<validate> imm(this->enabled_, this, this->pc_);
    2158        8737 :           len = 1 + imm.length;
    2159        8737 :           if (!this->Validate(this->pc_, imm)) break;
    2160             :           auto index = Pop(0, kWasmI32);
    2161        8553 :           PopArgs(imm.sig);
    2162        8558 :           auto* returns = PushReturns(imm.sig);
    2163        6576 :           CALL_INTERFACE_IF_REACHABLE(CallIndirect, index, imm, args_.data(),
    2164             :                                       returns);
    2165             :           break;
    2166             :         }
    2167             :         case kExprReturnCall: {
    2168         255 :           CHECK_PROTOTYPE_OPCODE(return_call);
    2169             : 
    2170         255 :           CallFunctionImmediate<validate> imm(this, this->pc_);
    2171         255 :           len = 1 + imm.length;
    2172         255 :           if (!this->Validate(this->pc_, imm)) break;
    2173         510 :           if (!this->CanReturnCall(imm.sig)) {
    2174           4 :             OPCODE_ERROR(opcode, "tail call return types mismatch");
    2175           4 :             break;
    2176             :           }
    2177             : 
    2178             :           PopArgs(imm.sig);
    2179             : 
    2180         244 :           CALL_INTERFACE_IF_REACHABLE(ReturnCall, imm, args_.data());
    2181         252 :           EndControl();
    2182         252 :           break;
    2183             :         }
    2184             :         case kExprReturnCallIndirect: {
    2185         157 :           CHECK_PROTOTYPE_OPCODE(return_call);
    2186         156 :           CallIndirectImmediate<validate> imm(this->enabled_, this, this->pc_);
    2187         156 :           len = 1 + imm.length;
    2188         156 :           if (!this->Validate(this->pc_, imm)) break;
    2189         282 :           if (!this->CanReturnCall(imm.sig)) {
    2190           0 :             OPCODE_ERROR(opcode, "tail call return types mismatch");
    2191           0 :             break;
    2192             :           }
    2193             :           auto index = Pop(0, kWasmI32);
    2194         141 :           PopArgs(imm.sig);
    2195         136 :           CALL_INTERFACE_IF_REACHABLE(ReturnCallIndirect, index, imm,
    2196             :                                       args_.data());
    2197         141 :           EndControl();
    2198         141 :           break;
    2199             :         }
    2200             :         case kNumericPrefix: {
    2201             :           ++len;
    2202             :           byte numeric_index =
    2203         538 :               this->template read_u8<validate>(this->pc_ + 1, "numeric index");
    2204         538 :           opcode = static_cast<WasmOpcode>(opcode << 8 | numeric_index);
    2205         538 :           if (opcode < kExprMemoryInit) {
    2206          98 :             CHECK_PROTOTYPE_OPCODE(sat_f2i_conversions);
    2207             :           } else {
    2208         440 :             CHECK_PROTOTYPE_OPCODE(bulk_memory);
    2209             :           }
    2210             :           TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    2211             :                      WasmOpcodes::OpcodeName(opcode));
    2212         529 :           len += DecodeNumericOpcode(opcode);
    2213         529 :           break;
    2214             :         }
    2215             :         case kSimdPrefix: {
    2216       20921 :           CHECK_PROTOTYPE_OPCODE(simd);
    2217             :           len++;
    2218             :           byte simd_index =
    2219       20921 :               this->template read_u8<validate>(this->pc_ + 1, "simd index");
    2220       20921 :           opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
    2221             :           TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    2222             :                      WasmOpcodes::OpcodeName(opcode));
    2223       20921 :           len += DecodeSimdOpcode(opcode);
    2224       20921 :           break;
    2225             :         }
    2226             :         case kAtomicPrefix: {
    2227       47365 :           CHECK_PROTOTYPE_OPCODE(threads);
    2228       47385 :           if (!CheckHasSharedMemory()) break;
    2229             :           len++;
    2230             :           byte atomic_index =
    2231       47361 :               this->template read_u8<validate>(this->pc_ + 1, "atomic index");
    2232       47420 :           opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_index);
    2233             :           TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    2234             :                      WasmOpcodes::OpcodeName(opcode));
    2235       47420 :           len += DecodeAtomicOpcode(opcode);
    2236       47634 :           break;
    2237             :         }
    2238             : // Note that prototype opcodes are not handled in the fastpath
    2239             : // above this switch, to avoid checking a feature flag.
    2240             : #define SIMPLE_PROTOTYPE_CASE(name, opc, sig) \
    2241             :   case kExpr##name: /* fallthrough */
    2242             :           FOREACH_SIMPLE_PROTOTYPE_OPCODE(SIMPLE_PROTOTYPE_CASE)
    2243             : #undef SIMPLE_PROTOTYPE_CASE
    2244          88 :           BuildSimplePrototypeOperator(opcode);
    2245          88 :           break;
    2246             :         default: {
    2247             :           // Deal with special asmjs opcodes.
    2248      200384 :           if (this->module_ != nullptr &&
    2249      100192 :               this->module_->origin == kAsmJsOrigin) {
    2250      100161 :             FunctionSig* sig = WasmOpcodes::AsmjsSignature(opcode);
    2251      100161 :             if (sig) {
    2252      100161 :               BuildSimpleOperator(opcode, sig);
    2253             :             }
    2254             :           } else {
    2255          31 :             this->error("Invalid opcode");
    2256          31 :             return;
    2257             :           }
    2258             :         }
    2259             :       }
    2260             : 
    2261             : #if DEBUG
    2262             :       if (FLAG_trace_wasm_decoder) {
    2263             :         TRACE_PART(" ");
    2264             :         for (Control& c : control_) {
    2265             :           switch (c.kind) {
    2266             :             case kControlIf:
    2267             :               TRACE_PART("I");
    2268             :               break;
    2269             :             case kControlBlock:
    2270             :               TRACE_PART("B");
    2271             :               break;
    2272             :             case kControlLoop:
    2273             :               TRACE_PART("L");
    2274             :               break;
    2275             :             case kControlTry:
    2276             :               TRACE_PART("T");
    2277             :               break;
    2278             :             default:
    2279             :               break;
    2280             :           }
    2281             :           if (c.start_merge.arity) TRACE_PART("%u-", c.start_merge.arity);
    2282             :           TRACE_PART("%u", c.end_merge.arity);
    2283             :           if (!c.reachable()) TRACE_PART("%c", c.unreachable() ? '*' : '#');
    2284             :         }
    2285             :         TRACE_PART(" | ");
    2286             :         for (size_t i = 0; i < stack_.size(); ++i) {
    2287             :           auto& val = stack_[i];
    2288             :           WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
    2289             :           if (WasmOpcodes::IsPrefixOpcode(opcode)) {
    2290             :             opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1));
    2291             :           }
    2292             :           TRACE_PART(" %c@%d:%s", ValueTypes::ShortNameOf(val.type),
    2293             :                      static_cast<int>(val.pc - this->start_),
    2294             :                      WasmOpcodes::OpcodeName(opcode));
    2295             :           // If the decoder failed, don't try to decode the immediates, as this
    2296             :           // can trigger a DCHECK failure.
    2297             :           if (this->failed()) continue;
    2298             :           switch (opcode) {
    2299             :             case kExprI32Const: {
    2300             :               ImmI32Immediate<Decoder::kNoValidate> imm(this, val.pc);
    2301             :               TRACE_PART("[%d]", imm.value);
    2302             :               break;
    2303             :             }
    2304             :             case kExprGetLocal:
    2305             :             case kExprSetLocal:
    2306             :             case kExprTeeLocal: {
    2307             :               LocalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
    2308             :               TRACE_PART("[%u]", imm.index);
    2309             :               break;
    2310             :             }
    2311             :             case kExprGetGlobal:
    2312             :             case kExprSetGlobal: {
    2313             :               GlobalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
    2314             :               TRACE_PART("[%u]", imm.index);
    2315             :               break;
    2316             :             }
    2317             :             default:
    2318             :               break;
    2319             :           }
    2320             :         }
    2321             :       }
    2322             : #endif
    2323    11847508 :       this->pc_ += len;
    2324             :     }  // end decode loop
    2325     1265635 :     if (!VALIDATE(this->pc_ == this->end_) && this->ok()) {
    2326           0 :       this->error("Beyond end of code");
    2327             :     }
    2328             :   }
    2329             : 
    2330      565642 :   void EndControl() {
    2331             :     DCHECK(!control_.empty());
    2332             :     auto* current = &control_.back();
    2333     1131284 :     stack_.erase(stack_.begin() + current->stack_depth, stack_.end());
    2334      101501 :     CALL_INTERFACE_IF_REACHABLE(EndControl, current);
    2335      565694 :     current->reachability = kUnreachable;
    2336      565694 :   }
    2337             : 
    2338             :   template<typename func>
    2339     2027645 :   void InitMerge(Merge<Value>* merge, uint32_t arity, func get_val) {
    2340     3293725 :     merge->arity = arity;
    2341     2027645 :     if (arity == 1) {
    2342     1018210 :       merge->vals.first = get_val(0);
    2343     1009435 :     } else if (arity > 1) {
    2344        6324 :       merge->vals.array = zone_->NewArray<Value>(arity);
    2345       15866 :       for (uint32_t i = 0; i < arity; i++) {
    2346       12704 :         merge->vals.array[i] = get_val(i);
    2347             :       }
    2348             :     }
    2349     2027645 :   }
    2350             : 
    2351      380921 :   void SetBlockType(Control* c, BlockTypeImmediate<validate>& imm) {
    2352             :     DCHECK_EQ(imm.in_arity(), this->args_.size());
    2353      380921 :     const byte* pc = this->pc_;
    2354             :     Value* args = this->args_.data();
    2355      761842 :     InitMerge(&c->end_merge, imm.out_arity(), [pc, &imm](uint32_t i) {
    2356             :       return Value{pc, imm.out_type(i)};
    2357             :     });
    2358      761828 :     InitMerge(&c->start_merge, imm.in_arity(),
    2359         218 :               [args](uint32_t i) { return args[i]; });
    2360      380915 :   }
    2361             : 
    2362             :   // Pops arguments as required by signature into {args_}.
    2363             :   V8_INLINE void PopArgs(FunctionSig* sig) {
    2364      708675 :     int count = sig ? static_cast<int>(sig->parameter_count()) : 0;
    2365      708675 :     args_.resize(count, UnreachableValue(nullptr));
    2366     1346661 :     for (int i = count - 1; i >= 0; --i) {
    2367     1275743 :       args_[i] = Pop(i, sig->GetParam(i));
    2368             :     }
    2369             :   }
    2370             : 
    2371             :   ValueType GetReturnType(FunctionSig* sig) {
    2372             :     DCHECK_GE(1, sig->return_count());
    2373       89094 :     return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn();
    2374             :   }
    2375             : 
    2376     1646579 :   Control* PushControl(ControlKind kind) {
    2377             :     Reachability reachability =
    2378     3293158 :         control_.empty() ? kReachable : control_.back().innerReachability();
    2379     3293158 :     control_.emplace_back(kind, stack_size(), this->pc_, reachability);
    2380     1646950 :     return &control_.back();
    2381             :   }
    2382             : 
    2383      363673 :   void PopControl(Control* c) {
    2384             :     DCHECK_EQ(c, &control_.back());
    2385      486697 :     CALL_INTERFACE_IF_PARENT_REACHABLE(PopControl, c);
    2386             : 
    2387             :     // A loop just leaves the values on the stack.
    2388      363682 :     if (!c->is_loop()) PushMergeValues(c, &c->end_merge);
    2389             : 
    2390             :     bool parent_reached =
    2391      363674 :         c->reachable() || c->end_merge.reached || c->is_onearmed_if();
    2392             :     control_.pop_back();
    2393             :     // If the parent block was reachable before, but the popped control does not
    2394             :     // return to here, this block becomes "spec only reachable".
    2395      363677 :     if (!parent_reached && control_.back().reachable()) {
    2396       38052 :       control_.back().reachability = kSpecOnlyReachable;
    2397             :     }
    2398      363677 :   }
    2399             : 
    2400      192655 :   int DecodeLoadMem(LoadType type, int prefix_len = 0) {
    2401      192686 :     if (!CheckHasMemory()) return 0;
    2402      192622 :     MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
    2403      192622 :                                         type.size_log_2());
    2404             :     auto index = Pop(0, kWasmI32);
    2405             :     auto* result = Push(type.value_type());
    2406      180214 :     CALL_INTERFACE_IF_REACHABLE(LoadMem, type, imm, index, result);
    2407      192649 :     return imm.length;
    2408             :   }
    2409             : 
    2410      269700 :   int DecodeStoreMem(StoreType store, int prefix_len = 0) {
    2411      269805 :     if (!CheckHasMemory()) return 0;
    2412      269741 :     MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
    2413      269741 :                                         store.size_log_2());
    2414             :     auto value = Pop(1, store.value_type());
    2415             :     auto index = Pop(0, kWasmI32);
    2416      258505 :     CALL_INTERFACE_IF_REACHABLE(StoreMem, store, imm, index, value);
    2417      269819 :     return imm.length;
    2418             :   }
    2419             : 
    2420         276 :   uint32_t SimdExtractLane(WasmOpcode opcode, ValueType type) {
    2421         276 :     SimdLaneImmediate<validate> imm(this, this->pc_);
    2422         276 :     if (this->Validate(this->pc_, opcode, imm)) {
    2423           0 :       Value inputs[] = {Pop(0, kWasmS128)};
    2424             :       auto* result = Push(type);
    2425         276 :       CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
    2426             :                                   result);
    2427             :     }
    2428         276 :     return imm.length;
    2429             :   }
    2430             : 
    2431         400 :   uint32_t SimdReplaceLane(WasmOpcode opcode, ValueType type) {
    2432         400 :     SimdLaneImmediate<validate> imm(this, this->pc_);
    2433         400 :     if (this->Validate(this->pc_, opcode, imm)) {
    2434         400 :       Value inputs[2] = {UnreachableValue(this->pc_),
    2435           0 :                          UnreachableValue(this->pc_)};
    2436         400 :       inputs[1] = Pop(1, type);
    2437         400 :       inputs[0] = Pop(0, kWasmS128);
    2438             :       auto* result = Push(kWasmS128);
    2439         400 :       CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
    2440             :                                   result);
    2441             :     }
    2442         400 :     return imm.length;
    2443             :   }
    2444             : 
    2445        1272 :   uint32_t SimdShiftOp(WasmOpcode opcode) {
    2446        1272 :     SimdShiftImmediate<validate> imm(this, this->pc_);
    2447        1272 :     if (this->Validate(this->pc_, opcode, imm)) {
    2448             :       auto input = Pop(0, kWasmS128);
    2449             :       auto* result = Push(kWasmS128);
    2450        1272 :       CALL_INTERFACE_IF_REACHABLE(SimdShiftOp, opcode, imm, input, result);
    2451             :     }
    2452        1272 :     return imm.length;
    2453             :   }
    2454             : 
    2455       14801 :   uint32_t Simd8x16ShuffleOp() {
    2456       14801 :     Simd8x16ShuffleImmediate<validate> imm(this, this->pc_);
    2457       14801 :     if (this->Validate(this->pc_, imm)) {
    2458             :       auto input1 = Pop(1, kWasmS128);
    2459             :       auto input0 = Pop(0, kWasmS128);
    2460             :       auto* result = Push(kWasmS128);
    2461       14800 :       CALL_INTERFACE_IF_REACHABLE(Simd8x16ShuffleOp, imm, input0, input1,
    2462             :                                   result);
    2463             :     }
    2464       14801 :     return 16;
    2465             :   }
    2466             : 
    2467       20921 :   uint32_t DecodeSimdOpcode(WasmOpcode opcode) {
    2468             :     uint32_t len = 0;
    2469       20921 :     switch (opcode) {
    2470             :       case kExprF32x4ExtractLane: {
    2471          64 :         len = SimdExtractLane(opcode, kWasmF32);
    2472          64 :         break;
    2473             :       }
    2474             :       case kExprI32x4ExtractLane:
    2475             :       case kExprI16x8ExtractLane:
    2476             :       case kExprI8x16ExtractLane: {
    2477         212 :         len = SimdExtractLane(opcode, kWasmI32);
    2478         212 :         break;
    2479             :       }
    2480             :       case kExprF32x4ReplaceLane: {
    2481          64 :         len = SimdReplaceLane(opcode, kWasmF32);
    2482          64 :         break;
    2483             :       }
    2484             :       case kExprI32x4ReplaceLane:
    2485             :       case kExprI16x8ReplaceLane:
    2486             :       case kExprI8x16ReplaceLane: {
    2487         336 :         len = SimdReplaceLane(opcode, kWasmI32);
    2488         336 :         break;
    2489             :       }
    2490             :       case kExprI32x4Shl:
    2491             :       case kExprI32x4ShrS:
    2492             :       case kExprI32x4ShrU:
    2493             :       case kExprI16x8Shl:
    2494             :       case kExprI16x8ShrS:
    2495             :       case kExprI16x8ShrU:
    2496             :       case kExprI8x16Shl:
    2497             :       case kExprI8x16ShrS:
    2498             :       case kExprI8x16ShrU: {
    2499        1272 :         len = SimdShiftOp(opcode);
    2500        1272 :         break;
    2501             :       }
    2502             :       case kExprS8x16Shuffle: {
    2503       14801 :         len = Simd8x16ShuffleOp();
    2504       14801 :         break;
    2505             :       }
    2506             :       case kExprS128LoadMem:
    2507          16 :         len = DecodeLoadMem(LoadType::kS128Load, 1);
    2508          16 :         break;
    2509             :       case kExprS128StoreMem:
    2510           8 :         len = DecodeStoreMem(StoreType::kS128Store, 1);
    2511           8 :         break;
    2512             :       default: {
    2513        4148 :         FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2514        4148 :         if (!VALIDATE(sig != nullptr)) {
    2515           0 :           this->error("invalid simd opcode");
    2516           0 :           break;
    2517             :         }
    2518             :         PopArgs(sig);
    2519             :         auto* results =
    2520        4148 :             sig->return_count() == 0 ? nullptr : Push(GetReturnType(sig));
    2521        8296 :         CALL_INTERFACE_IF_REACHABLE(SimdOp, opcode, VectorOf(args_), results);
    2522             :       }
    2523             :     }
    2524       20921 :     return len;
    2525             :   }
    2526             : 
    2527       47357 :   uint32_t DecodeAtomicOpcode(WasmOpcode opcode) {
    2528             :     uint32_t len = 0;
    2529             :     ValueType ret_type;
    2530       47357 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2531       47343 :     if (sig != nullptr) {
    2532             :       MachineType memtype;
    2533       47343 :       switch (opcode) {
    2534             : #define CASE_ATOMIC_STORE_OP(Name, Type) \
    2535             :   case kExpr##Name: {                    \
    2536             :     memtype = MachineType::Type();       \
    2537             :     ret_type = kWasmStmt;                \
    2538             :     break;                               \
    2539             :   }
    2540         357 :         ATOMIC_STORE_OP_LIST(CASE_ATOMIC_STORE_OP)
    2541             : #undef CASE_ATOMIC_OP
    2542             : #define CASE_ATOMIC_OP(Name, Type) \
    2543             :   case kExpr##Name: {              \
    2544             :     memtype = MachineType::Type(); \
    2545             :     ret_type = GetReturnType(sig); \
    2546             :     break;                         \
    2547             :   }
    2548       42619 :         ATOMIC_OP_LIST(CASE_ATOMIC_OP)
    2549             : #undef CASE_ATOMIC_OP
    2550             :         default:
    2551           0 :           this->error("invalid atomic opcode");
    2552           0 :           return 0;
    2553             :       }
    2554             :       MemoryAccessImmediate<validate> imm(
    2555       47343 :           this, this->pc_ + 1, ElementSizeLog2Of(memtype.representation()));
    2556       47366 :       len += imm.length;
    2557             :       PopArgs(sig);
    2558       47499 :       auto result = ret_type == kWasmStmt ? nullptr : Push(GetReturnType(sig));
    2559       80101 :       CALL_INTERFACE_IF_REACHABLE(AtomicOp, opcode, VectorOf(args_), imm,
    2560             :                                   result);
    2561             :     } else {
    2562           0 :       this->error("invalid atomic opcode");
    2563             :     }
    2564             :     return len;
    2565             :   }
    2566             : 
    2567         529 :   unsigned DecodeNumericOpcode(WasmOpcode opcode) {
    2568             :     unsigned len = 0;
    2569         529 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2570         529 :     if (sig != nullptr) {
    2571         529 :       switch (opcode) {
    2572             :         case kExprI32SConvertSatF32:
    2573             :         case kExprI32UConvertSatF32:
    2574             :         case kExprI32SConvertSatF64:
    2575             :         case kExprI32UConvertSatF64:
    2576             :         case kExprI64SConvertSatF32:
    2577             :         case kExprI64UConvertSatF32:
    2578             :         case kExprI64SConvertSatF64:
    2579             :         case kExprI64UConvertSatF64:
    2580          96 :           BuildSimpleOperator(opcode, sig);
    2581          96 :           break;
    2582             :         case kExprMemoryInit: {
    2583          82 :           MemoryInitImmediate<validate> imm(this, this->pc_);
    2584          82 :           if (!this->Validate(imm)) break;
    2585          81 :           len += imm.length;
    2586             :           auto size = Pop(2, sig->GetParam(2));
    2587             :           auto src = Pop(1, sig->GetParam(1));
    2588             :           auto dst = Pop(0, sig->GetParam(0));
    2589          84 :           CALL_INTERFACE_IF_REACHABLE(MemoryInit, imm, dst, src, size);
    2590             :           break;
    2591             :         }
    2592             :         case kExprDataDrop: {
    2593          42 :           DataDropImmediate<validate> imm(this, this->pc_);
    2594          42 :           if (!this->Validate(imm)) break;
    2595          41 :           len += imm.length;
    2596          42 :           CALL_INTERFACE_IF_REACHABLE(DataDrop, imm);
    2597             :           break;
    2598             :         }
    2599             :         case kExprMemoryCopy: {
    2600          66 :           MemoryCopyImmediate<validate> imm(this, this->pc_);
    2601          66 :           if (!this->Validate(imm)) break;
    2602          65 :           len += imm.length;
    2603             :           auto size = Pop(2, sig->GetParam(2));
    2604             :           auto src = Pop(1, sig->GetParam(1));
    2605             :           auto dst = Pop(0, sig->GetParam(0));
    2606          66 :           CALL_INTERFACE_IF_REACHABLE(MemoryCopy, imm, dst, src, size);
    2607             :           break;
    2608             :         }
    2609             :         case kExprMemoryFill: {
    2610          66 :           MemoryIndexImmediate<validate> imm(this, this->pc_ + 1);
    2611         132 :           if (!this->Validate(this->pc_ + 1, imm)) break;
    2612          65 :           len += imm.length;
    2613             :           auto size = Pop(2, sig->GetParam(2));
    2614             :           auto value = Pop(1, sig->GetParam(1));
    2615             :           auto dst = Pop(0, sig->GetParam(0));
    2616          66 :           CALL_INTERFACE_IF_REACHABLE(MemoryFill, imm, dst, value, size);
    2617             :           break;
    2618             :         }
    2619             :         case kExprTableInit: {
    2620          56 :           TableInitImmediate<validate> imm(this, this->pc_);
    2621          56 :           if (!this->Validate(imm)) break;
    2622          53 :           len += imm.length;
    2623             :           PopArgs(sig);
    2624          88 :           CALL_INTERFACE_IF_REACHABLE(TableInit, imm, VectorOf(args_));
    2625             :           break;
    2626             :         }
    2627             :         case kExprElemDrop: {
    2628          35 :           ElemDropImmediate<validate> imm(this, this->pc_);
    2629          35 :           if (!this->Validate(imm)) break;
    2630          33 :           len += imm.length;
    2631          34 :           CALL_INTERFACE_IF_REACHABLE(ElemDrop, imm);
    2632             :           break;
    2633             :         }
    2634             :         case kExprTableCopy: {
    2635          86 :           TableCopyImmediate<validate> imm(this, this->pc_);
    2636          86 :           if (!this->Validate(imm)) break;
    2637          85 :           len += imm.length;
    2638             :           PopArgs(sig);
    2639         142 :           CALL_INTERFACE_IF_REACHABLE(TableCopy, imm, VectorOf(args_));
    2640             :           break;
    2641             :         }
    2642             :         default:
    2643           0 :           this->error("invalid numeric opcode");
    2644           0 :           break;
    2645             :       }
    2646             :     } else {
    2647           0 :       this->error("invalid numeric opcode");
    2648             :     }
    2649         529 :     return len;
    2650             :   }
    2651             : 
    2652     1259606 :   void DoReturn() {
    2653      565674 :     size_t return_count = this->sig_->return_count();
    2654             :     DCHECK_GE(stack_.size(), return_count);
    2655             :     Vector<Value> return_values =
    2656             :         return_count == 0
    2657             :             ? Vector<Value>{}
    2658      565674 :             : Vector<Value>{&*(stack_.end() - return_count), return_count};
    2659             : 
    2660     1259606 :     CALL_INTERFACE_IF_REACHABLE(DoReturn, return_values);
    2661     1259521 :   }
    2662             : 
    2663             :   inline Value* Push(ValueType type) {
    2664             :     DCHECK_NE(kWasmStmt, type);
    2665     7382641 :     stack_.emplace_back(this->pc_, type);
    2666             :     return &stack_.back();
    2667             :   }
    2668             : 
    2669      751966 :   void PushMergeValues(Control* c, Merge<Value>* merge) {
    2670             :     DCHECK_EQ(c, &control_.back());
    2671             :     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
    2672     1503932 :     stack_.erase(stack_.begin() + c->stack_depth, stack_.end());
    2673      752026 :     if (merge->arity == 1) {
    2674       20840 :       stack_.push_back(merge->vals.first);
    2675             :     } else {
    2676      731822 :       for (uint32_t i = 0; i < merge->arity; i++) {
    2677         318 :         stack_.push_back(merge->vals.array[i]);
    2678             :       }
    2679             :     }
    2680             :     DCHECK_EQ(c->stack_depth + merge->arity, stack_.size());
    2681      752019 :   }
    2682             : 
    2683      274459 :   Value* PushReturns(FunctionSig* sig) {
    2684             :     size_t return_count = sig->return_count();
    2685      274459 :     if (return_count == 0) return nullptr;
    2686             :     size_t old_size = stack_.size();
    2687      743388 :     for (size_t i = 0; i < return_count; ++i) {
    2688             :       Push(sig->GetReturn(i));
    2689             :     }
    2690      245818 :     return stack_.data() + old_size;
    2691             :   }
    2692             : 
    2693             :   V8_INLINE Value Pop(int index, ValueType expected) {
    2694             :     auto val = Pop();
    2695     6135921 :     if (!VALIDATE(ValueTypes::IsSubType(expected, val.type) ||
    2696             :                   val.type == kWasmVar || expected == kWasmVar)) {
    2697      106872 :       this->errorf(val.pc, "%s[%d] expected type %s, found %s of type %s",
    2698             :                    SafeOpcodeNameAt(this->pc_), index,
    2699             :                    ValueTypes::TypeName(expected), SafeOpcodeNameAt(val.pc),
    2700             :                    ValueTypes::TypeName(val.type));
    2701             :     }
    2702             :     return val;
    2703             :   }
    2704             : 
    2705             :   V8_INLINE Value Pop() {
    2706             :     DCHECK(!control_.empty());
    2707     6322024 :     uint32_t limit = control_.back().stack_depth;
    2708     6322024 :     if (stack_.size() <= limit) {
    2709             :       // Popping past the current control start in reachable code.
    2710       18531 :       if (!VALIDATE(control_.back().unreachable())) {
    2711       19573 :         this->errorf(this->pc_, "%s found empty stack",
    2712             :                      SafeOpcodeNameAt(this->pc_));
    2713             :       }
    2714       17587 :       return UnreachableValue(this->pc_);
    2715             :     }
    2716     6121672 :     auto val = stack_.back();
    2717             :     stack_.pop_back();
    2718     2059229 :     return val;
    2719             :   }
    2720             : 
    2721        6931 :   int startrel(const byte* ptr) { return static_cast<int>(ptr - this->start_); }
    2722             : 
    2723         535 :   void FallThruTo(Control* c) {
    2724             :     DCHECK_EQ(c, &control_.back());
    2725         547 :     if (!TypeCheckFallThru(c)) return;
    2726         547 :     if (!c->reachable()) return;
    2727             : 
    2728         320 :     if (!c->is_loop()) CALL_INTERFACE(FallThruTo, c);
    2729         332 :     c->end_merge.reached = true;
    2730             :   }
    2731             : 
    2732      996217 :   bool TypeCheckMergeValues(Control* c, Merge<Value>* merge) {
    2733             :     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
    2734             :     DCHECK_GE(stack_.size(), c->stack_depth + merge->arity);
    2735             :     // The computation of {stack_values} is only valid if {merge->arity} is >0.
    2736             :     DCHECK_LT(0, merge->arity);
    2737      996217 :     Value* stack_values = &*(stack_.end() - merge->arity);
    2738             :     // Typecheck the topmost {merge->arity} values on the stack.
    2739     2981867 :     for (uint32_t i = 0; i < merge->arity; ++i) {
    2740      998118 :       Value& val = stack_values[i];
    2741             :       Value& old = (*merge)[i];
    2742      998118 :       if (ValueTypes::IsSubType(old.type, val.type)) continue;
    2743             :       // If {val.type} is polymorphic, which results from unreachable, make
    2744             :       // it more specific by using the merge value's expected type.
    2745             :       // If it is not polymorphic, this is a type error.
    2746       29170 :       if (!VALIDATE(val.type == kWasmVar)) {
    2747        6974 :         this->errorf(this->pc_, "type error in merge[%u] (expected %s, got %s)",
    2748        1792 :                      i, ValueTypes::TypeName(old.type),
    2749             :                      ValueTypes::TypeName(val.type));
    2750        3390 :         return false;
    2751             :       }
    2752       23988 :       val.type = old.type;
    2753             :     }
    2754             : 
    2755             :     return true;
    2756             :   }
    2757             : 
    2758     1592743 :   bool TypeCheckFallThru(Control* c) {
    2759             :     DCHECK_EQ(c, &control_.back());
    2760             :     if (!validate) return true;
    2761     1592743 :     uint32_t expected = c->end_merge.arity;
    2762             :     DCHECK_GE(stack_.size(), c->stack_depth);
    2763     1592743 :     uint32_t actual = static_cast<uint32_t>(stack_.size()) - c->stack_depth;
    2764             :     // Fallthrus must match the arity of the control exactly.
    2765     1592743 :     if (!InsertUnreachablesIfNecessary(expected, actual) || actual > expected) {
    2766        9750 :       this->errorf(
    2767             :           this->pc_,
    2768             :           "expected %u elements on the stack for fallthru to @%d, found %u",
    2769             :           expected, startrel(c->pc), actual);
    2770        4876 :       return false;
    2771             :     }
    2772     1588334 :     if (expected == 0) return true;  // Fast path.
    2773             : 
    2774      984483 :     return TypeCheckMergeValues(c, &c->end_merge);
    2775             :   }
    2776             : 
    2777      301055 :   bool TypeCheckBranch(Control* c) {
    2778             :     // Branches must have at least the number of values expected; can have more.
    2779      301055 :     uint32_t expected = c->br_merge()->arity;
    2780      301055 :     if (expected == 0) return true;  // Fast path.
    2781             :     DCHECK_GE(stack_.size(), control_.back().stack_depth);
    2782             :     uint32_t actual =
    2783       19269 :         static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth;
    2784       13983 :     if (!InsertUnreachablesIfNecessary(expected, actual)) {
    2785        4112 :       this->errorf(this->pc_,
    2786             :                    "expected %u elements on the stack for br to @%d, found %u",
    2787             :                    expected, startrel(c->pc), actual);
    2788        2056 :       return false;
    2789             :     }
    2790       11923 :     return TypeCheckMergeValues(c, c->br_merge());
    2791             :   }
    2792             : 
    2793      303473 :   bool TypeCheckReturn() {
    2794             :     // Returns must have at least the number of values expected; can have more.
    2795      303473 :     uint32_t num_returns = static_cast<uint32_t>(this->sig_->return_count());
    2796             :     DCHECK_GE(stack_.size(), control_.back().stack_depth);
    2797             :     uint32_t actual =
    2798      412015 :         static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth;
    2799      303473 :     if (!InsertUnreachablesIfNecessary(num_returns, actual)) {
    2800         802 :       this->errorf(this->pc_,
    2801             :                    "expected %u elements on the stack for return, found %u",
    2802             :                    num_returns, actual);
    2803         802 :       return false;
    2804             :     }
    2805             : 
    2806             :     // Typecheck the topmost {num_returns} values on the stack.
    2807      302673 :     if (num_returns == 0) return true;
    2808             :     // This line requires num_returns > 0.
    2809             :     Value* stack_values = &*(stack_.end() - num_returns);
    2810      214610 :     for (uint32_t i = 0; i < num_returns; ++i) {
    2811       71652 :       auto& val = stack_values[i];
    2812       71652 :       ValueType expected_type = this->sig_->GetReturn(i);
    2813       71652 :       if (ValueTypes::IsSubType(expected_type, val.type)) continue;
    2814             :       // If {val.type} is polymorphic, which results from unreachable,
    2815             :       // make it more specific by using the return's expected type.
    2816             :       // If it is not polymorphic, this is a type error.
    2817         257 :       if (!VALIDATE(val.type == kWasmVar)) {
    2818         161 :         this->errorf(this->pc_,
    2819             :                      "type error in return[%u] (expected %s, got %s)", i,
    2820             :                      ValueTypes::TypeName(expected_type),
    2821             :                      ValueTypes::TypeName(val.type));
    2822         161 :         return false;
    2823             :       }
    2824          96 :       val.type = expected_type;
    2825             :     }
    2826             :     return true;
    2827             :   }
    2828             : 
    2829     1910156 :   inline bool InsertUnreachablesIfNecessary(uint32_t expected,
    2830             :                                             uint32_t actual) {
    2831     1910156 :     if (V8_LIKELY(actual >= expected)) {
    2832             :       return true;  // enough actual values are there.
    2833             :     }
    2834       28183 :     if (!VALIDATE(control_.back().unreachable())) {
    2835             :       // There aren't enough values on the stack.
    2836             :       return false;
    2837             :     }
    2838             :     // A slow path. When the actual number of values on the stack is less
    2839             :     // than the expected number of values and the current control is
    2840             :     // unreachable, insert unreachable values below the actual values.
    2841             :     // This simplifies {TypeCheckMergeValues}.
    2842       23130 :     auto pos = stack_.begin() + (stack_.size() - actual);
    2843       65165 :     stack_.insert(pos, expected - actual, UnreachableValue(this->pc_));
    2844       23128 :     return true;
    2845             :   }
    2846             : 
    2847       66907 :   void onFirstError() override {
    2848       66907 :     this->end_ = this->pc_;  // Terminate decoding loop.
    2849             :     TRACE(" !%s\n", this->error_.message().c_str());
    2850             :     CALL_INTERFACE(OnFirstError);
    2851       66907 :   }
    2852             : 
    2853          88 :   void BuildSimplePrototypeOperator(WasmOpcode opcode) {
    2854          88 :     if (WasmOpcodes::IsSignExtensionOpcode(opcode)) {
    2855          56 :       RET_ON_PROTOTYPE_OPCODE(se);
    2856             :     }
    2857          88 :     if (WasmOpcodes::IsAnyRefOpcode(opcode)) {
    2858          32 :       RET_ON_PROTOTYPE_OPCODE(anyref);
    2859             :     }
    2860          88 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2861          88 :     BuildSimpleOperator(opcode, sig);
    2862          88 :   }
    2863             : 
    2864      100345 :   void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
    2865      100345 :     switch (sig->parameter_count()) {
    2866             :       case 1: {
    2867             :         auto val = Pop(0, sig->GetParam(0));
    2868             :         auto* ret =
    2869       57564 :             sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
    2870       57089 :         CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, val, ret);
    2871             :         break;
    2872             :       }
    2873             :       case 2: {
    2874             :         auto rval = Pop(1, sig->GetParam(1));
    2875             :         auto lval = Pop(0, sig->GetParam(0));
    2876             :         auto* ret =
    2877       42781 :             sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
    2878       41281 :         CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, lval, rval, ret);
    2879             :         break;
    2880             :       }
    2881             :       default:
    2882           0 :         UNREACHABLE();
    2883             :     }
    2884      100345 :   }
    2885             : 
    2886      495556 :   void BuildSimpleOperator(WasmOpcode opcode, ValueType return_type,
    2887             :                            ValueType arg_type) {
    2888             :     auto val = Pop(0, arg_type);
    2889      495611 :     auto* ret = return_type == kWasmStmt ? nullptr : Push(return_type);
    2890      283151 :     CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, val, ret);
    2891      495588 :   }
    2892             : 
    2893     1605717 :   void BuildSimpleOperator(WasmOpcode opcode, ValueType return_type,
    2894             :                            ValueType lhs_type, ValueType rhs_type) {
    2895             :     auto rval = Pop(1, rhs_type);
    2896             :     auto lval = Pop(0, lhs_type);
    2897     1605859 :     auto* ret = return_type == kWasmStmt ? nullptr : Push(return_type);
    2898     1461311 :     CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, lval, rval, ret);
    2899     1605720 :   }
    2900             : 
    2901             : #define DEFINE_SIMPLE_SIG_OPERATOR(sig, ...)          \
    2902             :   void BuildSimpleOperator_##sig(WasmOpcode opcode) { \
    2903             :     BuildSimpleOperator(opcode, __VA_ARGS__);         \
    2904             :   }
    2905      221712 :   FOREACH_SIGNATURE(DEFINE_SIMPLE_SIG_OPERATOR)
    2906             : #undef DEFINE_SIMPLE_SIG_OPERATOR
    2907             : };
    2908             : 
    2909             : #undef CALL_INTERFACE
    2910             : #undef CALL_INTERFACE_IF_REACHABLE
    2911             : #undef CALL_INTERFACE_IF_PARENT_REACHABLE
    2912             : 
    2913             : class EmptyInterface {
    2914             :  public:
    2915             :   static constexpr Decoder::ValidateFlag validate = Decoder::kValidate;
    2916             :   using Value = ValueBase;
    2917             :   using Control = ControlBase<Value>;
    2918             :   using FullDecoder = WasmFullDecoder<validate, EmptyInterface>;
    2919             : 
    2920             : #define DEFINE_EMPTY_CALLBACK(name, ...) \
    2921             :   void name(FullDecoder* decoder, ##__VA_ARGS__) {}
    2922             :   INTERFACE_FUNCTIONS(DEFINE_EMPTY_CALLBACK)
    2923             : #undef DEFINE_EMPTY_CALLBACK
    2924             : };
    2925             : 
    2926             : #undef TRACE
    2927             : #undef TRACE_INST_FORMAT
    2928             : #undef VALIDATE
    2929             : #undef CHECK_PROTOTYPE_OPCODE
    2930             : #undef OPCODE_ERROR
    2931             : 
    2932             : }  // namespace wasm
    2933             : }  // namespace internal
    2934             : }  // namespace v8
    2935             : 
    2936             : #endif  // V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_

Generated by: LCOV version 1.10