LCOV - code coverage report
Current view: top level - src/wasm - function-body-decoder-impl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 994 1057 94.0 %
Date: 2019-02-19 Functions: 166 204 81.4 %

          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(AtomicWake, 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    24222174 :   inline LocalIndexImmediate(Decoder* decoder, const byte* pc) {
     141    48444424 :     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        1065 :   inline ExceptionIndexImmediate(Decoder* decoder, const byte* pc) {
     152        2131 :     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    23305242 :     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      210560 :     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      675223 :   inline ImmF32Immediate(Decoder* decoder, const byte* pc) {
     179             :     // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
     180     1350446 :     uint32_t tmp = decoder->read_u32<validate>(pc + 1, "immf32");
     181      675223 :     memcpy(&value, &tmp, sizeof(value));
     182      675223 :   }
     183             : };
     184             : 
     185             : template <Decoder::ValidateFlag validate>
     186             : struct ImmF64Immediate {
     187             :   double value;
     188             :   uint32_t length = 8;
     189      246183 :   inline ImmF64Immediate(Decoder* decoder, const byte* pc) {
     190             :     // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
     191      492366 :     uint64_t tmp = decoder->read_u64<validate>(pc + 1, "immf64");
     192      246183 :     memcpy(&value, &tmp, sizeof(value));
     193      246183 :   }
     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       96585 :   inline GlobalIndexImmediate(Decoder* decoder, const byte* pc) {
     204      193170 :     index = decoder->read_u32v<validate>(pc + 1, &length, "global index");
     205       58358 :   }
     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     4900576 :   inline BlockTypeImmediate(const WasmFeatures& enabled, Decoder* decoder,
     216     4900576 :                             const byte* pc) {
     217     4900576 :     uint8_t val = decoder->read_u8<validate>(pc + 1, "block type");
     218     4900577 :     if (!decode_local_type(val, &type)) {
     219             :       // Handle multi-value blocks.
     220         276 :       if (!VALIDATE(enabled.mv)) {
     221          49 :         decoder->error(pc + 1, "invalid block type");
     222          49 :         return;
     223             :       }
     224         227 :       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     4900582 :   inline bool decode_local_type(uint8_t val, ValueType* result) {
     238     4900582 :     switch (static_cast<ValueTypeCode>(val)) {
     239             :       case kLocalVoid:
     240     4817218 :         *result = kWasmStmt;
     241             :         return true;
     242             :       case kLocalI32:
     243       35934 :         *result = kWasmI32;
     244             :         return true;
     245             :       case kLocalI64:
     246        1519 :         *result = kWasmI64;
     247             :         return true;
     248             :       case kLocalF32:
     249        2557 :         *result = kWasmF32;
     250             :         return true;
     251             :       case kLocalF64:
     252        2619 :         *result = kWasmF64;
     253             :         return true;
     254             :       case kLocalS128:
     255           8 :         *result = kWasmS128;
     256             :         return true;
     257             :       case kLocalAnyFunc:
     258           0 :         *result = kWasmAnyFunc;
     259             :         return true;
     260             :       case kLocalAnyRef:
     261          59 :         *result = kWasmAnyRef;
     262             :         return true;
     263             :       default:
     264       40668 :         *result = kWasmVar;
     265             :         return false;
     266             :     }
     267             :   }
     268             : 
     269             :   uint32_t in_arity() const {
     270      392696 :     if (type != kWasmVar) return 0;
     271         243 :     return static_cast<uint32_t>(sig->parameter_count());
     272             :   }
     273             :   uint32_t out_arity() const {
     274      454307 :     if (type == kWasmStmt) return 0;
     275       29521 :     if (type != kWasmVar) return 1;
     276         267 :     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       28651 :     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      747470 :     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       10144 :   inline CallIndirectImmediate(Decoder* decoder, const byte* pc) {
     306       10144 :     uint32_t len = 0;
     307       20288 :     sig_index = decoder->read_u32v<validate>(pc + 1, &len, "signature index");
     308       10145 :     if (!VALIDATE(decoder->ok())) return;
     309       19521 :     table_index = decoder->read_u8<validate>(pc + 1 + len, "table index");
     310        9378 :     if (!VALIDATE(table_index == 0)) {
     311         112 :       decoder->errorf(pc + 1 + len, "expected table index 0, found %u",
     312          56 :                       table_index);
     313             :     }
     314       10143 :     length = 1 + len;
     315             :   }
     316             : };
     317             : 
     318             : template <Decoder::ValidateFlag validate>
     319             : struct CallFunctionImmediate {
     320             :   uint32_t index;
     321             :   FunctionSig* sig = nullptr;
     322             :   uint32_t length;
     323      850938 :   inline CallFunctionImmediate(Decoder* decoder, const byte* pc) {
     324     1701877 :     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             :   inline MemoryIndexImmediate() = default;
     333        4455 :   inline MemoryIndexImmediate(Decoder* decoder, const byte* pc) {
     334        8910 :     index = decoder->read_u8<validate>(pc + 1, "memory index");
     335        4455 :     if (!VALIDATE(index == 0)) {
     336         256 :       decoder->errorf(pc + 1, "expected memory index 0, found %u", index);
     337             :     }
     338        4455 :   }
     339             : };
     340             : 
     341             : template <Decoder::ValidateFlag validate>
     342             : struct TableIndexImmediate {
     343             :   uint32_t index = 0;
     344             :   unsigned length = 1;
     345             :   inline TableIndexImmediate() = default;
     346          24 :   inline TableIndexImmediate(Decoder* decoder, const byte* pc) {
     347         580 :     index = decoder->read_u8<validate>(pc + 1, "table index");
     348             :   }
     349             : };
     350             : 
     351             : template <Decoder::ValidateFlag validate>
     352             : struct BranchTableImmediate {
     353             :   uint32_t table_count;
     354             :   const byte* start;
     355             :   const byte* table;
     356      243321 :   inline BranchTableImmediate(Decoder* decoder, const byte* pc) {
     357             :     DCHECK_EQ(kExprBrTable, decoder->read_u8<validate>(pc, "opcode"));
     358      243321 :     start = pc + 1;
     359      243321 :     uint32_t len = 0;
     360      243321 :     table_count = decoder->read_u32v<validate>(pc + 1, &len, "table count");
     361      243321 :     table = pc + 1 + len;
     362      243321 :   }
     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     1798906 :   bool has_next() { return VALIDATE(decoder_->ok()) && index_ <= table_count_; }
     371     1958579 :   uint32_t next() {
     372             :     DCHECK(has_next());
     373     1958579 :     index_++;
     374             :     uint32_t length;
     375             :     uint32_t result =
     376     1958579 :         decoder_->read_u32v<validate>(pc_, &length, "branch table entry");
     377     1958591 :     pc_ += length;
     378     1958591 :     return result;
     379             :   }
     380             :   // length, including the length of the {BranchTableImmediate}, but not the
     381             :   // opcode.
     382       37554 :   uint32_t length() {
     383       50215 :     while (has_next()) next();
     384       16609 :     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      253936 :         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     6784322 :   inline MemoryAccessImmediate(Decoder* decoder, const byte* pc,
     409     6784322 :                                uint32_t max_alignment) {
     410             :     uint32_t alignment_length;
     411    13568674 :     alignment =
     412             :         decoder->read_u32v<validate>(pc + 1, &alignment_length, "alignment");
     413      509950 :     if (!VALIDATE(alignment <= max_alignment)) {
     414         942 :       decoder->errorf(pc + 1,
     415             :                       "invalid alignment; expected maximum alignment is %u, "
     416             :                       "actual alignment is %u",
     417             :                       max_alignment, alignment);
     418             :     }
     419     6785288 :     if (!VALIDATE(decoder->ok())) return;
     420             :     uint32_t offset_length;
     421    13566798 :     offset = decoder->read_u32v<validate>(pc + 1 + alignment_length,
     422             :                                           &offset_length, "offset");
     423     6783396 :     length = alignment_length + offset_length;
     424             :   }
     425             : };
     426             : 
     427             : // Immediate for SIMD lane operations.
     428             : template <Decoder::ValidateFlag validate>
     429             : struct SimdLaneImmediate {
     430             :   uint8_t lane;
     431             :   uint32_t length = 1;
     432             : 
     433       18676 :   inline SimdLaneImmediate(Decoder* decoder, const byte* pc) {
     434     3209700 :     lane = decoder->read_u8<validate>(pc + 2, "lane");
     435             :   }
     436             : };
     437             : 
     438             : // Immediate for SIMD shift operations.
     439             : template <Decoder::ValidateFlag validate>
     440             : struct SimdShiftImmediate {
     441             :   uint8_t shift;
     442             :   uint32_t length = 1;
     443             : 
     444        1272 :   inline SimdShiftImmediate(Decoder* decoder, const byte* pc) {
     445       26496 :     shift = decoder->read_u8<validate>(pc + 2, "shift");
     446             :   }
     447             : };
     448             : 
     449             : // Immediate for SIMD S8x16 shuffle operations.
     450             : template <Decoder::ValidateFlag validate>
     451             : struct Simd8x16ShuffleImmediate {
     452             :   uint8_t shuffle[kSimd128Size] = {0};
     453             : 
     454       26513 :   inline Simd8x16ShuffleImmediate(Decoder* decoder, const byte* pc) {
     455      438737 :     for (uint32_t i = 0; i < kSimd128Size; ++i) {
     456      656898 :       shuffle[i] = decoder->read_u8<validate>(pc + 2 + i, "shuffle");
     457      247250 :       if (!VALIDATE(decoder->ok())) return;
     458             :     }
     459             :   }
     460             : };
     461             : 
     462             : template <Decoder::ValidateFlag validate>
     463             : struct MemoryInitImmediate {
     464             :   uint32_t data_segment_index = 0;
     465             :   MemoryIndexImmediate<validate> memory;
     466             :   unsigned length = 0;
     467             : 
     468          78 :   inline MemoryInitImmediate(Decoder* decoder, const byte* pc) {
     469          78 :     uint32_t len = 0;
     470         156 :     data_segment_index =
     471             :         decoder->read_i32v<validate>(pc + 2, &len, "data segment index");
     472          79 :     if (!VALIDATE(decoder->ok())) return;
     473          77 :     memory = MemoryIndexImmediate<validate>(decoder, pc + 1 + len);
     474          77 :     length = len + memory.length;
     475             :   }
     476             : };
     477             : 
     478             : template <Decoder::ValidateFlag validate>
     479             : struct DataDropImmediate {
     480             :   uint32_t index;
     481             :   unsigned length;
     482             : 
     483             :   inline DataDropImmediate(Decoder* decoder, const byte* pc) {
     484          84 :     index = decoder->read_i32v<validate>(pc + 2, &length, "data segment index");
     485             :   }
     486             : };
     487             : 
     488             : template <Decoder::ValidateFlag validate>
     489             : struct MemoryCopyImmediate {
     490             :   MemoryIndexImmediate<validate> memory_src;
     491             :   MemoryIndexImmediate<validate> memory_dst;
     492             :   unsigned length = 0;
     493             : 
     494          50 :   inline MemoryCopyImmediate(Decoder* decoder, const byte* pc) {
     495          50 :     memory_src = MemoryIndexImmediate<validate>(decoder, pc + 1);
     496          50 :     if (!VALIDATE(decoder->ok())) return;
     497          50 :     memory_dst =
     498          50 :         MemoryIndexImmediate<validate>(decoder, pc + 1 + memory_src.length);
     499          50 :     if (!VALIDATE(decoder->ok())) return;
     500          50 :     length = memory_src.length + memory_dst.length;
     501             :   }
     502             : };
     503             : 
     504             : template <Decoder::ValidateFlag validate>
     505             : struct TableInitImmediate {
     506             :   uint32_t elem_segment_index = 0;
     507             :   TableIndexImmediate<validate> table;
     508             :   unsigned length = 0;
     509             : 
     510          56 :   inline TableInitImmediate(Decoder* decoder, const byte* pc) {
     511          56 :     uint32_t len = 0;
     512         111 :     elem_segment_index =
     513             :         decoder->read_i32v<validate>(pc + 2, &len, "elem segment index");
     514          56 :     if (!VALIDATE(decoder->ok())) return;
     515         108 :     table = TableIndexImmediate<validate>(decoder, pc + 1 + len);
     516          54 :     length = len + table.length;
     517             :   }
     518             : };
     519             : 
     520             : template <Decoder::ValidateFlag validate>
     521             : struct ElemDropImmediate {
     522             :   uint32_t index;
     523             :   unsigned length;
     524             : 
     525             :   inline ElemDropImmediate(Decoder* decoder, const byte* pc) {
     526          70 :     index = decoder->read_i32v<validate>(pc + 2, &length, "elem segment index");
     527             :   }
     528             : };
     529             : 
     530             : template <Decoder::ValidateFlag validate>
     531             : struct TableCopyImmediate {
     532             :   TableIndexImmediate<validate> table_src;
     533             :   TableIndexImmediate<validate> table_dst;
     534             :   unsigned length = 0;
     535             : 
     536         106 :   inline TableCopyImmediate(Decoder* decoder, const byte* pc) {
     537         106 :     table_src = TableIndexImmediate<validate>(decoder, pc + 1);
     538         106 :     if (!VALIDATE(decoder->ok())) return;
     539         212 :     table_dst =
     540             :         TableIndexImmediate<validate>(decoder, pc + 1 + table_src.length);
     541         106 :     if (!VALIDATE(decoder->ok())) return;
     542         106 :     length = table_src.length + table_dst.length;
     543             :   }
     544             : };
     545             : 
     546             : // An entry on the value stack.
     547             : struct ValueBase {
     548             :   const byte* pc = nullptr;
     549             :   ValueType type = kWasmStmt;
     550             : 
     551     7668601 :   ValueBase(const byte* pc, ValueType type) : pc(pc), type(type) {}
     552             : };
     553             : 
     554             : template <typename Value>
     555             : struct Merge {
     556             :   uint32_t arity = 0;
     557             :   union {  // Either multiple values or a single value.
     558             :     Value* array;
     559             :     Value first;
     560             :   } vals = {nullptr};  // Initialize {array} with {nullptr}.
     561             : 
     562             :   // Tracks whether this merge was ever reached. Uses precise reachability, like
     563             :   // Reachability::kReachable.
     564             :   bool reached;
     565             : 
     566     1648931 :   Merge(bool reached = false) : reached(reached) {}
     567             : 
     568             :   Value& operator[](uint32_t i) {
     569             :     DCHECK_GT(arity, i);
     570     1016516 :     return arity == 1 ? vals.first : vals.array[i];
     571             :   }
     572             : };
     573             : 
     574             : enum ControlKind : uint8_t {
     575             :   kControlIf,
     576             :   kControlIfElse,
     577             :   kControlBlock,
     578             :   kControlLoop,
     579             :   kControlTry,
     580             :   kControlTryCatch
     581             : };
     582             : 
     583             : enum Reachability : uint8_t {
     584             :   // reachable code.
     585             :   kReachable,
     586             :   // reachable code in unreachable block (implies normal validation).
     587             :   kSpecOnlyReachable,
     588             :   // code unreachable in its own block (implies polymorphic validation).
     589             :   kUnreachable
     590             : };
     591             : 
     592             : // An entry on the control stack (i.e. if, block, loop, or try).
     593             : template <typename Value>
     594             : struct ControlBase {
     595             :   ControlKind kind = kControlBlock;
     596             :   uint32_t stack_depth = 0;  // stack height at the beginning of the construct.
     597             :   const uint8_t* pc = nullptr;
     598             :   Reachability reachability = kReachable;
     599             : 
     600             :   // Values merged into the start or end of this control construct.
     601             :   Merge<Value> start_merge;
     602             :   Merge<Value> end_merge;
     603             : 
     604             :   MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ControlBase);
     605             : 
     606             :   ControlBase(ControlKind kind, uint32_t stack_depth, const uint8_t* pc,
     607             :               Reachability reachability)
     608             :       : kind(kind),
     609             :         stack_depth(stack_depth),
     610             :         pc(pc),
     611             :         reachability(reachability),
     612     1648931 :         start_merge(reachability == kReachable) {}
     613             : 
     614             :   // Check whether the current block is reachable.
     615             :   bool reachable() const { return reachability == kReachable; }
     616             : 
     617             :   // Check whether the rest of the block is unreachable.
     618             :   // Note that this is different from {!reachable()}, as there is also the
     619             :   // "indirect unreachable state", for which both {reachable()} and
     620             :   // {unreachable()} return false.
     621       12929 :   bool unreachable() const { return reachability == kUnreachable; }
     622             : 
     623             :   // Return the reachability of new control structs started in this block.
     624             :   Reachability innerReachability() const {
     625      414126 :     return reachability == kReachable ? kReachable : kSpecOnlyReachable;
     626             :   }
     627             : 
     628       21275 :   bool is_if() const { return is_onearmed_if() || is_if_else(); }
     629             :   bool is_onearmed_if() const { return kind == kControlIf; }
     630             :   bool is_if_else() const { return kind == kControlIfElse; }
     631             :   bool is_block() const { return kind == kControlBlock; }
     632             :   bool is_loop() const { return kind == kControlLoop; }
     633             :   bool is_incomplete_try() const { return kind == kControlTry; }
     634             :   bool is_try_catch() const { return kind == kControlTryCatch; }
     635         532 :   bool is_try() const { return is_incomplete_try() || is_try_catch(); }
     636             : 
     637     1141887 :   inline Merge<Value>* br_merge() {
     638     1262186 :     return is_loop() ? &this->start_merge : &this->end_merge;
     639             :   }
     640             : };
     641             : 
     642             : // This is the list of callback functions that an interface for the
     643             : // WasmFullDecoder should implement.
     644             : // F(Name, args...)
     645             : #define INTERFACE_FUNCTIONS(F)                                                \
     646             :   /* General: */                                                              \
     647             :   F(StartFunction)                                                            \
     648             :   F(StartFunctionBody, Control* block)                                        \
     649             :   F(FinishFunction)                                                           \
     650             :   F(OnFirstError)                                                             \
     651             :   F(NextInstruction, WasmOpcode)                                              \
     652             :   /* Control: */                                                              \
     653             :   F(Block, Control* block)                                                    \
     654             :   F(Loop, Control* block)                                                     \
     655             :   F(Try, Control* block)                                                      \
     656             :   F(Catch, Control* block, Value* exception)                                  \
     657             :   F(If, const Value& cond, Control* if_block)                                 \
     658             :   F(FallThruTo, Control* c)                                                   \
     659             :   F(PopControl, Control* block)                                               \
     660             :   F(EndControl, Control* block)                                               \
     661             :   /* Instructions: */                                                         \
     662             :   F(UnOp, WasmOpcode opcode, const Value& value, Value* result)               \
     663             :   F(BinOp, WasmOpcode opcode, const Value& lhs, const Value& rhs,             \
     664             :     Value* result)                                                            \
     665             :   F(I32Const, Value* result, int32_t value)                                   \
     666             :   F(I64Const, Value* result, int64_t value)                                   \
     667             :   F(F32Const, Value* result, float value)                                     \
     668             :   F(F64Const, Value* result, double value)                                    \
     669             :   F(RefNull, Value* result)                                                   \
     670             :   F(Drop, const Value& value)                                                 \
     671             :   F(DoReturn, Vector<Value> values)                                           \
     672             :   F(GetLocal, Value* result, const LocalIndexImmediate<validate>& imm)        \
     673             :   F(SetLocal, const Value& value, const LocalIndexImmediate<validate>& imm)   \
     674             :   F(TeeLocal, const Value& value, Value* result,                              \
     675             :     const LocalIndexImmediate<validate>& imm)                                 \
     676             :   F(GetGlobal, Value* result, const GlobalIndexImmediate<validate>& imm)      \
     677             :   F(SetGlobal, const Value& value, const GlobalIndexImmediate<validate>& imm) \
     678             :   F(GetTable, const Value& index, Value* result,                              \
     679             :     const TableIndexImmediate<validate>& imm)                                 \
     680             :   F(SetTable, const Value& index, const Value& value,                         \
     681             :     const TableIndexImmediate<validate>& imm)                                 \
     682             :   F(Unreachable)                                                              \
     683             :   F(Select, const Value& cond, const Value& fval, const Value& tval,          \
     684             :     Value* result)                                                            \
     685             :   F(Br, Control* target)                                                      \
     686             :   F(BrIf, const Value& cond, uint32_t depth)                                  \
     687             :   F(BrTable, const BranchTableImmediate<validate>& imm, const Value& key)     \
     688             :   F(Else, Control* if_block)                                                  \
     689             :   F(LoadMem, LoadType type, const MemoryAccessImmediate<validate>& imm,       \
     690             :     const Value& index, Value* result)                                        \
     691             :   F(StoreMem, StoreType type, const MemoryAccessImmediate<validate>& imm,     \
     692             :     const Value& index, const Value& value)                                   \
     693             :   F(CurrentMemoryPages, Value* result)                                        \
     694             :   F(MemoryGrow, const Value& value, Value* result)                            \
     695             :   F(CallDirect, const CallFunctionImmediate<validate>& imm,                   \
     696             :     const Value args[], Value returns[])                                      \
     697             :   F(CallIndirect, const Value& index,                                         \
     698             :     const CallIndirectImmediate<validate>& imm, const Value args[],           \
     699             :     Value returns[])                                                          \
     700             :   F(ReturnCall, const CallFunctionImmediate<validate>& imm,                   \
     701             :     const Value args[])                                                       \
     702             :   F(ReturnCallIndirect, const Value& index,                                   \
     703             :     const CallIndirectImmediate<validate>& imm, const Value args[])           \
     704             :   F(SimdOp, WasmOpcode opcode, Vector<Value> args, Value* result)             \
     705             :   F(SimdLaneOp, WasmOpcode opcode, const SimdLaneImmediate<validate>& imm,    \
     706             :     const Vector<Value> inputs, Value* result)                                \
     707             :   F(SimdShiftOp, WasmOpcode opcode, const SimdShiftImmediate<validate>& imm,  \
     708             :     const Value& input, Value* result)                                        \
     709             :   F(Simd8x16ShuffleOp, const Simd8x16ShuffleImmediate<validate>& imm,         \
     710             :     const Value& input0, const Value& input1, Value* result)                  \
     711             :   F(Throw, const ExceptionIndexImmediate<validate>& imm,                      \
     712             :     const Vector<Value>& args)                                                \
     713             :   F(Rethrow, const Value& exception)                                          \
     714             :   F(BrOnException, const Value& exception,                                    \
     715             :     const ExceptionIndexImmediate<validate>& imm, uint32_t depth,             \
     716             :     Vector<Value> values)                                                     \
     717             :   F(AtomicOp, WasmOpcode opcode, Vector<Value> args,                          \
     718             :     const MemoryAccessImmediate<validate>& imm, Value* result)                \
     719             :   F(MemoryInit, const MemoryInitImmediate<validate>& imm, const Value& dst,   \
     720             :     const Value& src, const Value& size)                                      \
     721             :   F(DataDrop, const DataDropImmediate<validate>& imm)                         \
     722             :   F(MemoryCopy, const MemoryCopyImmediate<validate>& imm, const Value& dst,   \
     723             :     const Value& src, const Value& size)                                      \
     724             :   F(MemoryFill, const MemoryIndexImmediate<validate>& imm, const Value& dst,  \
     725             :     const Value& value, const Value& size)                                    \
     726             :   F(TableInit, const TableInitImmediate<validate>& imm, Vector<Value> args)   \
     727             :   F(ElemDrop, const ElemDropImmediate<validate>& imm)                         \
     728             :   F(TableCopy, const TableCopyImmediate<validate>& imm, Vector<Value> args)
     729             : 
     730             : // Generic Wasm bytecode decoder with utilities for decoding immediates,
     731             : // lengths, etc.
     732             : template <Decoder::ValidateFlag validate>
     733     3296829 : class WasmDecoder : public Decoder {
     734             :  public:
     735             :   WasmDecoder(const WasmModule* module, const WasmFeatures& enabled,
     736             :               WasmFeatures* detected, FunctionSig* sig, const byte* start,
     737             :               const byte* end, uint32_t buffer_offset = 0)
     738             :       : Decoder(start, end, buffer_offset),
     739             :         module_(module),
     740             :         enabled_(enabled),
     741             :         detected_(detected),
     742             :         sig_(sig),
     743     3296845 :         local_types_(nullptr) {}
     744             :   const WasmModule* module_;
     745             :   const WasmFeatures enabled_;
     746             :   WasmFeatures* detected_;
     747             :   FunctionSig* sig_;
     748             : 
     749             :   ZoneVector<ValueType>* local_types_;
     750             : 
     751             :   uint32_t total_locals() const {
     752             :     return local_types_ == nullptr
     753             :                ? 0
     754     2946428 :                : static_cast<uint32_t>(local_types_->size());
     755             :   }
     756             : 
     757     1673004 :   static bool DecodeLocals(const WasmFeatures& enabled, Decoder* decoder,
     758             :                            const FunctionSig* sig,
     759             :                            ZoneVector<ValueType>* type_list) {
     760             :     DCHECK_NOT_NULL(type_list);
     761             :     DCHECK_EQ(0, type_list->size());
     762             :     // Initialize from signature.
     763     1623435 :     if (sig != nullptr) {
     764     1305976 :       type_list->assign(sig->parameters().begin(), sig->parameters().end());
     765             :     }
     766             :     // Decode local declarations, if any.
     767             :     uint32_t entries = decoder->consume_u32v("local decls count");
     768     1623590 :     if (decoder->failed()) return false;
     769             : 
     770             :     TRACE("local decls count: %u\n", entries);
     771     1771986 :     while (entries-- > 0 && VALIDATE(decoder->ok()) && decoder->more()) {
     772             :       uint32_t count = decoder->consume_u32v("local count");
     773       49567 :       if (decoder->failed()) return false;
     774             : 
     775             :       DCHECK_LE(type_list->size(), kV8MaxWasmFunctionLocals);
     776       98972 :       if (count > kV8MaxWasmFunctionLocals - type_list->size()) {
     777          43 :         decoder->error(decoder->pc() - 1, "local count too large");
     778          43 :         return false;
     779             :       }
     780             :       byte code = decoder->consume_u8("local type");
     781       49443 :       if (decoder->failed()) return false;
     782             : 
     783             :       ValueType type;
     784       49443 :       switch (code) {
     785             :         case kLocalI32:
     786       23483 :           type = kWasmI32;
     787       23483 :           break;
     788             :         case kLocalI64:
     789       18973 :           type = kWasmI64;
     790       18973 :           break;
     791             :         case kLocalF32:
     792        1337 :           type = kWasmF32;
     793        1337 :           break;
     794             :         case kLocalF64:
     795        2172 :           type = kWasmF64;
     796        2172 :           break;
     797             :         case kLocalAnyRef:
     798          34 :           if (enabled.anyref) {
     799          34 :             type = kWasmAnyRef;
     800          34 :             break;
     801             :           }
     802           0 :           decoder->error(decoder->pc() - 1, "invalid local type");
     803           0 :           return false;
     804             :         case kLocalAnyFunc:
     805          64 :           if (enabled.anyref) {
     806          64 :             type = kWasmAnyFunc;
     807          64 :             break;
     808             :           }
     809           0 :           decoder->error(decoder->pc() - 1,
     810             :                          "local type 'anyfunc' is not enabled with "
     811           0 :                          "--experimental-wasm-anyref");
     812           0 :           return false;
     813             :         case kLocalExceptRef:
     814         129 :           if (enabled.eh) {
     815         129 :             type = kWasmExceptRef;
     816         129 :             break;
     817             :           }
     818           0 :           decoder->error(decoder->pc() - 1, "invalid local type");
     819           0 :           return false;
     820             :         case kLocalS128:
     821        3220 :           if (enabled.simd) {
     822        3212 :             type = kWasmS128;
     823        3212 :             break;
     824             :           }
     825             :           V8_FALLTHROUGH;
     826             :         default:
     827          39 :           decoder->error(decoder->pc() - 1, "invalid local type");
     828          38 :           return false;
     829             :       }
     830       49404 :       type_list->insert(type_list->end(), count, type);
     831             :     }
     832             :     DCHECK(decoder->ok());
     833             :     return true;
     834             :   }
     835             : 
     836     1602417 :   static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc,
     837             :                                           uint32_t locals_count, Zone* zone) {
     838        9168 :     if (pc >= decoder->end()) return nullptr;
     839        9167 :     if (*pc != kExprLoop) return nullptr;
     840             : 
     841             :     // The number of locals_count is augmented by 2 so that 'locals_count - 2'
     842             :     // can be used to track mem_size, and 'locals_count - 1' to track mem_start.
     843      121862 :     BitVector* assigned = new (zone) BitVector(locals_count, zone);
     844             :     int depth = 0;
     845             :     // Iteratively process all AST nodes nested inside the loop.
     846     3195648 :     while (pc < decoder->end() && VALIDATE(decoder->ok())) {
     847     1593242 :       WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
     848             :       uint32_t length = 1;
     849     1593242 :       switch (opcode) {
     850             :         case kExprLoop:
     851             :         case kExprIf:
     852             :         case kExprBlock:
     853             :         case kExprTry:
     854       83963 :           length = OpcodeLength(decoder, pc);
     855       83963 :           depth++;
     856       83963 :           break;
     857             :         case kExprSetLocal:  // fallthru
     858             :         case kExprTeeLocal: {
     859             :           LocalIndexImmediate<validate> imm(decoder, pc);
     860      112695 :           if (assigned->length() > 0 &&
     861             :               imm.index < static_cast<uint32_t>(assigned->length())) {
     862             :             // Unverified code might have an out-of-bounds index.
     863      112694 :             assigned->Add(imm.index);
     864             :           }
     865      112695 :           length = 1 + imm.length;
     866             :           break;
     867             :         }
     868             :         case kExprMemoryGrow:
     869             :         case kExprCallFunction:
     870             :         case kExprCallIndirect:
     871             :         case kExprReturnCall:
     872             :         case kExprReturnCallIndirect:
     873             :           // Add instance cache nodes to the assigned set.
     874             :           // TODO(titzer): make this more clear.
     875       18210 :           assigned->Add(locals_count - 1);
     876       18210 :           length = OpcodeLength(decoder, pc);
     877       18210 :           break;
     878             :         case kExprEnd:
     879       83951 :           depth--;
     880       83951 :           break;
     881             :         default:
     882     1294423 :           length = OpcodeLength(decoder, pc);
     883     1294433 :           break;
     884             :       }
     885     1593252 :       if (depth <= 0) break;
     886     1584092 :       pc += length;
     887             :     }
     888        9167 :     return VALIDATE(decoder->ok()) ? assigned : nullptr;
     889             :   }
     890             : 
     891     2910150 :   inline bool Validate(const byte* pc, LocalIndexImmediate<validate>& imm) {
     892     2910150 :     if (!VALIDATE(imm.index < total_locals())) {
     893         523 :       errorf(pc + 1, "invalid local index: %u", imm.index);
     894         522 :       return false;
     895             :     }
     896     2909067 :     imm.type = local_types_ ? local_types_->at(imm.index) : kWasmStmt;
     897     1454552 :     return true;
     898             :   }
     899             : 
     900             :   inline bool Complete(const byte* pc, ExceptionIndexImmediate<validate>& imm) {
     901        3080 :     if (!VALIDATE(module_ != nullptr &&
     902             :                   imm.index < module_->exceptions.size())) {
     903             :       return false;
     904             :     }
     905        2076 :     imm.exception = &module_->exceptions[imm.index];
     906             :     return true;
     907             :   }
     908             : 
     909        1027 :   inline bool Validate(const byte* pc, ExceptionIndexImmediate<validate>& imm) {
     910        1027 :     if (!Complete(pc, imm)) {
     911           1 :       errorf(pc + 1, "Invalid exception index: %u", imm.index);
     912           1 :       return false;
     913             :     }
     914             :     return true;
     915             :   }
     916             : 
     917       54512 :   inline bool Validate(const byte* pc, GlobalIndexImmediate<validate>& imm) {
     918      163509 :     if (!VALIDATE(module_ != nullptr && imm.index < module_->globals.size())) {
     919          24 :       errorf(pc + 1, "invalid global index: %u", imm.index);
     920          24 :       return false;
     921             :     }
     922      108976 :     imm.global = &module_->globals[imm.index];
     923       54488 :     imm.type = imm.global->type;
     924       54488 :     return true;
     925             :   }
     926             : 
     927          51 :   inline bool CanTailCall(FunctionSig* tgt_sig) {
     928          17 :     if (tgt_sig == nullptr) return false;
     929          34 :     size_t num_returns = sig_->return_count();
     930          17 :     if (num_returns != tgt_sig->return_count()) return false;
     931          13 :     for (size_t i = 0; i < num_returns; ++i) {
     932          17 :       if (sig_->GetReturn(i) != tgt_sig->GetReturn(i)) return false;
     933             :     }
     934             :     return true;
     935             :   }
     936             : 
     937             :   inline bool Complete(const byte* pc, CallFunctionImmediate<validate>& imm) {
     938      797037 :     if (!VALIDATE(module_ != nullptr &&
     939             :                   imm.index < module_->functions.size())) {
     940             :       return false;
     941             :     }
     942      536024 :     imm.sig = module_->functions[imm.index].sig;
     943             :     return true;
     944             :   }
     945             : 
     946      265702 :   inline bool Validate(const byte* pc, CallFunctionImmediate<validate>& imm) {
     947      265702 :     if (Complete(pc, imm)) {
     948             :       return true;
     949             :     }
     950          72 :     errorf(pc + 1, "invalid function index: %u", imm.index);
     951          72 :     return false;
     952             :   }
     953             : 
     954             :   inline bool Complete(const byte* pc, CallIndirectImmediate<validate>& imm) {
     955       24944 :     if (!VALIDATE(module_ != nullptr &&
     956             :                   imm.sig_index < module_->signatures.size())) {
     957             :       return false;
     958             :     }
     959       17012 :     imm.sig = module_->signatures[imm.sig_index];
     960             :     return true;
     961             :   }
     962             : 
     963        8369 :   inline bool Validate(const byte* pc, CallIndirectImmediate<validate>& imm) {
     964       16737 :     if (!VALIDATE(module_ != nullptr && !module_->tables.empty())) {
     965          30 :       error("function table has to exist to execute call_indirect");
     966          30 :       return false;
     967             :     }
     968        8339 :     if (!Complete(pc, imm)) {
     969          73 :       errorf(pc + 1, "invalid signature index: #%u", imm.sig_index);
     970          73 :       return false;
     971             :     }
     972             :     return true;
     973             :   }
     974             : 
     975             :   inline bool Validate(const byte* pc, BranchDepthImmediate<validate>& imm,
     976             :                        size_t control_depth) {
     977      270494 :     if (!VALIDATE(imm.depth < control_depth)) {
     978         630 :       errorf(pc + 1, "invalid branch depth: %u", imm.depth);
     979             :       return false;
     980             :     }
     981             :     return true;
     982             :   }
     983             : 
     984       12758 :   bool Validate(const byte* pc, BranchTableImmediate<validate>& imm,
     985             :                 size_t block_depth) {
     986       12758 :     if (!VALIDATE(imm.table_count < kV8MaxWasmFunctionSize)) {
     987          16 :       errorf(pc + 1, "invalid table count (> max function size): %u",
     988             :              imm.table_count);
     989             :       return false;
     990             :     }
     991       12742 :     return checkAvailable(imm.table_count);
     992             :   }
     993             : 
     994       18676 :   inline bool Validate(const byte* pc, WasmOpcode opcode,
     995             :                        SimdLaneImmediate<validate>& imm) {
     996             :     uint8_t num_lanes = 0;
     997       18676 :     switch (opcode) {
     998             :       case kExprF32x4ExtractLane:
     999             :       case kExprF32x4ReplaceLane:
    1000             :       case kExprI32x4ExtractLane:
    1001             :       case kExprI32x4ReplaceLane:
    1002             :         num_lanes = 4;
    1003             :         break;
    1004             :       case kExprI16x8ExtractLane:
    1005             :       case kExprI16x8ReplaceLane:
    1006             :         num_lanes = 8;
    1007             :         break;
    1008             :       case kExprI8x16ExtractLane:
    1009             :       case kExprI8x16ReplaceLane:
    1010             :         num_lanes = 16;
    1011             :         break;
    1012             :       default:
    1013           0 :         UNREACHABLE();
    1014             :         break;
    1015             :     }
    1016       18676 :     if (!VALIDATE(imm.lane >= 0 && imm.lane < num_lanes)) {
    1017           0 :       error(pc_ + 2, "invalid lane index");
    1018             :       return false;
    1019             :     } else {
    1020             :       return true;
    1021             :     }
    1022             :   }
    1023             : 
    1024        1272 :   inline bool Validate(const byte* pc, WasmOpcode opcode,
    1025             :                        SimdShiftImmediate<validate>& imm) {
    1026             :     uint8_t max_shift = 0;
    1027        1272 :     switch (opcode) {
    1028             :       case kExprI32x4Shl:
    1029             :       case kExprI32x4ShrS:
    1030             :       case kExprI32x4ShrU:
    1031             :         max_shift = 32;
    1032             :         break;
    1033             :       case kExprI16x8Shl:
    1034             :       case kExprI16x8ShrS:
    1035             :       case kExprI16x8ShrU:
    1036             :         max_shift = 16;
    1037             :         break;
    1038             :       case kExprI8x16Shl:
    1039             :       case kExprI8x16ShrS:
    1040             :       case kExprI8x16ShrU:
    1041             :         max_shift = 8;
    1042             :         break;
    1043             :       default:
    1044           0 :         UNREACHABLE();
    1045             :         break;
    1046             :     }
    1047        1272 :     if (!VALIDATE(imm.shift >= 0 && imm.shift < max_shift)) {
    1048           0 :       error(pc_ + 2, "invalid shift amount");
    1049             :       return false;
    1050             :     } else {
    1051             :       return true;
    1052             :     }
    1053             :   }
    1054             : 
    1055       14545 :   inline bool Validate(const byte* pc,
    1056             :                        Simd8x16ShuffleImmediate<validate>& imm) {
    1057       14545 :     uint8_t max_lane = 0;
    1058      232720 :     for (uint32_t i = 0; i < kSimd128Size; ++i) {
    1059      465440 :       max_lane = std::max(max_lane, imm.shuffle[i]);
    1060             :     }
    1061             :     // Shuffle indices must be in [0..31] for a 16 lane shuffle.
    1062       14545 :     if (!VALIDATE(max_lane <= 2 * kSimd128Size)) {
    1063           0 :       error(pc_ + 2, "invalid shuffle mask");
    1064             :       return false;
    1065             :     }
    1066             :     return true;
    1067             :   }
    1068             : 
    1069      392693 :   inline bool Complete(BlockTypeImmediate<validate>& imm) {
    1070      392693 :     if (imm.type != kWasmVar) return true;
    1071         746 :     if (!VALIDATE((module_ && imm.sig_index < module_->signatures.size()))) {
    1072             :       return false;
    1073             :     }
    1074         486 :     imm.sig = module_->signatures[imm.sig_index];
    1075             :     return true;
    1076             :   }
    1077             : 
    1078      392694 :   inline bool Validate(BlockTypeImmediate<validate>& imm) {
    1079      392694 :     if (!Complete(imm)) {
    1080          34 :       errorf(pc_, "block type index %u out of bounds (%zu signatures)",
    1081           0 :              imm.sig_index, module_ ? module_->signatures.size() : 0);
    1082          17 :       return false;
    1083             :     }
    1084             :     return true;
    1085             :   }
    1086             : 
    1087         226 :   inline bool Validate(const byte* pc, MemoryIndexImmediate<validate>& imm) {
    1088         226 :     if (!VALIDATE(module_ != nullptr && module_->has_memory)) {
    1089           2 :       errorf(pc + 1, "memory instruction with no memory");
    1090             :       return false;
    1091             :     }
    1092             :     return true;
    1093             :   }
    1094             : 
    1095          78 :   inline bool Validate(MemoryInitImmediate<validate>& imm) {
    1096          78 :     if (!VALIDATE(module_ != nullptr &&
    1097             :                   imm.data_segment_index <
    1098             :                       module_->num_declared_data_segments)) {
    1099           1 :       errorf(pc_ + 2, "invalid data segment index: %u", imm.data_segment_index);
    1100           1 :       return false;
    1101             :     }
    1102          77 :     if (!Validate(pc_ + imm.length - imm.memory.length - 1, imm.memory))
    1103             :       return false;
    1104          77 :     return true;
    1105             :   }
    1106             : 
    1107          42 :   inline bool Validate(DataDropImmediate<validate>& imm) {
    1108          42 :     if (!VALIDATE(module_ != nullptr &&
    1109             :                   imm.index < module_->num_declared_data_segments)) {
    1110           1 :       errorf(pc_ + 2, "invalid data segment index: %u", imm.index);
    1111             :       return false;
    1112             :     }
    1113             :     return true;
    1114             :   }
    1115             : 
    1116          50 :   inline bool Validate(MemoryCopyImmediate<validate>& imm) {
    1117          50 :     if (!Validate(pc_ + 1, imm.memory_src)) return false;
    1118          49 :     if (!Validate(pc_ + 2, imm.memory_dst)) return false;
    1119             :     return true;
    1120             :   }
    1121             : 
    1122         288 :   inline bool Validate(const byte* pc, TableIndexImmediate<validate>& imm) {
    1123         575 :     if (!VALIDATE(module_ != nullptr && imm.index < module_->tables.size())) {
    1124           5 :       errorf(pc, "invalid table index: %u", imm.index);
    1125           5 :       return false;
    1126             :     }
    1127             :     return true;
    1128             :   }
    1129             : 
    1130          56 :   inline bool Validate(TableInitImmediate<validate>& imm) {
    1131         111 :     if (!VALIDATE(module_ != nullptr &&
    1132             :                   imm.elem_segment_index < module_->elem_segments.size())) {
    1133           3 :       errorf(pc_ + 2, "invalid element segment index: %u",
    1134             :              imm.elem_segment_index);
    1135           3 :       return false;
    1136             :     }
    1137          53 :     if (!Validate(pc_ + imm.length - imm.table.length - 1, imm.table))
    1138             :       return false;
    1139          53 :     return true;
    1140             :   }
    1141             : 
    1142          35 :   inline bool Validate(ElemDropImmediate<validate>& imm) {
    1143          69 :     if (!VALIDATE(module_ != nullptr &&
    1144             :                   imm.index < module_->elem_segments.size())) {
    1145           2 :       errorf(pc_ + 2, "invalid element segment index: %u", imm.index);
    1146           2 :       return false;
    1147             :     }
    1148             :     return true;
    1149             :   }
    1150             : 
    1151         106 :   inline bool Validate(TableCopyImmediate<validate>& imm) {
    1152         106 :     if (!Validate(pc_ + 1, imm.table_src)) return false;
    1153         105 :     if (!Validate(pc_ + 2, imm.table_dst)) return false;
    1154         105 :     return true;
    1155             :   }
    1156             : 
    1157     3469705 :   static uint32_t OpcodeLength(Decoder* decoder, const byte* pc) {
    1158     3469705 :     WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
    1159     3469705 :     switch (opcode) {
    1160             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1161             :       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1162             :       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1163             : #undef DECLARE_OPCODE_CASE
    1164             :       {
    1165      143250 :         MemoryAccessImmediate<validate> imm(decoder, pc, UINT32_MAX);
    1166      143250 :         return 1 + imm.length;
    1167             :       }
    1168             :       case kExprBr:
    1169             :       case kExprBrIf: {
    1170             :         BranchDepthImmediate<validate> imm(decoder, pc);
    1171       55695 :         return 1 + imm.length;
    1172             :       }
    1173             :       case kExprGetGlobal:
    1174             :       case kExprSetGlobal: {
    1175        3477 :         GlobalIndexImmediate<validate> imm(decoder, pc);
    1176       22476 :         return 1 + imm.length;
    1177             :       }
    1178             :       case kExprGetTable:
    1179             :       case kExprSetTable: {
    1180             :         TableIndexImmediate<validate> imm(decoder, pc);
    1181             :         return 1 + imm.length;
    1182             :       }
    1183             :       case kExprCallFunction:
    1184             :       case kExprReturnCall: {
    1185             :         CallFunctionImmediate<validate> imm(decoder, pc);
    1186       19565 :         return 1 + imm.length;
    1187             :       }
    1188             :       case kExprCallIndirect:
    1189             :       case kExprReturnCallIndirect: {
    1190        1255 :         CallIndirectImmediate<validate> imm(decoder, pc);
    1191        1255 :         return 1 + imm.length;
    1192             :       }
    1193             : 
    1194             :       case kExprTry:
    1195             :       case kExprIf:  // fall through
    1196             :       case kExprLoop:
    1197             :       case kExprBlock: {
    1198      114987 :         BlockTypeImmediate<validate> imm(kAllWasmFeatures, decoder, pc);
    1199      114985 :         return 1 + imm.length;
    1200             :       }
    1201             : 
    1202             :       case kExprThrow: {
    1203             :         ExceptionIndexImmediate<validate> imm(decoder, pc);
    1204          13 :         return 1 + imm.length;
    1205             :       }
    1206             : 
    1207             :       case kExprBrOnExn: {
    1208             :         BranchDepthImmediate<validate> imm_br(decoder, pc);
    1209           8 :         if (!VALIDATE(decoder->ok())) return 1 + imm_br.length;
    1210           1 :         ExceptionIndexImmediate<validate> imm_idx(decoder, pc + imm_br.length);
    1211           1 :         return 1 + imm_br.length + imm_idx.length;
    1212             :       }
    1213             : 
    1214             :       case kExprSetLocal:
    1215             :       case kExprTeeLocal:
    1216             :       case kExprGetLocal: {
    1217             :         LocalIndexImmediate<validate> imm(decoder, pc);
    1218      494154 :         return 1 + imm.length;
    1219             :       }
    1220             :       case kExprBrTable: {
    1221        4294 :         BranchTableImmediate<validate> imm(decoder, pc);
    1222             :         BranchTableIterator<validate> iterator(decoder, imm);
    1223        4294 :         return 1 + iterator.length();
    1224             :       }
    1225             :       case kExprI32Const: {
    1226             :         ImmI32Immediate<validate> imm(decoder, pc);
    1227     1168635 :         return 1 + imm.length;
    1228             :       }
    1229             :       case kExprI64Const: {
    1230             :         ImmI64Immediate<validate> imm(decoder, pc);
    1231        2716 :         return 1 + imm.length;
    1232             :       }
    1233             :       case kExprRefNull: {
    1234             :         return 1;
    1235             :       }
    1236             :       case kExprMemoryGrow:
    1237             :       case kExprMemorySize: {
    1238          64 :         MemoryIndexImmediate<validate> imm(decoder, pc);
    1239          64 :         return 1 + imm.length;
    1240             :       }
    1241             :       case kExprF32Const:
    1242         525 :         return 5;
    1243             :       case kExprF64Const:
    1244        3661 :         return 9;
    1245             :       case kNumericPrefix: {
    1246             :         byte numeric_index =
    1247       24394 :             decoder->read_u8<validate>(pc + 1, "numeric_index");
    1248           0 :         if (!VALIDATE(decoder->ok())) return 2;
    1249             :         WasmOpcode opcode =
    1250          32 :             static_cast<WasmOpcode>(kNumericPrefix << 8 | numeric_index);
    1251          32 :         switch (opcode) {
    1252             :           case kExprI32SConvertSatF32:
    1253             :           case kExprI32UConvertSatF32:
    1254             :           case kExprI32SConvertSatF64:
    1255             :           case kExprI32UConvertSatF64:
    1256             :           case kExprI64SConvertSatF32:
    1257             :           case kExprI64UConvertSatF32:
    1258             :           case kExprI64SConvertSatF64:
    1259             :           case kExprI64UConvertSatF64:
    1260             :             return 2;
    1261             :           case kExprMemoryInit: {
    1262           0 :             MemoryInitImmediate<validate> imm(decoder, pc);
    1263           0 :             return 2 + imm.length;
    1264             :           }
    1265             :           case kExprDataDrop: {
    1266             :             DataDropImmediate<validate> imm(decoder, pc);
    1267           0 :             return 2 + imm.length;
    1268             :           }
    1269             :           case kExprMemoryCopy: {
    1270           0 :             MemoryCopyImmediate<validate> imm(decoder, pc);
    1271           0 :             return 2 + imm.length;
    1272             :           }
    1273             :           case kExprMemoryFill: {
    1274           0 :             MemoryIndexImmediate<validate> imm(decoder, pc + 1);
    1275           0 :             return 2 + imm.length;
    1276             :           }
    1277             :           case kExprTableInit: {
    1278           0 :             TableInitImmediate<validate> imm(decoder, pc);
    1279           0 :             return 2 + imm.length;
    1280             :           }
    1281             :           case kExprElemDrop: {
    1282             :             ElemDropImmediate<validate> imm(decoder, pc);
    1283           0 :             return 2 + imm.length;
    1284             :           }
    1285             :           case kExprTableCopy: {
    1286           0 :             TableCopyImmediate<validate> imm(decoder, pc);
    1287           0 :             return 2 + imm.length;
    1288             :           }
    1289             :           default:
    1290           0 :             decoder->error(pc, "invalid numeric opcode");
    1291           0 :             return 2;
    1292             :         }
    1293             :       }
    1294             :       case kSimdPrefix: {
    1295          32 :         byte simd_index = decoder->read_u8<validate>(pc + 1, "simd_index");
    1296          32 :         if (!VALIDATE(decoder->ok())) return 2;
    1297             :         WasmOpcode opcode =
    1298       23978 :             static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
    1299       23978 :         switch (opcode) {
    1300             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1301             :           FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
    1302             : #undef DECLARE_OPCODE_CASE
    1303             :           return 2;
    1304             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1305             :           FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
    1306             : #undef DECLARE_OPCODE_CASE
    1307        9881 :           return 3;
    1308             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1309             :           FOREACH_SIMD_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1310             : #undef DECLARE_OPCODE_CASE
    1311             :           {
    1312           0 :             MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
    1313           0 :             return 2 + imm.length;
    1314             :           }
    1315             :           // Shuffles require a byte per lane, or 16 immediate bytes.
    1316             :           case kExprS8x16Shuffle:
    1317       11969 :             return 2 + kSimd128Size;
    1318             :           default:
    1319           1 :             decoder->error(pc, "invalid SIMD opcode");
    1320           1 :             return 2;
    1321             :         }
    1322             :       }
    1323             :       case kAtomicPrefix: {
    1324          78 :         byte atomic_index = decoder->read_u8<validate>(pc + 1, "atomic_index");
    1325          78 :         if (!VALIDATE(decoder->ok())) return 2;
    1326             :         WasmOpcode opcode =
    1327         494 :             static_cast<WasmOpcode>(kAtomicPrefix << 8 | atomic_index);
    1328         494 :         switch (opcode) {
    1329             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1330             :           FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE)
    1331             : #undef DECLARE_OPCODE_CASE
    1332             :           {
    1333         494 :             MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
    1334         494 :             return 2 + imm.length;
    1335             :           }
    1336             :           default:
    1337           0 :             decoder->error(pc, "invalid Atomics opcode");
    1338           0 :             return 2;
    1339             :         }
    1340             :       }
    1341             :       default:
    1342             :         return 1;
    1343             :     }
    1344             :   }
    1345             : 
    1346     2042940 :   std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) {
    1347     2040308 :     WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
    1348             :     // Handle "simple" opcodes with a fixed signature first.
    1349     2402774 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    1350     2040308 :     if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode);
    1351     2400350 :     if (sig) return {sig->parameter_count(), sig->return_count()};
    1352             : 
    1353             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1354             :     // clang-format off
    1355     1680266 :     switch (opcode) {
    1356             :       case kExprSelect:
    1357          20 :         return {3, 1};
    1358             :       case kExprSetTable:
    1359             :       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1360       74496 :         return {2, 0};
    1361             :       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1362             :       case kExprGetTable:
    1363             :       case kExprTeeLocal:
    1364             :       case kExprMemoryGrow:
    1365       68533 :         return {1, 1};
    1366             :       case kExprSetLocal:
    1367             :       case kExprSetGlobal:
    1368             :       case kExprDrop:
    1369             :       case kExprBrIf:
    1370             :       case kExprBrTable:
    1371             :       case kExprIf:
    1372             :       case kExprRethrow:
    1373       84210 :         return {1, 0};
    1374             :       case kExprGetLocal:
    1375             :       case kExprGetGlobal:
    1376             :       case kExprI32Const:
    1377             :       case kExprI64Const:
    1378             :       case kExprF32Const:
    1379             :       case kExprF64Const:
    1380             :       case kExprRefNull:
    1381             :       case kExprMemorySize:
    1382     1010018 :         return {0, 1};
    1383             :       case kExprCallFunction: {
    1384             :         CallFunctionImmediate<validate> imm(this, pc);
    1385             :         CHECK(Complete(pc, imm));
    1386        4760 :         return {imm.sig->parameter_count(), imm.sig->return_count()};
    1387             :       }
    1388             :       case kExprCallIndirect: {
    1389         240 :         CallIndirectImmediate<validate> imm(this, pc);
    1390         240 :         CHECK(Complete(pc, imm));
    1391             :         // Indirect calls pop an additional argument for the table index.
    1392             :         return {imm.sig->parameter_count() + 1,
    1393         480 :                 imm.sig->return_count()};
    1394             :       }
    1395             :       case kExprThrow: {
    1396             :         ExceptionIndexImmediate<validate> imm(this, pc);
    1397             :         CHECK(Complete(pc, imm));
    1398             :         DCHECK_EQ(0, imm.exception->sig->return_count());
    1399          24 :         return {imm.exception->sig->parameter_count(), 0};
    1400             :       }
    1401             :       case kExprBr:
    1402             :       case kExprBlock:
    1403             :       case kExprLoop:
    1404             :       case kExprEnd:
    1405             :       case kExprElse:
    1406             :       case kExprTry:
    1407             :       case kExprCatch:
    1408             :       case kExprBrOnExn:
    1409             :       case kExprNop:
    1410             :       case kExprReturn:
    1411             :       case kExprReturnCall:
    1412             :       case kExprReturnCallIndirect:
    1413             :       case kExprUnreachable:
    1414      416101 :         return {0, 0};
    1415             :       case kNumericPrefix:
    1416             :       case kAtomicPrefix:
    1417             :       case kSimdPrefix: {
    1418       24256 :         opcode = static_cast<WasmOpcode>(opcode << 8 | *(pc + 1));
    1419       24256 :         switch (opcode) {
    1420             :           FOREACH_SIMD_1_OPERAND_1_PARAM_OPCODE(DECLARE_OPCODE_CASE)
    1421        9680 :             return {1, 1};
    1422             :           FOREACH_SIMD_1_OPERAND_2_PARAM_OPCODE(DECLARE_OPCODE_CASE)
    1423             :           FOREACH_SIMD_MASK_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
    1424       12152 :             return {2, 1};
    1425             :           default: {
    1426        2424 :             sig = WasmOpcodes::Signature(opcode);
    1427        2424 :             if (sig) {
    1428        2424 :               return {sig->parameter_count(), sig->return_count()};
    1429             :             }
    1430             :           }
    1431             :         }
    1432             :         V8_FALLTHROUGH;
    1433             :       }
    1434             :       default:
    1435           0 :         V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x (%s)", opcode,
    1436           0 :                  WasmOpcodes::OpcodeName(opcode));
    1437             :         return {0, 0};
    1438             :     }
    1439             : #undef DECLARE_OPCODE_CASE
    1440             :     // clang-format on
    1441             :   }
    1442             : };
    1443             : 
    1444             : #define CALL_INTERFACE(name, ...) interface_.name(this, ##__VA_ARGS__)
    1445             : #define CALL_INTERFACE_IF_REACHABLE(name, ...)                 \
    1446             :   do {                                                         \
    1447             :     DCHECK(!control_.empty());                                 \
    1448             :     if (VALIDATE(this->ok()) && control_.back().reachable()) { \
    1449             :       interface_.name(this, ##__VA_ARGS__);                    \
    1450             :     }                                                          \
    1451             :   } while (false)
    1452             : #define CALL_INTERFACE_IF_PARENT_REACHABLE(name, ...)           \
    1453             :   do {                                                          \
    1454             :     DCHECK(!control_.empty());                                  \
    1455             :     if (VALIDATE(this->ok()) &&                                 \
    1456             :         (control_.size() == 1 || control_at(1)->reachable())) { \
    1457             :       interface_.name(this, ##__VA_ARGS__);                     \
    1458             :     }                                                           \
    1459             :   } while (false)
    1460             : 
    1461             : template <Decoder::ValidateFlag validate, typename Interface>
    1462     2444294 : class WasmFullDecoder : public WasmDecoder<validate> {
    1463             :   using Value = typename Interface::Value;
    1464             :   using Control = typename Interface::Control;
    1465             :   using MergeValues = Merge<Value>;
    1466             : 
    1467             :   // All Value types should be trivially copyable for performance. We push, pop,
    1468             :   // and store them in local variables.
    1469             :   ASSERT_TRIVIALLY_COPYABLE(Value);
    1470             : 
    1471             :  public:
    1472             :   template <typename... InterfaceArgs>
    1473     1256537 :   WasmFullDecoder(Zone* zone, const WasmModule* module,
    1474             :                   const WasmFeatures& enabled, WasmFeatures* detected,
    1475             :                   const FunctionBody& body, InterfaceArgs&&... interface_args)
    1476             :       : WasmDecoder<validate>(module, enabled, detected, body.sig, body.start,
    1477             :                               body.end, body.offset),
    1478             :         zone_(zone),
    1479             :         interface_(std::forward<InterfaceArgs>(interface_args)...),
    1480             :         local_type_vec_(zone),
    1481             :         stack_(zone),
    1482             :         control_(zone),
    1483     3701432 :         args_(zone) {
    1484     1256525 :     this->local_types_ = &local_type_vec_;
    1485     1256525 :   }
    1486             : 
    1487             :   Interface& interface() { return interface_; }
    1488             : 
    1489     1256520 :   bool Decode() {
    1490             :     DCHECK(stack_.empty());
    1491             :     DCHECK(control_.empty());
    1492             : 
    1493             :     base::ElapsedTimer decode_timer;
    1494             :     if (FLAG_trace_wasm_decode_time) {
    1495             :       decode_timer.Start();
    1496             :     }
    1497             : 
    1498     1256520 :     if (this->end_ < this->pc_) {
    1499           0 :       this->error("function body end < start");
    1500           0 :       return false;
    1501             :     }
    1502             : 
    1503             :     DCHECK_EQ(0, this->local_types_->size());
    1504     1256520 :     WasmDecoder<validate>::DecodeLocals(this->enabled_, this, this->sig_,
    1505     1256520 :                                         this->local_types_);
    1506     1594857 :     CALL_INTERFACE(StartFunction);
    1507     1256608 :     DecodeFunctionBody();
    1508     1097641 :     if (!this->failed()) CALL_INTERFACE(FinishFunction);
    1509             : 
    1510             :     // Generate a better error message whether the unterminated control
    1511             :     // structure is the function body block or an innner structure.
    1512     2512394 :     if (control_.size() > 1) {
    1513        8353 :       this->error(control_.back().pc, "unterminated control structure");
    1514     1247844 :     } else if (control_.size() == 1) {
    1515       47012 :       this->error("function body must end with \"end\" opcode");
    1516             :     }
    1517             : 
    1518     1256213 :     if (this->failed()) return this->TraceFailed();
    1519             : 
    1520             :     if (FLAG_trace_wasm_decode_time) {
    1521             :       double ms = decode_timer.Elapsed().InMillisecondsF();
    1522             :       PrintF("wasm-decode %s (%0.3f ms)\n\n",
    1523             :              VALIDATE(this->ok()) ? "ok" : "failed", ms);
    1524             :     } else {
    1525             :       TRACE("wasm-decode %s\n\n", VALIDATE(this->ok()) ? "ok" : "failed");
    1526             :     }
    1527             : 
    1528     1200315 :     return true;
    1529             :   }
    1530             : 
    1531             :   bool TraceFailed() {
    1532             :     TRACE("wasm-error module+%-6d func+%d: %s\n\n", this->error_.offset(),
    1533             :           this->GetBufferRelativeOffset(this->error_.offset()),
    1534             :           this->error_.message().c_str());
    1535             :     return false;
    1536             :   }
    1537             : 
    1538       71431 :   const char* SafeOpcodeNameAt(const byte* pc) {
    1539       71431 :     if (pc >= this->end_) return "<end>";
    1540       59085 :     return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(*pc));
    1541             :   }
    1542             : 
    1543             :   inline Zone* zone() const { return zone_; }
    1544             : 
    1545             :   inline uint32_t num_locals() const {
    1546     3327650 :     return static_cast<uint32_t>(local_type_vec_.size());
    1547             :   }
    1548             : 
    1549             :   inline ValueType GetLocalType(uint32_t index) {
    1550     4297880 :     return local_type_vec_[index];
    1551             :   }
    1552             : 
    1553             :   inline WasmCodePosition position() {
    1554     1671791 :     int offset = static_cast<int>(this->pc_ - this->start_);
    1555             :     DCHECK_EQ(this->pc_ - this->start_, offset);  // overflows cannot happen
    1556             :     return offset;
    1557             :   }
    1558             : 
    1559             :   inline uint32_t control_depth() const {
    1560      749790 :     return static_cast<uint32_t>(control_.size());
    1561             :   }
    1562             : 
    1563             :   inline Control* control_at(uint32_t depth) {
    1564             :     DCHECK_GT(control_.size(), depth);
    1565      689486 :     return &control_.back() - depth;
    1566             :   }
    1567             : 
    1568             :   inline uint32_t stack_size() const {
    1569             :     DCHECK_GE(kMaxUInt32, stack_.size());
    1570     3331464 :     return static_cast<uint32_t>(stack_.size());
    1571             :   }
    1572             : 
    1573             :   inline Value* stack_value(uint32_t depth) {
    1574             :     DCHECK_LT(0, depth);
    1575             :     DCHECK_GE(stack_.size(), depth);
    1576             :     return &*(stack_.end() - depth);
    1577             :   }
    1578             : 
    1579             :  private:
    1580             :   Zone* zone_;
    1581             : 
    1582             :   Interface interface_;
    1583             : 
    1584             :   ZoneVector<ValueType> local_type_vec_;  // types of local variables.
    1585             :   ZoneVector<Value> stack_;               // stack of values.
    1586             :   ZoneVector<Control> control_;           // stack of blocks, loops, and ifs.
    1587             :   ZoneVector<Value> args_;                // parameters of current block or call
    1588             : 
    1589      731804 :   static Value UnreachableValue(const uint8_t* pc) {
    1590      731804 :     return Value{pc, kWasmVar};
    1591             :   }
    1592             : 
    1593      466531 :   bool CheckHasMemory() {
    1594      466531 :     if (!VALIDATE(this->module_->has_memory)) {
    1595         160 :       this->error(this->pc_ - 1, "memory instruction with no memory");
    1596         160 :       return false;
    1597             :     }
    1598             :     return true;
    1599             :   }
    1600             : 
    1601       47332 :   bool CheckHasSharedMemory() {
    1602       47332 :     if (!VALIDATE(this->module_->has_shared_memory)) {
    1603          16 :       this->error(this->pc_ - 1, "Atomic opcodes used without shared memory");
    1604          16 :       return false;
    1605             :     }
    1606             :     return true;
    1607             :   }
    1608             : 
    1609             :   class TraceLine {
    1610             :    public:
    1611             :     static constexpr int kMaxLen = 512;
    1612             :     ~TraceLine() {
    1613             :       if (!FLAG_trace_wasm_decoder) return;
    1614             :       PrintF("%.*s\n", len_, buffer_);
    1615             :     }
    1616             : 
    1617             :     // Appends a formatted string.
    1618             :     PRINTF_FORMAT(2, 3)
    1619             :     void Append(const char* format, ...) {
    1620             :       if (!FLAG_trace_wasm_decoder) return;
    1621             :       va_list va_args;
    1622             :       va_start(va_args, format);
    1623             :       size_t remaining_len = kMaxLen - len_;
    1624             :       Vector<char> remaining_msg_space(buffer_ + len_, remaining_len);
    1625             :       int len = VSNPrintF(remaining_msg_space, format, va_args);
    1626             :       va_end(va_args);
    1627             :       len_ += len < 0 ? remaining_len : len;
    1628             :     }
    1629             : 
    1630             :    private:
    1631             :     char buffer_[kMaxLen];
    1632             :     int len_ = 0;
    1633             :   };
    1634             : 
    1635             :   // Decodes the body of a function.
    1636     1256470 :   void DecodeFunctionBody() {
    1637             :     TRACE("wasm-decode %p...%p (module+%u, %d bytes)\n",
    1638             :           reinterpret_cast<const void*>(this->start()),
    1639             :           reinterpret_cast<const void*>(this->end()), this->pc_offset(),
    1640             :           static_cast<int>(this->end() - this->start()));
    1641             : 
    1642             :     // Set up initial function block.
    1643             :     {
    1644     1256470 :       auto* c = PushControl(kControlBlock);
    1645     1256395 :       InitMerge(&c->start_merge, 0, [](uint32_t) -> Value { UNREACHABLE(); });
    1646     2512812 :       InitMerge(&c->end_merge,
    1647             :                 static_cast<uint32_t>(this->sig_->return_count()),
    1648             :                 [&](uint32_t i) {
    1649             :                   return Value{this->pc_, this->sig_->GetReturn(i)};
    1650     2755005 :                 });
    1651     3226833 :       CALL_INTERFACE(StartFunctionBody, c);
    1652             :     }
    1653             : 
    1654    13809937 :     while (this->pc_ < this->end_) {  // decoding loop.
    1655             :       uint32_t len = 1;
    1656    11959448 :       WasmOpcode opcode = static_cast<WasmOpcode>(*this->pc_);
    1657             : 
    1658     2546560 :       CALL_INTERFACE_IF_REACHABLE(NextInstruction, opcode);
    1659             : 
    1660             : #if DEBUG
    1661             :       TraceLine trace_msg;
    1662             : #define TRACE_PART(...) trace_msg.Append(__VA_ARGS__)
    1663             :       if (!WasmOpcodes::IsPrefixOpcode(opcode)) {
    1664             :         TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    1665             :                    WasmOpcodes::OpcodeName(opcode));
    1666             :       }
    1667             : #else
    1668             : #define TRACE_PART(...)
    1669             : #endif
    1670             : 
    1671    11959448 :       switch (opcode) {
    1672             : #define BUILD_SIMPLE_OPCODE(op, _, sig) \
    1673             :   case kExpr##op:                       \
    1674             :     BuildSimpleOperator_##sig(opcode);  \
    1675             :     break;
    1676             :         FOREACH_SIMPLE_OPCODE(BUILD_SIMPLE_OPCODE)
    1677             : #undef BUILD_SIMPLE_OPCODE
    1678             :         case kExprNop:
    1679             :           break;
    1680             :         case kExprBlock: {
    1681      313724 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1682      313725 :           if (!this->Validate(imm)) break;
    1683      313720 :           PopArgs(imm.sig);
    1684      627436 :           auto* block = PushControl(kControlBlock);
    1685      313717 :           SetBlockType(block, imm);
    1686      119020 :           CALL_INTERFACE_IF_REACHABLE(Block, block);
    1687      627436 :           PushMergeValues(block, &block->start_merge);
    1688      313717 :           len = 1 + imm.length;
    1689      313717 :           break;
    1690             :         }
    1691             :         case kExprRethrow: {
    1692         428 :           CHECK_PROTOTYPE_OPCODE(eh);
    1693             :           auto exception = Pop(0, kWasmExceptRef);
    1694         848 :           CALL_INTERFACE_IF_REACHABLE(Rethrow, exception);
    1695         427 :           EndControl();
    1696         427 :           break;
    1697             :         }
    1698             :         case kExprThrow: {
    1699         643 :           CHECK_PROTOTYPE_OPCODE(eh);
    1700         643 :           ExceptionIndexImmediate<validate> imm(this, this->pc_);
    1701         644 :           len = 1 + imm.length;
    1702         644 :           if (!this->Validate(this->pc_, imm)) break;
    1703         643 :           PopArgs(imm.exception->ToFunctionSig());
    1704        1786 :           CALL_INTERFACE_IF_REACHABLE(Throw, imm, VectorOf(args_));
    1705         645 :           EndControl();
    1706         643 :           break;
    1707             :         }
    1708             :         case kExprTry: {
    1709         769 :           CHECK_PROTOTYPE_OPCODE(eh);
    1710         769 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1711         769 :           if (!this->Validate(imm)) break;
    1712         770 :           PopArgs(imm.sig);
    1713        1539 :           auto* try_block = PushControl(kControlTry);
    1714         770 :           SetBlockType(try_block, imm);
    1715         769 :           len = 1 + imm.length;
    1716        1510 :           CALL_INTERFACE_IF_REACHABLE(Try, try_block);
    1717        1540 :           PushMergeValues(try_block, &try_block->start_merge);
    1718         769 :           break;
    1719             :         }
    1720             :         case kExprCatch: {
    1721         532 :           CHECK_PROTOTYPE_OPCODE(eh);
    1722         532 :           if (!VALIDATE(!control_.empty())) {
    1723           0 :             this->error("catch does not match any try");
    1724           0 :             break;
    1725             :           }
    1726         532 :           Control* c = &control_.back();
    1727         532 :           if (!VALIDATE(c->is_try())) {
    1728           1 :             this->error("catch does not match any try");
    1729           1 :             break;
    1730             :           }
    1731         531 :           if (!VALIDATE(c->is_incomplete_try())) {
    1732           1 :             this->error("catch already present for try");
    1733           1 :             break;
    1734             :           }
    1735         530 :           c->kind = kControlTryCatch;
    1736         530 :           FallThruTo(c);
    1737        1064 :           stack_.erase(stack_.begin() + c->stack_depth, stack_.end());
    1738        1064 :           c->reachability = control_at(1)->innerReachability();
    1739             :           auto* exception = Push(kWasmExceptRef);
    1740        1064 :           CALL_INTERFACE_IF_PARENT_REACHABLE(Catch, c, exception);
    1741             :           break;
    1742             :         }
    1743             :         case kExprBrOnExn: {
    1744         385 :           CHECK_PROTOTYPE_OPCODE(eh);
    1745         385 :           BranchDepthImmediate<validate> imm_br(this, this->pc_);
    1746         770 :           if (!this->Validate(this->pc_, imm_br, control_.size())) break;
    1747             :           ExceptionIndexImmediate<validate> imm_idx(this,
    1748         384 :                                                     this->pc_ + imm_br.length);
    1749         384 :           if (!this->Validate(this->pc_ + imm_br.length, imm_idx)) break;
    1750         384 :           Control* c = control_at(imm_br.depth);
    1751             :           auto exception = Pop(0, kWasmExceptRef);
    1752         633 :           const WasmExceptionSig* sig = imm_idx.exception->sig;
    1753             :           size_t value_count = sig->parameter_count();
    1754             :           // TODO(mstarzinger): This operand stack mutation is an ugly hack to
    1755             :           // make both type checking here as well as environment merging in the
    1756             :           // graph builder interface work out of the box. We should introduce
    1757             :           // special handling for both and do minimal/no stack mutation here.
    1758         633 :           for (size_t i = 0; i < value_count; ++i) Push(sig->GetParam(i));
    1759         376 :           Vector<Value> values(stack_.data() + c->stack_depth, value_count);
    1760         384 :           if (!TypeCheckBranch(c)) break;
    1761         384 :           if (control_.back().reachable()) {
    1762         376 :             CALL_INTERFACE(BrOnException, exception, imm_idx, imm_br.depth,
    1763             :                            values);
    1764         383 :             c->br_merge()->reached = true;
    1765             :           }
    1766         383 :           len = 1 + imm_br.length + imm_idx.length;
    1767         632 :           for (size_t i = 0; i < value_count; ++i) Pop();
    1768             :           auto* pexception = Push(kWasmExceptRef);
    1769         383 :           *pexception = exception;
    1770         383 :           break;
    1771             :         }
    1772             :         case kExprLoop: {
    1773       15971 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1774       15970 :           if (!this->Validate(imm)) break;
    1775       15972 :           PopArgs(imm.sig);
    1776       31940 :           auto* block = PushControl(kControlLoop);
    1777       15972 :           SetBlockType(&control_.back(), imm);
    1778       15972 :           len = 1 + imm.length;
    1779       22816 :           CALL_INTERFACE_IF_REACHABLE(Loop, block);
    1780       31940 :           PushMergeValues(block, &block->start_merge);
    1781       15970 :           break;
    1782             :         }
    1783             :         case kExprIf: {
    1784       62235 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1785       62233 :           if (!this->Validate(imm)) break;
    1786             :           auto cond = Pop(0, kWasmI32);
    1787       62221 :           PopArgs(imm.sig);
    1788       62219 :           if (!VALIDATE(this->ok())) break;
    1789      124135 :           auto* if_block = PushControl(kControlIf);
    1790       62072 :           SetBlockType(if_block, imm);
    1791      118935 :           CALL_INTERFACE_IF_REACHABLE(If, cond, if_block);
    1792       62070 :           len = 1 + imm.length;
    1793      124140 :           PushMergeValues(if_block, &if_block->start_merge);
    1794       62070 :           break;
    1795             :         }
    1796             :         case kExprElse: {
    1797       21275 :           if (!VALIDATE(!control_.empty())) {
    1798           0 :             this->error("else does not match any if");
    1799           0 :             break;
    1800             :           }
    1801       43854 :           Control* c = &control_.back();
    1802       40838 :           if (!VALIDATE(c->is_if())) {
    1803           0 :             this->error(this->pc_, "else does not match an if");
    1804           0 :             break;
    1805             :           }
    1806       21275 :           if (c->is_if_else()) {
    1807           2 :             this->error(this->pc_, "else already present for if");
    1808           2 :             break;
    1809             :           }
    1810       21273 :           if (!TypeCheckFallThru(c)) break;
    1811       21073 :           c->kind = kControlIfElse;
    1812       39132 :           CALL_INTERFACE_IF_PARENT_REACHABLE(Else, c);
    1813       21071 :           if (c->reachable()) c->end_merge.reached = true;
    1814       42142 :           PushMergeValues(c, &c->start_merge);
    1815       42146 :           c->reachability = control_at(1)->innerReachability();
    1816       21073 :           break;
    1817             :         }
    1818             :         case kExprEnd: {
    1819     1588141 :           if (!VALIDATE(!control_.empty())) {
    1820           0 :             this->error("end does not match any if, try, or block");
    1821           0 :             break;
    1822             :           }
    1823     1588141 :           Control* c = &control_.back();
    1824     1588141 :           if (!VALIDATE(!c->is_incomplete_try())) {
    1825           1 :             this->error(this->pc_, "missing catch or catch-all in try");
    1826           1 :             break;
    1827             :           }
    1828     1588140 :           if (c->is_onearmed_if()) {
    1829       40149 :             if (!VALIDATE(c->end_merge.arity == c->start_merge.arity)) {
    1830          97 :               this->error(
    1831             :                   c->pc,
    1832             :                   "start-arity and end-arity of one-armed if must match");
    1833          97 :               break;
    1834             :             }
    1835             :           }
    1836             : 
    1837     1588043 :           if (!TypeCheckFallThru(c)) break;
    1838             : 
    1839     1581646 :           if (control_.size() == 1) {
    1840             :             // If at the last (implicit) control, check we are at end.
    1841     1200930 :             if (!VALIDATE(this->pc_ + 1 == this->end_)) {
    1842           2 :               this->error(this->pc_ + 1, "trailing code after function end");
    1843           2 :               break;
    1844             :             }
    1845             :             // The result of the block is the return value.
    1846             :             TRACE_PART("\n" TRACE_INST_FORMAT, startrel(this->pc_),
    1847             :                        "(implicit) return");
    1848     1067477 :             DoReturn();
    1849             :             control_.clear();
    1850             :             break;
    1851             :           }
    1852             : 
    1853      380716 :           PopControl(c);
    1854      380713 :           break;
    1855             :         }
    1856             :         case kExprSelect: {
    1857             :           auto cond = Pop(2, kWasmI32);
    1858             :           auto fval = Pop();
    1859        1211 :           auto tval = Pop(0, fval.type);
    1860        3676 :           auto* result = Push(tval.type == kWasmVar ? fval.type : tval.type);
    1861        4838 :           CALL_INTERFACE_IF_REACHABLE(Select, cond, fval, tval, result);
    1862             :           break;
    1863             :         }
    1864             :         case kExprBr: {
    1865       31020 :           BranchDepthImmediate<validate> imm(this, this->pc_);
    1866       62041 :           if (!this->Validate(this->pc_, imm, control_.size())) break;
    1867       30464 :           Control* c = control_at(imm.depth);
    1868       30464 :           if (!TypeCheckBranch(c)) break;
    1869       56988 :           if (imm.depth == control_.size() - 1) {
    1870         264 :             DoReturn();
    1871       28034 :           } else if (control_.back().reachable()) {
    1872       22738 :             CALL_INTERFACE(Br, c);
    1873       27447 :             c->br_merge()->reached = true;
    1874             :           }
    1875       28496 :           len = 1 + imm.length;
    1876       28496 :           EndControl();
    1877       28495 :           break;
    1878             :         }
    1879             :         case kExprBrIf: {
    1880      239301 :           BranchDepthImmediate<validate> imm(this, this->pc_);
    1881             :           auto cond = Pop(0, kWasmI32);
    1882      239302 :           if (this->failed()) break;
    1883      478178 :           if (!this->Validate(this->pc_, imm, control_.size())) break;
    1884      239017 :           Control* c = control_at(imm.depth);
    1885      239017 :           if (!TypeCheckBranch(c)) break;
    1886      238797 :           if (control_.back().reachable()) {
    1887      132374 :             CALL_INTERFACE(BrIf, cond, imm.depth);
    1888      238148 :             c->br_merge()->reached = true;
    1889             :           }
    1890      238796 :           len = 1 + imm.length;
    1891      238796 :           break;
    1892             :         }
    1893             :         case kExprBrTable: {
    1894       12880 :           BranchTableImmediate<validate> imm(this, this->pc_);
    1895             :           BranchTableIterator<validate> iterator(this, imm);
    1896             :           auto key = Pop(0, kWasmI32);
    1897       12877 :           if (this->failed()) break;
    1898       12758 :           if (!this->Validate(this->pc_, imm, control_.size())) break;
    1899             :           uint32_t br_arity = 0;
    1900       12725 :           std::vector<bool> br_targets(control_.size());
    1901      658194 :           while (iterator.has_next()) {
    1902      633100 :             const uint32_t i = iterator.cur_index();
    1903      633100 :             const byte* pos = iterator.pc();
    1904      633100 :             uint32_t target = iterator.next();
    1905     1266204 :             if (!VALIDATE(target < control_.size())) {
    1906         178 :               this->errorf(pos,
    1907             :                            "improper branch in br_table target %u (depth %u)",
    1908             :                            i, target);
    1909         178 :               break;
    1910             :             }
    1911             :             // Avoid redundant branch target checks.
    1912     1265848 :             if (br_targets[target]) continue;
    1913             :             br_targets[target] = true;
    1914             :             // Check that label types match up.
    1915             :             Control* c = control_at(target);
    1916       29219 :             uint32_t arity = c->br_merge()->arity;
    1917       29219 :             if (i == 0) {
    1918             :               br_arity = arity;
    1919       16553 :             } else if (!VALIDATE(br_arity == arity)) {
    1920          68 :               this->errorf(pos,
    1921             :                            "inconsistent arity in br_table target %u"
    1922             :                            " (previous was %u, this one %u)",
    1923             :                            i, br_arity, arity);
    1924             :             }
    1925       29219 :             if (!TypeCheckBranch(c)) break;
    1926             :           }
    1927       12728 :           if (this->failed()) break;
    1928             : 
    1929       12298 :           if (control_.back().reachable()) {
    1930       10615 :             CALL_INTERFACE(BrTable, imm, key);
    1931             : 
    1932       82359 :             for (uint32_t depth = control_depth(); depth-- > 0;) {
    1933      117670 :               if (!br_targets[depth]) continue;
    1934       28173 :               control_at(depth)->br_merge()->reached = true;
    1935             :             }
    1936             :           }
    1937             : 
    1938       12298 :           len = 1 + iterator.length();
    1939       12297 :           EndControl();
    1940       12297 :           break;
    1941             :         }
    1942             :         case kExprReturn: {
    1943      321026 :           if (!TypeCheckReturn()) break;
    1944      212652 :           DoReturn();
    1945      320569 :           EndControl();
    1946      320576 :           break;
    1947             :         }
    1948             :         case kExprUnreachable: {
    1949      221748 :           CALL_INTERFACE_IF_REACHABLE(Unreachable);
    1950      219529 :           EndControl();
    1951      219529 :           break;
    1952             :         }
    1953             :         case kExprI32Const: {
    1954     3078961 :           ImmI32Immediate<validate> imm(this, this->pc_);
    1955             :           auto* value = Push(kWasmI32);
    1956     5945613 :           CALL_INTERFACE_IF_REACHABLE(I32Const, value, imm.value);
    1957     3079082 :           len = 1 + imm.length;
    1958             :           break;
    1959             :         }
    1960             :         case kExprI64Const: {
    1961       95448 :           ImmI64Immediate<validate> imm(this, this->pc_);
    1962             :           auto* value = Push(kWasmI64);
    1963      124701 :           CALL_INTERFACE_IF_REACHABLE(I64Const, value, imm.value);
    1964       95478 :           len = 1 + imm.length;
    1965             :           break;
    1966             :         }
    1967             :         case kExprF32Const: {
    1968      239185 :           ImmF32Immediate<validate> imm(this, this->pc_);
    1969             :           auto* value = Push(kWasmF32);
    1970      243647 :           CALL_INTERFACE_IF_REACHABLE(F32Const, value, imm.value);
    1971      239187 :           len = 1 + imm.length;
    1972             :           break;
    1973             :         }
    1974             :         case kExprF64Const: {
    1975      245608 :           ImmF64Immediate<validate> imm(this, this->pc_);
    1976             :           auto* value = Push(kWasmF64);
    1977      256716 :           CALL_INTERFACE_IF_REACHABLE(F64Const, value, imm.value);
    1978      245610 :           len = 1 + imm.length;
    1979             :           break;
    1980             :         }
    1981             :         case kExprRefNull: {
    1982         146 :           CHECK_PROTOTYPE_OPCODE(anyref);
    1983             :           auto* value = Push(kWasmNullRef);
    1984         290 :           CALL_INTERFACE_IF_REACHABLE(RefNull, value);
    1985             :           len = 1;
    1986             :           break;
    1987             :         }
    1988             :         case kExprGetLocal: {
    1989      908959 :           LocalIndexImmediate<validate> imm(this, this->pc_);
    1990      909033 :           if (!this->Validate(this->pc_, imm)) break;
    1991      908655 :           auto* value = Push(imm.type);
    1992     1701089 :           CALL_INTERFACE_IF_REACHABLE(GetLocal, value, imm);
    1993      908713 :           len = 1 + imm.length;
    1994      908713 :           break;
    1995             :         }
    1996             :         case kExprSetLocal: {
    1997      444827 :           LocalIndexImmediate<validate> imm(this, this->pc_);
    1998      444828 :           if (!this->Validate(this->pc_, imm)) break;
    1999      990556 :           auto value = Pop(0, local_type_vec_[imm.index]);
    2000      866717 :           CALL_INTERFACE_IF_REACHABLE(SetLocal, value, imm);
    2001      444676 :           len = 1 + imm.length;
    2002      444676 :           break;
    2003             :         }
    2004             :         case kExprTeeLocal: {
    2005      101199 :           LocalIndexImmediate<validate> imm(this, this->pc_);
    2006      101199 :           if (!this->Validate(this->pc_, imm)) break;
    2007      202396 :           auto value = Pop(0, local_type_vec_[imm.index]);
    2008             :           auto* result = Push(value.type);
    2009      199536 :           CALL_INTERFACE_IF_REACHABLE(TeeLocal, value, result, imm);
    2010      101198 :           len = 1 + imm.length;
    2011      101198 :           break;
    2012             :         }
    2013             :         case kExprDrop: {
    2014             :           auto value = Pop();
    2015        6631 :           CALL_INTERFACE_IF_REACHABLE(Drop, value);
    2016             :           break;
    2017             :         }
    2018             :         case kExprGetGlobal: {
    2019       38043 :           GlobalIndexImmediate<validate> imm(this, this->pc_);
    2020       38043 :           len = 1 + imm.length;
    2021       38043 :           if (!this->Validate(this->pc_, imm)) break;
    2022       38022 :           auto* result = Push(imm.type);
    2023       75014 :           CALL_INTERFACE_IF_REACHABLE(GetGlobal, result, imm);
    2024             :           break;
    2025             :         }
    2026             :         case kExprSetGlobal: {
    2027       16466 :           GlobalIndexImmediate<validate> imm(this, this->pc_);
    2028       16466 :           len = 1 + imm.length;
    2029       16466 :           if (!this->Validate(this->pc_, imm)) break;
    2030       16466 :           if (!VALIDATE(imm.global->mutability)) {
    2031          25 :             this->errorf(this->pc_, "immutable global #%u cannot be assigned",
    2032             :                          imm.index);
    2033          25 :             break;
    2034             :           }
    2035       16441 :           auto value = Pop(0, imm.type);
    2036       32055 :           CALL_INTERFACE_IF_REACHABLE(SetGlobal, value, imm);
    2037             :           break;
    2038             :         }
    2039             :         case kExprGetTable: {
    2040          12 :           CHECK_PROTOTYPE_OPCODE(anyref);
    2041          12 :           TableIndexImmediate<validate> imm(this, this->pc_);
    2042          12 :           len = 1 + imm.length;
    2043          12 :           if (!this->Validate(this->pc_, imm)) break;
    2044             :           DCHECK_NOT_NULL(this->module_);
    2045             :           auto index = Pop(0, kWasmI32);
    2046          30 :           auto* result = Push(this->module_->tables[imm.index].type);
    2047          20 :           CALL_INTERFACE_IF_REACHABLE(GetTable, index, result, imm);
    2048             :           break;
    2049             :         }
    2050             :         case kExprSetTable: {
    2051          12 :           CHECK_PROTOTYPE_OPCODE(anyref);
    2052          12 :           TableIndexImmediate<validate> imm(this, this->pc_);
    2053          12 :           len = 1 + imm.length;
    2054          12 :           if (!this->Validate(this->pc_, imm)) break;
    2055          20 :           auto value = Pop(0, this->module_->tables[imm.index].type);
    2056             :           auto index = Pop(0, kWasmI32);
    2057          16 :           CALL_INTERFACE_IF_REACHABLE(SetTable, index, value, imm);
    2058             :           break;
    2059             :         }
    2060             : 
    2061             :         case kExprI32LoadMem8S:
    2062        3210 :           len = 1 + DecodeLoadMem(LoadType::kI32Load8S);
    2063        3210 :           break;
    2064             :         case kExprI32LoadMem8U:
    2065        2024 :           len = 1 + DecodeLoadMem(LoadType::kI32Load8U);
    2066        2024 :           break;
    2067             :         case kExprI32LoadMem16S:
    2068         466 :           len = 1 + DecodeLoadMem(LoadType::kI32Load16S);
    2069         466 :           break;
    2070             :         case kExprI32LoadMem16U:
    2071         784 :           len = 1 + DecodeLoadMem(LoadType::kI32Load16U);
    2072         784 :           break;
    2073             :         case kExprI32LoadMem:
    2074       86927 :           len = 1 + DecodeLoadMem(LoadType::kI32Load);
    2075       86918 :           break;
    2076             :         case kExprI64LoadMem8S:
    2077         493 :           len = 1 + DecodeLoadMem(LoadType::kI64Load8S);
    2078         493 :           break;
    2079             :         case kExprI64LoadMem8U:
    2080         387 :           len = 1 + DecodeLoadMem(LoadType::kI64Load8U);
    2081         387 :           break;
    2082             :         case kExprI64LoadMem16S:
    2083         445 :           len = 1 + DecodeLoadMem(LoadType::kI64Load16S);
    2084         445 :           break;
    2085             :         case kExprI64LoadMem16U:
    2086         435 :           len = 1 + DecodeLoadMem(LoadType::kI64Load16U);
    2087         435 :           break;
    2088             :         case kExprI64LoadMem32S:
    2089         469 :           len = 1 + DecodeLoadMem(LoadType::kI64Load32S);
    2090         469 :           break;
    2091             :         case kExprI64LoadMem32U:
    2092         459 :           len = 1 + DecodeLoadMem(LoadType::kI64Load32U);
    2093         459 :           break;
    2094             :         case kExprI64LoadMem:
    2095       89829 :           len = 1 + DecodeLoadMem(LoadType::kI64Load);
    2096       89829 :           break;
    2097             :         case kExprF32LoadMem:
    2098        2842 :           len = 1 + DecodeLoadMem(LoadType::kF32Load);
    2099        2842 :           break;
    2100             :         case kExprF64LoadMem:
    2101        3832 :           len = 1 + DecodeLoadMem(LoadType::kF64Load);
    2102        3832 :           break;
    2103             :         case kExprI32StoreMem8:
    2104        2394 :           len = 1 + DecodeStoreMem(StoreType::kI32Store8);
    2105        2394 :           break;
    2106             :         case kExprI32StoreMem16:
    2107         850 :           len = 1 + DecodeStoreMem(StoreType::kI32Store16);
    2108         850 :           break;
    2109             :         case kExprI32StoreMem:
    2110      160654 :           len = 1 + DecodeStoreMem(StoreType::kI32Store);
    2111      160661 :           break;
    2112             :         case kExprI64StoreMem8:
    2113         320 :           len = 1 + DecodeStoreMem(StoreType::kI64Store8);
    2114         320 :           break;
    2115             :         case kExprI64StoreMem16:
    2116         480 :           len = 1 + DecodeStoreMem(StoreType::kI64Store16);
    2117         480 :           break;
    2118             :         case kExprI64StoreMem32:
    2119         432 :           len = 1 + DecodeStoreMem(StoreType::kI64Store32);
    2120         431 :           break;
    2121             :         case kExprI64StoreMem:
    2122      102130 :           len = 1 + DecodeStoreMem(StoreType::kI64Store);
    2123      102130 :           break;
    2124             :         case kExprF32StoreMem:
    2125         765 :           len = 1 + DecodeStoreMem(StoreType::kF32Store);
    2126         765 :           break;
    2127             :         case kExprF64StoreMem:
    2128        1693 :           len = 1 + DecodeStoreMem(StoreType::kF64Store);
    2129        1693 :           break;
    2130             :         case kExprMemoryGrow: {
    2131        3167 :           if (!CheckHasMemory()) break;
    2132        3127 :           MemoryIndexImmediate<validate> imm(this, this->pc_);
    2133        3127 :           len = 1 + imm.length;
    2134             :           DCHECK_NOT_NULL(this->module_);
    2135        3127 :           if (!VALIDATE(this->module_->origin == kWasmOrigin)) {
    2136           1 :             this->error("grow_memory is not supported for asmjs modules");
    2137           1 :             break;
    2138             :           }
    2139             :           auto value = Pop(0, kWasmI32);
    2140             :           auto* result = Push(kWasmI32);
    2141        6105 :           CALL_INTERFACE_IF_REACHABLE(MemoryGrow, value, result);
    2142             :           break;
    2143             :         }
    2144             :         case kExprMemorySize: {
    2145        1062 :           if (!CheckHasMemory()) break;
    2146        1038 :           MemoryIndexImmediate<validate> imm(this, this->pc_);
    2147             :           auto* result = Push(kWasmI32);
    2148        1038 :           len = 1 + imm.length;
    2149        1940 :           CALL_INTERFACE_IF_REACHABLE(CurrentMemoryPages, result);
    2150             :           break;
    2151             :         }
    2152             :         case kExprCallFunction: {
    2153      265689 :           CallFunctionImmediate<validate> imm(this, this->pc_);
    2154      265690 :           len = 1 + imm.length;
    2155      265690 :           if (!this->Validate(this->pc_, imm)) break;
    2156             :           // TODO(clemensh): Better memory management.
    2157      265620 :           PopArgs(imm.sig);
    2158      265617 :           auto* returns = PushReturns(imm.sig);
    2159      332451 :           CALL_INTERFACE_IF_REACHABLE(CallDirect, imm, args_.data(), returns);
    2160             :           break;
    2161             :         }
    2162             :         case kExprCallIndirect: {
    2163        8347 :           CallIndirectImmediate<validate> imm(this, this->pc_);
    2164        8349 :           len = 1 + imm.length;
    2165        8349 :           if (!this->Validate(this->pc_, imm)) break;
    2166             :           auto index = Pop(0, kWasmI32);
    2167        8259 :           PopArgs(imm.sig);
    2168        8261 :           auto* returns = PushReturns(imm.sig);
    2169       16049 :           CALL_INTERFACE_IF_REACHABLE(CallIndirect, index, imm, args_.data(),
    2170             :                                       returns);
    2171             :           break;
    2172             :         }
    2173             :         case kExprReturnCall: {
    2174          12 :           CHECK_PROTOTYPE_OPCODE(return_call);
    2175             : 
    2176          12 :           CallFunctionImmediate<validate> imm(this, this->pc_);
    2177          12 :           len = 1 + imm.length;
    2178          12 :           if (!this->Validate(this->pc_, imm)) break;
    2179          12 :           if (!this->CanTailCall(imm.sig)) {
    2180           4 :             OPCODE_ERROR(opcode, "tail call return types mismatch");
    2181           4 :             break;
    2182             :           }
    2183             : 
    2184             :           PopArgs(imm.sig);
    2185             : 
    2186           0 :           CALL_INTERFACE_IF_REACHABLE(ReturnCall, imm, args_.data());
    2187           8 :           EndControl();
    2188           8 :           break;
    2189             :         }
    2190             :         case kExprReturnCallIndirect: {
    2191          21 :           CHECK_PROTOTYPE_OPCODE(return_call);
    2192          20 :           CallIndirectImmediate<validate> imm(this, this->pc_);
    2193          20 :           len = 1 + imm.length;
    2194          20 :           if (!this->Validate(this->pc_, imm)) break;
    2195           5 :           if (!this->CanTailCall(imm.sig)) {
    2196           0 :             OPCODE_ERROR(opcode, "tail call return types mismatch");
    2197           0 :             break;
    2198             :           }
    2199             :           auto index = Pop(0, kWasmI32);
    2200           5 :           PopArgs(imm.sig);
    2201           0 :           CALL_INTERFACE_IF_REACHABLE(ReturnCallIndirect, index, imm,
    2202             :                                       args_.data());
    2203           5 :           EndControl();
    2204           5 :           break;
    2205             :         }
    2206             :         case kNumericPrefix: {
    2207             :           ++len;
    2208             :           byte numeric_index =
    2209         522 :               this->template read_u8<validate>(this->pc_ + 1, "numeric index");
    2210         522 :           opcode = static_cast<WasmOpcode>(opcode << 8 | numeric_index);
    2211         522 :           if (opcode < kExprMemoryInit) {
    2212          98 :             CHECK_PROTOTYPE_OPCODE(sat_f2i_conversions);
    2213             :           } else {
    2214         424 :             CHECK_PROTOTYPE_OPCODE(bulk_memory);
    2215             :           }
    2216             :           TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    2217             :                      WasmOpcodes::OpcodeName(opcode));
    2218         513 :           len += DecodeNumericOpcode(opcode);
    2219         513 :           break;
    2220             :         }
    2221             :         case kSimdPrefix: {
    2222       38681 :           CHECK_PROTOTYPE_OPCODE(simd);
    2223             :           len++;
    2224             :           byte simd_index =
    2225       38681 :               this->template read_u8<validate>(this->pc_ + 1, "simd index");
    2226       38681 :           opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
    2227             :           TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    2228             :                      WasmOpcodes::OpcodeName(opcode));
    2229       38681 :           len += DecodeSimdOpcode(opcode);
    2230       38681 :           break;
    2231             :         }
    2232             :         case kAtomicPrefix: {
    2233       47341 :           CHECK_PROTOTYPE_OPCODE(threads);
    2234       47341 :           if (!CheckHasSharedMemory()) break;
    2235             :           len++;
    2236             :           byte atomic_index =
    2237       47336 :               this->template read_u8<validate>(this->pc_ + 1, "atomic index");
    2238       47350 :           opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_index);
    2239             :           TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    2240             :                      WasmOpcodes::OpcodeName(opcode));
    2241       47350 :           len += DecodeAtomicOpcode(opcode);
    2242       47389 :           break;
    2243             :         }
    2244             : // Note that prototype opcodes are not handled in the fastpath
    2245             : // above this switch, to avoid checking a feature flag.
    2246             : #define SIMPLE_PROTOTYPE_CASE(name, opc, sig) \
    2247             :   case kExpr##name: /* fallthrough */
    2248             :           FOREACH_SIMPLE_PROTOTYPE_OPCODE(SIMPLE_PROTOTYPE_CASE)
    2249             : #undef SIMPLE_PROTOTYPE_CASE
    2250          88 :           BuildSimplePrototypeOperator(opcode);
    2251          88 :           break;
    2252             :         default: {
    2253             :           // Deal with special asmjs opcodes.
    2254      100191 :           if (this->module_ != nullptr &&
    2255             :               this->module_->origin == kAsmJsOrigin) {
    2256      100160 :             FunctionSig* sig = WasmOpcodes::AsmjsSignature(opcode);
    2257      100160 :             if (sig) {
    2258      100160 :               BuildSimpleOperator(opcode, sig);
    2259             :             }
    2260             :           } else {
    2261          31 :             this->error("Invalid opcode");
    2262     1256474 :             return;
    2263             :           }
    2264             :         }
    2265             :       }
    2266             : 
    2267             : #if DEBUG
    2268             :       if (FLAG_trace_wasm_decoder) {
    2269             :         TRACE_PART(" ");
    2270             :         for (Control& c : control_) {
    2271             :           switch (c.kind) {
    2272             :             case kControlIf:
    2273             :               TRACE_PART("I");
    2274             :               break;
    2275             :             case kControlBlock:
    2276             :               TRACE_PART("B");
    2277             :               break;
    2278             :             case kControlLoop:
    2279             :               TRACE_PART("L");
    2280             :               break;
    2281             :             case kControlTry:
    2282             :               TRACE_PART("T");
    2283             :               break;
    2284             :             default:
    2285             :               break;
    2286             :           }
    2287             :           if (c.start_merge.arity) TRACE_PART("%u-", c.start_merge.arity);
    2288             :           TRACE_PART("%u", c.end_merge.arity);
    2289             :           if (!c.reachable()) TRACE_PART("%c", c.unreachable() ? '*' : '#');
    2290             :         }
    2291             :         TRACE_PART(" | ");
    2292             :         for (size_t i = 0; i < stack_.size(); ++i) {
    2293             :           auto& val = stack_[i];
    2294             :           WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
    2295             :           if (WasmOpcodes::IsPrefixOpcode(opcode)) {
    2296             :             opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1));
    2297             :           }
    2298             :           TRACE_PART(" %c@%d:%s", ValueTypes::ShortNameOf(val.type),
    2299             :                      static_cast<int>(val.pc - this->start_),
    2300             :                      WasmOpcodes::OpcodeName(opcode));
    2301             :           // If the decoder failed, don't try to decode the immediates, as this
    2302             :           // can trigger a DCHECK failure.
    2303             :           if (this->failed()) continue;
    2304             :           switch (opcode) {
    2305             :             case kExprI32Const: {
    2306             :               ImmI32Immediate<Decoder::kNoValidate> imm(this, val.pc);
    2307             :               TRACE_PART("[%d]", imm.value);
    2308             :               break;
    2309             :             }
    2310             :             case kExprGetLocal:
    2311             :             case kExprSetLocal:
    2312             :             case kExprTeeLocal: {
    2313             :               LocalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
    2314             :               TRACE_PART("[%u]", imm.index);
    2315             :               break;
    2316             :             }
    2317             :             case kExprGetGlobal:
    2318             :             case kExprSetGlobal: {
    2319             :               GlobalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
    2320             :               TRACE_PART("[%u]", imm.index);
    2321             :               break;
    2322             :             }
    2323             :             default:
    2324             :               break;
    2325             :           }
    2326             :         }
    2327             :       }
    2328             : #endif
    2329    11959414 :       this->pc_ += len;
    2330             :     }  // end decode loop
    2331     1311739 :     if (!VALIDATE(this->pc_ == this->end_) && this->ok()) {
    2332           0 :       this->error("Beyond end of code");
    2333             :     }
    2334             :   }
    2335             : 
    2336      581942 :   void EndControl() {
    2337             :     DCHECK(!control_.empty());
    2338             :     auto* current = &control_.back();
    2339     1163884 :     stack_.erase(stack_.begin() + current->stack_depth, stack_.end());
    2340      238779 :     CALL_INTERFACE_IF_REACHABLE(EndControl, current);
    2341      581964 :     current->reachability = kUnreachable;
    2342      581964 :   }
    2343             : 
    2344             :   template<typename func>
    2345     3297903 :   void InitMerge(Merge<Value>* merge, uint32_t arity, func get_val) {
    2346     3297903 :     merge->arity = arity;
    2347     3297903 :     if (arity == 1) {
    2348     1009892 :       merge->vals.first = get_val(0);
    2349     2288011 :     } else if (arity > 1) {
    2350        6308 :       merge->vals.array = zone_->NewArray<Value>(arity);
    2351        7630 :       for (uint32_t i = 0; i < arity; i++) {
    2352       12672 :         merge->vals.array[i] = get_val(i);
    2353             :       }
    2354             :     }
    2355     3297903 :   }
    2356             : 
    2357     1177575 :   void SetBlockType(Control* c, BlockTypeImmediate<validate>& imm) {
    2358             :     DCHECK_EQ(imm.in_arity(), this->args_.size());
    2359      392524 :     const byte* pc = this->pc_;
    2360             :     Value* args = this->args_.data();
    2361      785048 :     InitMerge(&c->end_merge, imm.out_arity(), [pc, &imm](uint32_t i) {
    2362             :       return Value{pc, imm.out_type(i)};
    2363      421175 :     });
    2364      785054 :     InitMerge(&c->start_merge, imm.in_arity(),
    2365      392721 :               [args](uint32_t i) { return args[i]; });
    2366      392528 :   }
    2367             : 
    2368             :   // Pops arguments as required by signature into {args_}.
    2369      318102 :   V8_INLINE void PopArgs(FunctionSig* sig) {
    2370      834671 :     int count = sig ? static_cast<int>(sig->parameter_count()) : 0;
    2371     1061116 :     args_.resize(count, UnreachableValue(nullptr));
    2372     1353586 :     for (int i = count - 1; i >= 0; --i) {
    2373     1813938 :       args_[i] = Pop(i, sig->GetParam(i));
    2374             :     }
    2375             :   }
    2376             : 
    2377      171625 :   ValueType GetReturnType(FunctionSig* sig) {
    2378             :     DCHECK_GE(1, sig->return_count());
    2379       87894 :     return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn();
    2380             :   }
    2381             : 
    2382     1648981 :   Control* PushControl(ControlKind kind) {
    2383             :     Reachability reachability =
    2384     3297962 :         control_.empty() ? kReachable : control_.back().innerReachability();
    2385     3297962 :     control_.emplace_back(kind, stack_size(), this->pc_, reachability);
    2386     1648903 :     return &control_.back();
    2387             :   }
    2388             : 
    2389      872930 :   void PopControl(Control* c) {
    2390             :     DCHECK_EQ(c, &control_.back());
    2391      522508 :     CALL_INTERFACE_IF_PARENT_REACHABLE(PopControl, c);
    2392             : 
    2393             :     // A loop just leaves the values on the stack.
    2394      809055 :     if (!c->is_loop()) PushMergeValues(c, &c->end_merge);
    2395             : 
    2396             :     bool parent_reached =
    2397      447960 :         c->reachable() || c->end_merge.reached || c->is_onearmed_if();
    2398             :     control_.pop_back();
    2399             :     // If the parent block was reachable before, but the popped control does not
    2400             :     // return to here, this block becomes "spec only reachable".
    2401      393735 :     if (!parent_reached && control_.back().reachable()) {
    2402       37523 :       control_.back().reachability = kSpecOnlyReachable;
    2403             :     }
    2404      380713 :   }
    2405             : 
    2406      192608 :   int DecodeLoadMem(LoadType type, int prefix_len = 0) {
    2407      192608 :     if (!CheckHasMemory()) return 0;
    2408             :     MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
    2409      192568 :                                         type.size_log_2());
    2410             :     auto index = Pop(0, kWasmI32);
    2411             :     auto* result = Push(type.value_type());
    2412      360551 :     CALL_INTERFACE_IF_REACHABLE(LoadMem, type, imm, index, result);
    2413      192570 :     return imm.length;
    2414             :   }
    2415             : 
    2416      269709 :   int DecodeStoreMem(StoreType store, int prefix_len = 0) {
    2417      269709 :     if (!CheckHasMemory()) return 0;
    2418             :     MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
    2419      269686 :                                         store.size_log_2());
    2420             :     auto value = Pop(1, store.value_type());
    2421             :     auto index = Pop(0, kWasmI32);
    2422      516918 :     CALL_INTERFACE_IF_REACHABLE(StoreMem, store, imm, index, value);
    2423      269703 :     return imm.length;
    2424             :   }
    2425             : 
    2426       18260 :   uint32_t SimdExtractLane(WasmOpcode opcode, ValueType type) {
    2427       18260 :     SimdLaneImmediate<validate> imm(this, this->pc_);
    2428       18260 :     if (this->Validate(this->pc_, opcode, imm)) {
    2429           0 :       Value inputs[] = {Pop(0, kWasmS128)};
    2430             :       auto* result = Push(type);
    2431       36520 :       CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
    2432             :                                   result);
    2433             :     }
    2434       18260 :     return imm.length;
    2435             :   }
    2436             : 
    2437         416 :   uint32_t SimdReplaceLane(WasmOpcode opcode, ValueType type) {
    2438         416 :     SimdLaneImmediate<validate> imm(this, this->pc_);
    2439         416 :     if (this->Validate(this->pc_, opcode, imm)) {
    2440         416 :       Value inputs[2] = {UnreachableValue(this->pc_),
    2441           0 :                          UnreachableValue(this->pc_)};
    2442         416 :       inputs[1] = Pop(1, type);
    2443         416 :       inputs[0] = Pop(0, kWasmS128);
    2444             :       auto* result = Push(kWasmS128);
    2445         832 :       CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
    2446             :                                   result);
    2447             :     }
    2448         416 :     return imm.length;
    2449             :   }
    2450             : 
    2451        1272 :   uint32_t SimdShiftOp(WasmOpcode opcode) {
    2452        1272 :     SimdShiftImmediate<validate> imm(this, this->pc_);
    2453        1272 :     if (this->Validate(this->pc_, opcode, imm)) {
    2454             :       auto input = Pop(0, kWasmS128);
    2455             :       auto* result = Push(kWasmS128);
    2456        2544 :       CALL_INTERFACE_IF_REACHABLE(SimdShiftOp, opcode, imm, input, result);
    2457             :     }
    2458        1272 :     return imm.length;
    2459             :   }
    2460             : 
    2461       14545 :   uint32_t Simd8x16ShuffleOp() {
    2462       14545 :     Simd8x16ShuffleImmediate<validate> imm(this, this->pc_);
    2463       14545 :     if (this->Validate(this->pc_, imm)) {
    2464             :       auto input1 = Pop(1, kWasmS128);
    2465             :       auto input0 = Pop(0, kWasmS128);
    2466             :       auto* result = Push(kWasmS128);
    2467       29088 :       CALL_INTERFACE_IF_REACHABLE(Simd8x16ShuffleOp, imm, input0, input1,
    2468             :                                   result);
    2469             :     }
    2470       14545 :     return 16;
    2471             :   }
    2472             : 
    2473       38681 :   uint32_t DecodeSimdOpcode(WasmOpcode opcode) {
    2474             :     uint32_t len = 0;
    2475       38681 :     switch (opcode) {
    2476             :       case kExprF32x4ExtractLane: {
    2477         704 :         len = SimdExtractLane(opcode, kWasmF32);
    2478         704 :         break;
    2479             :       }
    2480             :       case kExprI32x4ExtractLane:
    2481             :       case kExprI16x8ExtractLane:
    2482             :       case kExprI8x16ExtractLane: {
    2483       17556 :         len = SimdExtractLane(opcode, kWasmI32);
    2484       17556 :         break;
    2485             :       }
    2486             :       case kExprF32x4ReplaceLane: {
    2487          64 :         len = SimdReplaceLane(opcode, kWasmF32);
    2488          64 :         break;
    2489             :       }
    2490             :       case kExprI32x4ReplaceLane:
    2491             :       case kExprI16x8ReplaceLane:
    2492             :       case kExprI8x16ReplaceLane: {
    2493         352 :         len = SimdReplaceLane(opcode, kWasmI32);
    2494         352 :         break;
    2495             :       }
    2496             :       case kExprI32x4Shl:
    2497             :       case kExprI32x4ShrS:
    2498             :       case kExprI32x4ShrU:
    2499             :       case kExprI16x8Shl:
    2500             :       case kExprI16x8ShrS:
    2501             :       case kExprI16x8ShrU:
    2502             :       case kExprI8x16Shl:
    2503             :       case kExprI8x16ShrS:
    2504             :       case kExprI8x16ShrU: {
    2505        1272 :         len = SimdShiftOp(opcode);
    2506        1272 :         break;
    2507             :       }
    2508             :       case kExprS8x16Shuffle: {
    2509       14545 :         len = Simd8x16ShuffleOp();
    2510       14545 :         break;
    2511             :       }
    2512             :       case kExprS128LoadMem:
    2513          16 :         len = DecodeLoadMem(LoadType::kS128Load, 1);
    2514          16 :         break;
    2515             :       case kExprS128StoreMem:
    2516           8 :         len = DecodeStoreMem(StoreType::kS128Store, 1);
    2517           8 :         break;
    2518             :       default: {
    2519        8328 :         FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2520        4164 :         if (!VALIDATE(sig != nullptr)) {
    2521           0 :           this->error("invalid simd opcode");
    2522           0 :           break;
    2523             :         }
    2524             :         PopArgs(sig);
    2525             :         auto* results =
    2526        8328 :             sig->return_count() == 0 ? nullptr : Push(GetReturnType(sig));
    2527       12492 :         CALL_INTERFACE_IF_REACHABLE(SimdOp, opcode, VectorOf(args_), results);
    2528             :       }
    2529             :     }
    2530       38681 :     return len;
    2531             :   }
    2532             : 
    2533       47344 :   uint32_t DecodeAtomicOpcode(WasmOpcode opcode) {
    2534             :     uint32_t len = 0;
    2535             :     ValueType ret_type;
    2536       47344 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2537       47348 :     if (sig != nullptr) {
    2538             :       MachineType memtype;
    2539       47348 :       switch (opcode) {
    2540             : #define CASE_ATOMIC_STORE_OP(Name, Type) \
    2541             :   case kExpr##Name: {                    \
    2542             :     memtype = MachineType::Type();       \
    2543             :     ret_type = kWasmStmt;                \
    2544             :     break;                               \
    2545             :   }
    2546         357 :         ATOMIC_STORE_OP_LIST(CASE_ATOMIC_STORE_OP)
    2547             : #undef CASE_ATOMIC_OP
    2548             : #define CASE_ATOMIC_OP(Name, Type) \
    2549             :   case kExpr##Name: {              \
    2550             :     memtype = MachineType::Type(); \
    2551             :     ret_type = GetReturnType(sig); \
    2552             :     break;                         \
    2553             :   }
    2554       41877 :         ATOMIC_OP_LIST(CASE_ATOMIC_OP)
    2555             : #undef CASE_ATOMIC_OP
    2556             :         default:
    2557           0 :           this->error("invalid atomic opcode");
    2558           0 :           return 0;
    2559             :       }
    2560             :       MemoryAccessImmediate<validate> imm(
    2561       47348 :           this, this->pc_ + 1, ElementSizeLog2Of(memtype.representation()));
    2562       47369 :       len += imm.length;
    2563             :       PopArgs(sig);
    2564       76218 :       auto result = ret_type == kWasmStmt ? nullptr : Push(GetReturnType(sig));
    2565      127399 :       CALL_INTERFACE_IF_REACHABLE(AtomicOp, opcode, VectorOf(args_), imm,
    2566             :                                   result);
    2567             :     } else {
    2568           0 :       this->error("invalid atomic opcode");
    2569             :     }
    2570       47387 :     return len;
    2571             :   }
    2572             : 
    2573         513 :   unsigned DecodeNumericOpcode(WasmOpcode opcode) {
    2574             :     unsigned len = 0;
    2575        1038 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2576         513 :     if (sig != nullptr) {
    2577         513 :       switch (opcode) {
    2578             :         case kExprI32SConvertSatF32:
    2579             :         case kExprI32UConvertSatF32:
    2580             :         case kExprI32SConvertSatF64:
    2581             :         case kExprI32UConvertSatF64:
    2582             :         case kExprI64SConvertSatF32:
    2583             :         case kExprI64UConvertSatF32:
    2584             :         case kExprI64SConvertSatF64:
    2585             :         case kExprI64UConvertSatF64:
    2586          96 :           BuildSimpleOperator(opcode, sig);
    2587          96 :           break;
    2588             :         case kExprMemoryInit: {
    2589          78 :           MemoryInitImmediate<validate> imm(this, this->pc_);
    2590          78 :           if (!this->Validate(imm)) break;
    2591          77 :           len += imm.length;
    2592             :           auto size = Pop(2, sig->GetParam(2));
    2593             :           auto src = Pop(1, sig->GetParam(1));
    2594             :           auto dst = Pop(0, sig->GetParam(0));
    2595         152 :           CALL_INTERFACE_IF_REACHABLE(MemoryInit, imm, dst, src, size);
    2596             :           break;
    2597             :         }
    2598             :         case kExprDataDrop: {
    2599          42 :           DataDropImmediate<validate> imm(this, this->pc_);
    2600          42 :           if (!this->Validate(imm)) break;
    2601          41 :           len += imm.length;
    2602          82 :           CALL_INTERFACE_IF_REACHABLE(DataDrop, imm);
    2603             :           break;
    2604             :         }
    2605             :         case kExprMemoryCopy: {
    2606          50 :           MemoryCopyImmediate<validate> imm(this, this->pc_);
    2607          50 :           if (!this->Validate(imm)) break;
    2608          49 :           len += imm.length;
    2609             :           auto size = Pop(2, sig->GetParam(2));
    2610             :           auto src = Pop(1, sig->GetParam(1));
    2611             :           auto dst = Pop(0, sig->GetParam(0));
    2612          98 :           CALL_INTERFACE_IF_REACHABLE(MemoryCopy, imm, dst, src, size);
    2613             :           break;
    2614             :         }
    2615             :         case kExprMemoryFill: {
    2616          50 :           MemoryIndexImmediate<validate> imm(this, this->pc_ + 1);
    2617          50 :           if (!this->Validate(this->pc_ + 1, imm)) break;
    2618          49 :           len += imm.length;
    2619             :           auto size = Pop(2, sig->GetParam(2));
    2620             :           auto value = Pop(1, sig->GetParam(1));
    2621             :           auto dst = Pop(0, sig->GetParam(0));
    2622          98 :           CALL_INTERFACE_IF_REACHABLE(MemoryFill, imm, dst, value, size);
    2623             :           break;
    2624             :         }
    2625             :         case kExprTableInit: {
    2626          56 :           TableInitImmediate<validate> imm(this, this->pc_);
    2627          55 :           if (!this->Validate(imm)) break;
    2628          53 :           len += imm.length;
    2629             :           PopArgs(sig);
    2630         133 :           CALL_INTERFACE_IF_REACHABLE(TableInit, imm, VectorOf(args_));
    2631             :           break;
    2632             :         }
    2633             :         case kExprElemDrop: {
    2634          35 :           ElemDropImmediate<validate> imm(this, this->pc_);
    2635          35 :           if (!this->Validate(imm)) break;
    2636          33 :           len += imm.length;
    2637          66 :           CALL_INTERFACE_IF_REACHABLE(ElemDrop, imm);
    2638             :           break;
    2639             :         }
    2640             :         case kExprTableCopy: {
    2641         106 :           TableCopyImmediate<validate> imm(this, this->pc_);
    2642         106 :           if (!this->Validate(imm)) break;
    2643         105 :           len += imm.length;
    2644             :           PopArgs(sig);
    2645         274 :           CALL_INTERFACE_IF_REACHABLE(TableCopy, imm, VectorOf(args_));
    2646             :           break;
    2647             :         }
    2648             :         default:
    2649           0 :           this->error("invalid numeric opcode");
    2650           0 :           break;
    2651             :       }
    2652             :     } else {
    2653           0 :       this->error("invalid numeric opcode");
    2654             :     }
    2655         513 :     return len;
    2656             :   }
    2657             : 
    2658     1280393 :   void DoReturn() {
    2659      584681 :     size_t return_count = this->sig_->return_count();
    2660             :     DCHECK_GE(stack_.size(), return_count);
    2661             :     Vector<Value> return_values =
    2662             :         return_count == 0
    2663             :             ? Vector<Value>{}
    2664      584681 :             : Vector<Value>{&*(stack_.end() - return_count), return_count};
    2665             : 
    2666     2560859 :     CALL_INTERFACE_IF_REACHABLE(DoReturn, return_values);
    2667     1280345 :   }
    2668             : 
    2669             :   inline Value* Push(ValueType type) {
    2670             :     DCHECK_NE(kWasmStmt, type);
    2671     7448701 :     stack_.emplace_back(this->pc_, type);
    2672             :     return &stack_.back();
    2673             :   }
    2674             : 
    2675      780501 :   void PushMergeValues(Control* c, Merge<Value>* merge) {
    2676             :     DCHECK_EQ(c, &control_.back());
    2677             :     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
    2678     1561002 :     stack_.erase(stack_.begin() + c->stack_depth, stack_.end());
    2679      780518 :     if (merge->arity == 1) {
    2680       20554 :       stack_.push_back(merge->vals.first);
    2681             :     } else {
    2682         302 :       for (uint32_t i = 0; i < merge->arity; i++) {
    2683         302 :         stack_.push_back(merge->vals.array[i]);
    2684             :       }
    2685             :     }
    2686             :     DCHECK_EQ(c->stack_depth + merge->arity, stack_.size());
    2687      780518 :   }
    2688             : 
    2689      522436 :   Value* PushReturns(FunctionSig* sig) {
    2690             :     size_t return_count = sig->return_count();
    2691      273876 :     if (return_count == 0) return nullptr;
    2692      245595 :     size_t old_size = stack_.size();
    2693      494155 :     for (size_t i = 0; i < return_count; ++i) {
    2694             :       Push(sig->GetReturn(i));
    2695             :     }
    2696      245595 :     return stack_.data() + old_size;
    2697             :   }
    2698             : 
    2699             :   V8_INLINE bool IsSubType(ValueType expected, ValueType actual) {
    2700             :     return (expected == actual) ||
    2701             :            (expected == kWasmAnyRef && actual == kWasmNullRef) ||
    2702             :            (expected == kWasmAnyRef && actual == kWasmAnyFunc) ||
    2703     7276117 :            (expected == kWasmAnyFunc && actual == kWasmNullRef);
    2704             :   }
    2705             : 
    2706             :   V8_INLINE Value Pop(int index, ValueType expected) {
    2707             :     auto val = Pop();
    2708     8312350 :     if (!VALIDATE(IsSubType(expected, val.type) || val.type == kWasmVar ||
    2709             :                   expected == kWasmVar)) {
    2710       33340 :       this->errorf(val.pc, "%s[%d] expected type %s, found %s of type %s",
    2711             :                    SafeOpcodeNameAt(this->pc_), index,
    2712             :                    ValueTypes::TypeName(expected), SafeOpcodeNameAt(val.pc),
    2713             :                    ValueTypes::TypeName(val.type));
    2714             :     }
    2715             :     return val;
    2716             :   }
    2717             : 
    2718             :   V8_INLINE Value Pop() {
    2719             :     DCHECK(!control_.empty());
    2720     6371636 :     uint32_t limit = control_.back().stack_depth;
    2721     6371651 :     if (stack_.size() <= limit) {
    2722             :       // Popping past the current control start in reachable code.
    2723       12930 :       if (!VALIDATE(control_.back().unreachable())) {
    2724        4752 :         this->errorf(this->pc_, "%s found empty stack",
    2725             :                      SafeOpcodeNameAt(this->pc_));
    2726             :       }
    2727       12931 :       return UnreachableValue(this->pc_);
    2728             :     }
    2729     6358734 :     auto val = stack_.back();
    2730     6358685 :     stack_.pop_back();
    2731     2124161 :     return val;
    2732             :   }
    2733             : 
    2734        4665 :   int startrel(const byte* ptr) { return static_cast<int>(ptr - this->start_); }
    2735             : 
    2736         542 :   void FallThruTo(Control* c) {
    2737             :     DCHECK_EQ(c, &control_.back());
    2738         530 :     if (!TypeCheckFallThru(c)) return;
    2739         532 :     if (!c->reachable()) return;
    2740             : 
    2741         320 :     if (!c->is_loop()) CALL_INTERFACE(FallThruTo, c);
    2742         332 :     c->end_merge.reached = true;
    2743             :   }
    2744             : 
    2745      997021 :   bool TypeCheckMergeValues(Control* c, Merge<Value>* merge) {
    2746             :     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
    2747             :     DCHECK_GE(stack_.size(), c->stack_depth + merge->arity);
    2748             :     // The computation of {stack_values} is only valid if {merge->arity} is >0.
    2749             :     DCHECK_LT(0, merge->arity);
    2750      997021 :     Value* stack_values = &*(stack_.end() - merge->arity);
    2751             :     // Typecheck the topmost {merge->arity} values on the stack.
    2752     1030555 :     for (uint32_t i = 0; i < merge->arity; ++i) {
    2753      999661 :       Value& val = stack_values[i];
    2754             :       Value& old = (*merge)[i];
    2755     1999322 :       if (IsSubType(old.type, val.type)) continue;
    2756             :       // If {val.type} is polymorphic, which results from unreachable, make
    2757             :       // it more specific by using the merge value's expected type.
    2758             :       // If it is not polymorphic, this is a type error.
    2759       28455 :       if (!VALIDATE(val.type == kWasmVar)) {
    2760        4238 :         this->errorf(this->pc_, "type error in merge[%u] (expected %s, got %s)",
    2761             :                      i, ValueTypes::TypeName(old.type),
    2762             :                      ValueTypes::TypeName(val.type));
    2763        2498 :         return false;
    2764             :       }
    2765       24217 :       val.type = old.type;
    2766             :     }
    2767             : 
    2768             :     return true;
    2769             :   }
    2770             : 
    2771     1613294 :   bool TypeCheckFallThru(Control* c) {
    2772             :     DCHECK_EQ(c, &control_.back());
    2773             :     if (!validate) return true;
    2774     1609769 :     uint32_t expected = c->end_merge.arity;
    2775             :     DCHECK_GE(stack_.size(), c->stack_depth);
    2776     3219538 :     uint32_t actual = static_cast<uint32_t>(stack_.size()) - c->stack_depth;
    2777             :     // Fallthrus must match the arity of the control exactly.
    2778     1609769 :     if (!InsertUnreachablesIfNecessary(expected, actual) || actual > expected) {
    2779        7050 :       this->errorf(
    2780             :           this->pc_,
    2781             :           "expected %u elements on the stack for fallthru to @%d, found %u",
    2782             :           expected, startrel(c->pc), actual);
    2783        3525 :       return false;
    2784             :     }
    2785     1606498 :     if (expected == 0) return true;  // Fast path.
    2786             : 
    2787      985737 :     return TypeCheckMergeValues(c, &c->end_merge);
    2788             :   }
    2789             : 
    2790      300223 :   bool TypeCheckBranch(Control* c) {
    2791             :     // Branches must have at least the number of values expected; can have more.
    2792      299083 :     uint32_t expected = c->br_merge()->arity;
    2793      299083 :     if (expected == 0) return true;  // Fast path.
    2794             :     DCHECK_GE(stack_.size(), control_.back().stack_depth);
    2795             :     uint32_t actual =
    2796       37497 :         static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth;
    2797       12499 :     if (!InsertUnreachablesIfNecessary(expected, actual)) {
    2798        2280 :       this->errorf(this->pc_,
    2799             :                    "expected %u elements on the stack for br to @%d, found %u",
    2800             :                    expected, startrel(c->pc), actual);
    2801        1140 :       return false;
    2802             :     }
    2803       11359 :     return TypeCheckMergeValues(c, c->br_merge());
    2804             :   }
    2805             : 
    2806      321014 :   bool TypeCheckReturn() {
    2807             :     // Returns must have at least the number of values expected; can have more.
    2808      411229 :     uint32_t num_returns = static_cast<uint32_t>(this->sig_->return_count());
    2809             :     DCHECK_GE(stack_.size(), control_.back().stack_depth);
    2810             :     uint32_t actual =
    2811      963042 :         static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth;
    2812      321014 :     if (!InsertUnreachablesIfNecessary(num_returns, actual)) {
    2813         285 :       this->errorf(this->pc_,
    2814             :                    "expected %u elements on the stack for return, found %u",
    2815             :                    num_returns, actual);
    2816         285 :       return false;
    2817             :     }
    2818             : 
    2819             :     // Typecheck the topmost {num_returns} values on the stack.
    2820      320746 :     if (num_returns == 0) return true;
    2821             :     // This line requires num_returns > 0.
    2822             :     Value* stack_values = &*(stack_.end() - num_returns);
    2823      180265 :     for (uint32_t i = 0; i < num_returns; ++i) {
    2824       90215 :       auto& val = stack_values[i];
    2825       90215 :       ValueType expected_type = this->sig_->GetReturn(i);
    2826      180430 :       if (IsSubType(expected_type, val.type)) continue;
    2827             :       // If {val.type} is polymorphic, which results from unreachable,
    2828             :       // make it more specific by using the return's expected type.
    2829             :       // If it is not polymorphic, this is a type error.
    2830         237 :       if (!VALIDATE(val.type == kWasmVar)) {
    2831         141 :         this->errorf(this->pc_,
    2832             :                      "type error in return[%u] (expected %s, got %s)", i,
    2833             :                      ValueTypes::TypeName(expected_type),
    2834             :                      ValueTypes::TypeName(val.type));
    2835         145 :         return false;
    2836             :       }
    2837          96 :       val.type = expected_type;
    2838             :     }
    2839             :     return true;
    2840             :   }
    2841             : 
    2842     1943297 :   inline bool InsertUnreachablesIfNecessary(uint32_t expected,
    2843             :                                             uint32_t actual) {
    2844     1943297 :     if (V8_LIKELY(actual >= expected)) {
    2845             :       return true;  // enough actual values are there.
    2846             :     }
    2847       26368 :     if (!VALIDATE(control_.back().unreachable())) {
    2848             :       // There aren't enough values on the stack.
    2849             :       return false;
    2850             :     }
    2851             :     // A slow path. When the actual number of values on the stack is less
    2852             :     // than the expected number of values and the current control is
    2853             :     // unreachable, insert unreachable values below the actual values.
    2854             :     // This simplifies {TypeCheckMergeValues}.
    2855       46868 :     auto pos = stack_.begin() + (stack_.size() - actual);
    2856       66179 :     stack_.insert(pos, expected - actual, UnreachableValue(this->pc_));
    2857       23441 :     return true;
    2858             :   }
    2859             : 
    2860       55900 :   void onFirstError() override {
    2861       55900 :     this->end_ = this->pc_;  // Terminate decoding loop.
    2862             :     TRACE(" !%s\n", this->error_.message().c_str());
    2863             :     CALL_INTERFACE(OnFirstError);
    2864       55900 :   }
    2865             : 
    2866          88 :   void BuildSimplePrototypeOperator(WasmOpcode opcode) {
    2867          88 :     if (WasmOpcodes::IsSignExtensionOpcode(opcode)) {
    2868          56 :       RET_ON_PROTOTYPE_OPCODE(se);
    2869             :     }
    2870          88 :     if (WasmOpcodes::IsAnyRefOpcode(opcode)) {
    2871          32 :       RET_ON_PROTOTYPE_OPCODE(anyref);
    2872             :     }
    2873          88 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2874          88 :     BuildSimpleOperator(opcode, sig);
    2875          88 :   }
    2876             : 
    2877      444157 :   void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
    2878      100344 :     switch (sig->parameter_count()) {
    2879             :       case 1: {
    2880             :         auto val = Pop(0, sig->GetParam(0));
    2881             :         auto* ret =
    2882      114555 :             sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
    2883      114176 :         CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, val, ret);
    2884             :         break;
    2885             :       }
    2886             :       case 2: {
    2887             :         auto rval = Pop(1, sig->GetParam(1));
    2888             :         auto lval = Pop(0, sig->GetParam(0));
    2889             :         auto* ret =
    2890       83962 :             sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
    2891       82562 :         CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, lval, rval, ret);
    2892             :         break;
    2893             :       }
    2894             :       default:
    2895           0 :         UNREACHABLE();
    2896             :     }
    2897      100344 :   }
    2898             : 
    2899      490829 :   void BuildSimpleOperator(WasmOpcode opcode, ValueType return_type,
    2900             :                            ValueType arg_type) {
    2901             :     auto val = Pop(0, arg_type);
    2902      543958 :     auto* ret = return_type == kWasmStmt ? nullptr : Push(return_type);
    2903      557226 :     CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, val, ret);
    2904      490806 :   }
    2905             : 
    2906     1619660 :   void BuildSimpleOperator(WasmOpcode opcode, ValueType return_type,
    2907             :                            ValueType lhs_type, ValueType rhs_type) {
    2908             :     auto rval = Pop(1, rhs_type);
    2909             :     auto lval = Pop(0, lhs_type);
    2910     2330682 :     auto* ret = return_type == kWasmStmt ? nullptr : Push(return_type);
    2911     2950999 :     CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, lval, rval, ret);
    2912     1619623 :   }
    2913             : 
    2914             : #define DEFINE_SIMPLE_SIG_OPERATOR(sig, ...)          \
    2915             :   void BuildSimpleOperator_##sig(WasmOpcode opcode) { \
    2916             :     BuildSimpleOperator(opcode, __VA_ARGS__);         \
    2917             :   }
    2918      221021 :   FOREACH_SIGNATURE(DEFINE_SIMPLE_SIG_OPERATOR)
    2919             : #undef DEFINE_SIMPLE_SIG_OPERATOR
    2920             : };
    2921             : 
    2922             : #undef CALL_INTERFACE
    2923             : #undef CALL_INTERFACE_IF_REACHABLE
    2924             : #undef CALL_INTERFACE_IF_PARENT_REACHABLE
    2925             : 
    2926             : class EmptyInterface {
    2927             :  public:
    2928             :   static constexpr Decoder::ValidateFlag validate = Decoder::kValidate;
    2929             :   using Value = ValueBase;
    2930             :   using Control = ControlBase<Value>;
    2931             :   using FullDecoder = WasmFullDecoder<validate, EmptyInterface>;
    2932             : 
    2933             : #define DEFINE_EMPTY_CALLBACK(name, ...) \
    2934             :   void name(FullDecoder* decoder, ##__VA_ARGS__) {}
    2935             :   INTERFACE_FUNCTIONS(DEFINE_EMPTY_CALLBACK)
    2936             : #undef DEFINE_EMPTY_CALLBACK
    2937             : };
    2938             : 
    2939             : #undef TRACE
    2940             : #undef TRACE_INST_FORMAT
    2941             : #undef VALIDATE
    2942             : #undef CHECK_PROTOTYPE_OPCODE
    2943             : #undef OPCODE_ERROR
    2944             : 
    2945             : }  // namespace wasm
    2946             : }  // namespace internal
    2947             : }  // namespace v8
    2948             : 
    2949             : #endif  // V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_

Generated by: LCOV version 1.10