LCOV - code coverage report
Current view: top level - src/wasm - function-body-decoder-impl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 931 987 94.3 %
Date: 2019-01-20 Functions: 165 202 81.7 %

          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    30298801 :   inline LocalIndexImmediate(Decoder* decoder, const byte* pc) {
     141    60597623 :     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        1118 :   inline ExceptionIndexImmediate(Decoder* decoder, const byte* pc) {
     152        2237 :     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    30940169 :     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      240889 :     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      705549 :   inline ImmF32Immediate(Decoder* decoder, const byte* pc) {
     179             :     // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
     180     1411097 :     uint32_t tmp = decoder->read_u32<validate>(pc + 1, "immf32");
     181      705548 :     memcpy(&value, &tmp, sizeof(value));
     182      705548 :   }
     183             : };
     184             : 
     185             : template <Decoder::ValidateFlag validate>
     186             : struct ImmF64Immediate {
     187             :   double value;
     188             :   uint32_t length = 8;
     189      278549 :   inline ImmF64Immediate(Decoder* decoder, const byte* pc) {
     190             :     // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
     191      557098 :     uint64_t tmp = decoder->read_u64<validate>(pc + 1, "immf64");
     192      278549 :     memcpy(&value, &tmp, sizeof(value));
     193      278549 :   }
     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      142046 :   inline GlobalIndexImmediate(Decoder* decoder, const byte* pc) {
     204      284092 :     index = decoder->read_u32v<validate>(pc + 1, &length, "global index");
     205       93644 :   }
     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     6116152 :   inline BlockTypeImmediate(const WasmFeatures& enabled, Decoder* decoder,
     216     6116152 :                             const byte* pc) {
     217     6116152 :     uint8_t val = decoder->read_u8<validate>(pc + 1, "block type");
     218     6116156 :     if (!decode_local_type(val, &type)) {
     219             :       // Handle multi-value blocks.
     220         320 :       if (!VALIDATE(enabled.mv)) {
     221          53 :         decoder->error(pc + 1, "invalid block type");
     222          53 :         return;
     223             :       }
     224         267 :       if (!VALIDATE(decoder->ok())) return;
     225             :       int32_t index =
     226       50739 :           decoder->read_i32v<validate>(pc + 1, &length, "block arity");
     227         249 :       if (!VALIDATE(length > 0 && index >= 0)) {
     228           0 :         decoder->error(pc + 1, "invalid block type index");
     229           0 :         return;
     230             :       }
     231       50739 :       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     6116164 :   inline bool decode_local_type(uint8_t val, ValueType* result) {
     238     6116164 :     switch (static_cast<ValueTypeCode>(val)) {
     239             :       case kLocalVoid:
     240     6015963 :         *result = kWasmStmt;
     241             :         return true;
     242             :       case kLocalI32:
     243       41529 :         *result = kWasmI32;
     244             :         return true;
     245             :       case kLocalI64:
     246        1704 :         *result = kWasmI64;
     247             :         return true;
     248             :       case kLocalF32:
     249        3004 :         *result = kWasmF32;
     250             :         return true;
     251             :       case kLocalF64:
     252        3082 :         *result = kWasmF64;
     253             :         return true;
     254             :       case kLocalS128:
     255           9 :         *result = kWasmS128;
     256             :         return true;
     257             :       case kLocalAnyFunc:
     258           0 :         *result = kWasmAnyFunc;
     259             :         return true;
     260             :       case kLocalAnyRef:
     261          63 :         *result = kWasmAnyRef;
     262             :         return true;
     263             :       default:
     264       50810 :         *result = kWasmVar;
     265             :         return false;
     266             :     }
     267             :   }
     268             : 
     269             :   uint32_t in_arity() const {
     270      489541 :     if (type != kWasmVar) return 0;
     271         285 :     return static_cast<uint32_t>(sig->parameter_count());
     272             :   }
     273             :   uint32_t out_arity() const {
     274      566362 :     if (type == kWasmStmt) return 0;
     275       33785 :     if (type != kWasmVar) return 1;
     276         315 :     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       32786 :     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      863264 :     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       11758 :   inline CallIndirectImmediate(Decoder* decoder, const byte* pc) {
     306       11758 :     uint32_t len = 0;
     307       23516 :     sig_index = decoder->read_u32v<validate>(pc + 1, &len, "signature index");
     308       11759 :     if (!VALIDATE(decoder->ok())) return;
     309       22601 :     table_index = decoder->read_u8<validate>(pc + 1 + len, "table index");
     310       10844 :     if (!VALIDATE(table_index == 0)) {
     311         126 :       decoder->errorf(pc + 1 + len, "expected table index 0, found %u",
     312          63 :                       table_index);
     313             :     }
     314       11757 :     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      955820 :   inline CallFunctionImmediate(Decoder* decoder, const byte* pc) {
     324     1911633 :     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;
     331             :   uint32_t length = 1;
     332        4975 :   inline MemoryIndexImmediate(Decoder* decoder, const byte* pc) {
     333       10006 :     index = decoder->read_u8<validate>(pc + 1, "memory index");
     334        4975 :     if (!VALIDATE(index == 0)) {
     335         288 :       decoder->errorf(pc + 1, "expected memory index 0, found %u", index);
     336             :     }
     337        4975 :   }
     338             : };
     339             : 
     340             : template <Decoder::ValidateFlag validate>
     341             : struct TableIndexImmediate {
     342             :   uint32_t index;
     343             :   unsigned length = 1;
     344         145 :   inline TableIndexImmediate(Decoder* decoder, const byte* pc) {
     345         290 :     index = decoder->read_u8<validate>(pc + 1, "table index");
     346         145 :     if (!VALIDATE(index == 0)) {
     347           0 :       decoder->errorf(pc + 1, "expected table index 0, found %u", index);
     348             :     }
     349         145 :   }
     350             : };
     351             : 
     352             : template <Decoder::ValidateFlag validate>
     353             : struct BranchTableImmediate {
     354             :   uint32_t table_count;
     355             :   const byte* start;
     356             :   const byte* table;
     357      308828 :   inline BranchTableImmediate(Decoder* decoder, const byte* pc) {
     358             :     DCHECK_EQ(kExprBrTable, decoder->read_u8<validate>(pc, "opcode"));
     359      308828 :     start = pc + 1;
     360      308828 :     uint32_t len = 0;
     361      308828 :     table_count = decoder->read_u32v<validate>(pc + 1, &len, "table count");
     362      308828 :     table = pc + 1 + len;
     363      308828 :   }
     364             : };
     365             : 
     366             : // A helper to iterate over a branch table.
     367             : template <Decoder::ValidateFlag validate>
     368             : class BranchTableIterator {
     369             :  public:
     370             :   uint32_t cur_index() { return index_; }
     371     2161968 :   bool has_next() { return VALIDATE(decoder_->ok()) && index_ <= table_count_; }
     372     2359227 :   uint32_t next() {
     373             :     DCHECK(has_next());
     374     2359227 :     index_++;
     375             :     uint32_t length;
     376             :     uint32_t result =
     377     2359227 :         decoder_->read_u32v<validate>(pc_, &length, "branch table entry");
     378     2360868 :     pc_ += length;
     379     2360868 :     return result;
     380             :   }
     381             :   // length, including the length of the {BranchTableImmediate}, but not the
     382             :   // opcode.
     383       51693 :   uint32_t length() {
     384       72272 :     while (has_next()) next();
     385       25517 :     return static_cast<uint32_t>(pc_ - start_);
     386             :   }
     387             :   const byte* pc() { return pc_; }
     388             : 
     389             :   BranchTableIterator(Decoder* decoder,
     390             :                       const BranchTableImmediate<validate>& imm)
     391             :       : decoder_(decoder),
     392             :         start_(imm.start),
     393             :         pc_(imm.table),
     394      327069 :         table_count_(imm.table_count) {}
     395             : 
     396             :  private:
     397             :   Decoder* decoder_;
     398             :   const byte* start_;
     399             :   const byte* pc_;
     400             :   uint32_t index_ = 0;    // the current index.
     401             :   uint32_t table_count_;  // the count of entries, not including default.
     402             : };
     403             : 
     404             : template <Decoder::ValidateFlag validate>
     405             : struct MemoryAccessImmediate {
     406             :   uint32_t alignment;
     407             :   uint32_t offset;
     408             :   uint32_t length = 0;
     409     8613434 :   inline MemoryAccessImmediate(Decoder* decoder, const byte* pc,
     410     8613434 :                                uint32_t max_alignment) {
     411             :     uint32_t alignment_length;
     412    17226884 :     alignment =
     413             :         decoder->read_u32v<validate>(pc + 1, &alignment_length, "alignment");
     414      770877 :     if (!VALIDATE(alignment <= max_alignment)) {
     415        1055 :       decoder->errorf(pc + 1,
     416             :                       "invalid alignment; expected maximum alignment is %u, "
     417             :                       "actual alignment is %u",
     418             :                       max_alignment, alignment);
     419             :     }
     420     8614506 :     if (!VALIDATE(decoder->ok())) return;
     421             :     uint32_t offset_length;
     422    17224791 :     offset = decoder->read_u32v<validate>(pc + 1 + alignment_length,
     423             :                                           &offset_length, "offset");
     424     8612397 :     length = alignment_length + offset_length;
     425             :   }
     426             : };
     427             : 
     428             : // Immediate for SIMD lane operations.
     429             : template <Decoder::ValidateFlag validate>
     430             : struct SimdLaneImmediate {
     431             :   uint8_t lane;
     432             :   uint32_t length = 1;
     433             : 
     434       34880 :   inline SimdLaneImmediate(Decoder* decoder, const byte* pc) {
     435     4035195 :     lane = decoder->read_u8<validate>(pc + 2, "lane");
     436             :   }
     437             : };
     438             : 
     439             : // Immediate for SIMD shift operations.
     440             : template <Decoder::ValidateFlag validate>
     441             : struct SimdShiftImmediate {
     442             :   uint8_t shift;
     443             :   uint32_t length = 1;
     444             : 
     445        2385 :   inline SimdShiftImmediate(Decoder* decoder, const byte* pc) {
     446       34710 :     shift = decoder->read_u8<validate>(pc + 2, "shift");
     447             :   }
     448             : };
     449             : 
     450             : // Immediate for SIMD S8x16 shuffle operations.
     451             : template <Decoder::ValidateFlag validate>
     452             : struct Simd8x16ShuffleImmediate {
     453             :   uint8_t shuffle[kSimd128Size] = {0};
     454             : 
     455       49061 :   inline Simd8x16ShuffleImmediate(Decoder* decoder, const byte* pc) {
     456      818741 :     for (uint32_t i = 0; i < kSimd128Size; ++i) {
     457     1325442 :       shuffle[i] = decoder->read_u8<validate>(pc + 2 + i, "shuffle");
     458      574262 :       if (!VALIDATE(decoder->ok())) return;
     459             :     }
     460             :   }
     461             : };
     462             : 
     463             : template <Decoder::ValidateFlag validate>
     464             : struct MemoryInitImmediate {
     465             :   MemoryIndexImmediate<validate> memory;
     466             :   uint32_t data_segment_index = 0;
     467             :   unsigned length = 0;
     468             : 
     469          87 :   inline MemoryInitImmediate(Decoder* decoder, const byte* pc)
     470          87 :       : memory(decoder, pc + 1) {
     471          88 :     if (!VALIDATE(decoder->ok())) return;
     472          86 :     uint32_t len = 0;
     473         172 :     data_segment_index = decoder->read_i32v<validate>(
     474          86 :         pc + 2 + memory.length, &len, "data segment index");
     475          86 :     length = memory.length + len;
     476             :   }
     477             : };
     478             : 
     479             : template <Decoder::ValidateFlag validate>
     480             : struct MemoryDropImmediate {
     481             :   uint32_t index;
     482             :   unsigned length;
     483             : 
     484             :   inline MemoryDropImmediate(Decoder* decoder, const byte* pc) {
     485          94 :     index = decoder->read_i32v<validate>(pc + 2, &length, "data segment index");
     486             :   }
     487             : };
     488             : 
     489             : template <Decoder::ValidateFlag validate>
     490             : struct TableInitImmediate {
     491             :   TableIndexImmediate<validate> table;
     492             :   uint32_t elem_segment_index = 0;
     493             :   unsigned length = 0;
     494             : 
     495          26 :   inline TableInitImmediate(Decoder* decoder, const byte* pc)
     496          26 :       : table(decoder, pc + 1) {
     497          27 :     if (!VALIDATE(decoder->ok())) return;
     498          25 :     uint32_t len = 0;
     499          50 :     elem_segment_index = decoder->read_i32v<validate>(
     500          25 :         pc + 2 + table.length, &len, "elem segment index");
     501          25 :     length = table.length + len;
     502             :   }
     503             : };
     504             : 
     505             : template <Decoder::ValidateFlag validate>
     506             : struct TableDropImmediate {
     507             :   uint32_t index;
     508             :   unsigned length;
     509             : 
     510             :   inline TableDropImmediate(Decoder* decoder, const byte* pc) {
     511          78 :     index = decoder->read_i32v<validate>(pc + 2, &length, "elem segment index");
     512             :   }
     513             : };
     514             : 
     515             : // An entry on the value stack.
     516             : struct ValueBase {
     517             :   const byte* pc = nullptr;
     518             :   ValueType type = kWasmStmt;
     519             : 
     520    10887744 :   ValueBase(const byte* pc, ValueType type) : pc(pc), type(type) {}
     521             : };
     522             : 
     523             : template <typename Value>
     524             : struct Merge {
     525             :   uint32_t arity = 0;
     526             :   union {  // Either multiple values or a single value.
     527             :     Value* array;
     528             :     Value first;
     529             :   } vals = {nullptr};  // Initialize {array} with {nullptr}.
     530             : 
     531             :   // Tracks whether this merge was ever reached. Uses precise reachability, like
     532             :   // Reachability::kReachable.
     533             :   bool reached;
     534             : 
     535     2443372 :   Merge(bool reached = false) : reached(reached) {}
     536             : 
     537             :   Value& operator[](uint32_t i) {
     538             :     DCHECK_GT(arity, i);
     539     1694701 :     return arity == 1 ? vals.first : vals.array[i];
     540             :   }
     541             : };
     542             : 
     543             : enum ControlKind : uint8_t {
     544             :   kControlIf,
     545             :   kControlIfElse,
     546             :   kControlBlock,
     547             :   kControlLoop,
     548             :   kControlTry,
     549             :   kControlTryCatch
     550             : };
     551             : 
     552             : enum Reachability : uint8_t {
     553             :   // reachable code.
     554             :   kReachable,
     555             :   // reachable code in unreachable block (implies normal validation).
     556             :   kSpecOnlyReachable,
     557             :   // code unreachable in its own block (implies polymorphic validation).
     558             :   kUnreachable
     559             : };
     560             : 
     561             : // An entry on the control stack (i.e. if, block, loop, or try).
     562             : template <typename Value>
     563             : struct ControlBase {
     564             :   ControlKind kind = kControlBlock;
     565             :   uint32_t stack_depth = 0;  // stack height at the beginning of the construct.
     566             :   const uint8_t* pc = nullptr;
     567             :   Reachability reachability = kReachable;
     568             : 
     569             :   // Values merged into the start or end of this control construct.
     570             :   Merge<Value> start_merge;
     571             :   Merge<Value> end_merge;
     572             : 
     573             :   MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ControlBase);
     574             : 
     575             :   ControlBase(ControlKind kind, uint32_t stack_depth, const uint8_t* pc,
     576             :               Reachability reachability)
     577             :       : kind(kind),
     578             :         stack_depth(stack_depth),
     579             :         pc(pc),
     580             :         reachability(reachability),
     581     2443372 :         start_merge(reachability == kReachable) {}
     582             : 
     583             :   // Check whether the current block is reachable.
     584             :   bool reachable() const { return reachability == kReachable; }
     585             : 
     586             :   // Check whether the rest of the block is unreachable.
     587             :   // Note that this is different from {!reachable()}, as there is also the
     588             :   // "indirect unreachable state", for which both {reachable()} and
     589             :   // {unreachable()} return false.
     590       11976 :   bool unreachable() const { return reachability == kUnreachable; }
     591             : 
     592             :   // Return the reachability of new control structs started in this block.
     593             :   Reachability innerReachability() const {
     594      514454 :     return reachability == kReachable ? kReachable : kSpecOnlyReachable;
     595             :   }
     596             : 
     597       24841 :   bool is_if() const { return is_onearmed_if() || is_if_else(); }
     598             :   bool is_onearmed_if() const { return kind == kControlIf; }
     599             :   bool is_if_else() const { return kind == kControlIfElse; }
     600             :   bool is_block() const { return kind == kControlBlock; }
     601             :   bool is_loop() const { return kind == kControlLoop; }
     602             :   bool is_incomplete_try() const { return kind == kControlTry; }
     603             :   bool is_try_catch() const { return kind == kControlTryCatch; }
     604         517 :   bool is_try() const { return is_incomplete_try() || is_try_catch(); }
     605             : 
     606     1372103 :   inline Merge<Value>* br_merge() {
     607     1508860 :     return is_loop() ? &this->start_merge : &this->end_merge;
     608             :   }
     609             : };
     610             : 
     611             : // This is the list of callback functions that an interface for the
     612             : // WasmFullDecoder should implement.
     613             : // F(Name, args...)
     614             : #define INTERFACE_FUNCTIONS(F)                                                \
     615             :   /* General: */                                                              \
     616             :   F(StartFunction)                                                            \
     617             :   F(StartFunctionBody, Control* block)                                        \
     618             :   F(FinishFunction)                                                           \
     619             :   F(OnFirstError)                                                             \
     620             :   F(NextInstruction, WasmOpcode)                                              \
     621             :   /* Control: */                                                              \
     622             :   F(Block, Control* block)                                                    \
     623             :   F(Loop, Control* block)                                                     \
     624             :   F(Try, Control* block)                                                      \
     625             :   F(Catch, Control* block, Value* exception)                                  \
     626             :   F(If, const Value& cond, Control* if_block)                                 \
     627             :   F(FallThruTo, Control* c)                                                   \
     628             :   F(PopControl, Control* block)                                               \
     629             :   F(EndControl, Control* block)                                               \
     630             :   /* Instructions: */                                                         \
     631             :   F(UnOp, WasmOpcode opcode, const Value& value, Value* result)               \
     632             :   F(BinOp, WasmOpcode opcode, const Value& lhs, const Value& rhs,             \
     633             :     Value* result)                                                            \
     634             :   F(I32Const, Value* result, int32_t value)                                   \
     635             :   F(I64Const, Value* result, int64_t value)                                   \
     636             :   F(F32Const, Value* result, float value)                                     \
     637             :   F(F64Const, Value* result, double value)                                    \
     638             :   F(RefNull, Value* result)                                                   \
     639             :   F(Drop, const Value& value)                                                 \
     640             :   F(DoReturn, Vector<Value> values)                                           \
     641             :   F(GetLocal, Value* result, const LocalIndexImmediate<validate>& imm)        \
     642             :   F(SetLocal, const Value& value, const LocalIndexImmediate<validate>& imm)   \
     643             :   F(TeeLocal, const Value& value, Value* result,                              \
     644             :     const LocalIndexImmediate<validate>& imm)                                 \
     645             :   F(GetGlobal, Value* result, const GlobalIndexImmediate<validate>& imm)      \
     646             :   F(SetGlobal, const Value& value, const GlobalIndexImmediate<validate>& imm) \
     647             :   F(Unreachable)                                                              \
     648             :   F(Select, const Value& cond, const Value& fval, const Value& tval,          \
     649             :     Value* result)                                                            \
     650             :   F(Br, Control* target)                                                      \
     651             :   F(BrIf, const Value& cond, uint32_t depth)                                  \
     652             :   F(BrTable, const BranchTableImmediate<validate>& imm, const Value& key)     \
     653             :   F(Else, Control* if_block)                                                  \
     654             :   F(LoadMem, LoadType type, const MemoryAccessImmediate<validate>& imm,       \
     655             :     const Value& index, Value* result)                                        \
     656             :   F(StoreMem, StoreType type, const MemoryAccessImmediate<validate>& imm,     \
     657             :     const Value& index, const Value& value)                                   \
     658             :   F(CurrentMemoryPages, Value* result)                                        \
     659             :   F(MemoryGrow, const Value& value, Value* result)                            \
     660             :   F(CallDirect, const CallFunctionImmediate<validate>& imm,                   \
     661             :     const Value args[], Value returns[])                                      \
     662             :   F(CallIndirect, const Value& index,                                         \
     663             :     const CallIndirectImmediate<validate>& imm, const Value args[],           \
     664             :     Value returns[])                                                          \
     665             :   F(SimdOp, WasmOpcode opcode, Vector<Value> args, Value* result)             \
     666             :   F(SimdLaneOp, WasmOpcode opcode, const SimdLaneImmediate<validate>& imm,    \
     667             :     const Vector<Value> inputs, Value* result)                                \
     668             :   F(SimdShiftOp, WasmOpcode opcode, const SimdShiftImmediate<validate>& imm,  \
     669             :     const Value& input, Value* result)                                        \
     670             :   F(Simd8x16ShuffleOp, const Simd8x16ShuffleImmediate<validate>& imm,         \
     671             :     const Value& input0, const Value& input1, Value* result)                  \
     672             :   F(Throw, const ExceptionIndexImmediate<validate>& imm,                      \
     673             :     const Vector<Value>& args)                                                \
     674             :   F(Rethrow, const Value& exception)                                          \
     675             :   F(BrOnException, const Value& exception,                                    \
     676             :     const ExceptionIndexImmediate<validate>& imm, uint32_t depth,             \
     677             :     Vector<Value> values)                                                     \
     678             :   F(AtomicOp, WasmOpcode opcode, Vector<Value> args,                          \
     679             :     const MemoryAccessImmediate<validate>& imm, Value* result)                \
     680             :   F(MemoryInit, const MemoryInitImmediate<validate>& imm, const Value& dst,   \
     681             :     const Value& src, const Value& size)                                      \
     682             :   F(MemoryDrop, const MemoryDropImmediate<validate>& imm)                     \
     683             :   F(MemoryCopy, const MemoryIndexImmediate<validate>& imm, const Value& dst,  \
     684             :     const Value& src, const Value& size)                                      \
     685             :   F(MemoryFill, const MemoryIndexImmediate<validate>& imm, const Value& dst,  \
     686             :     const Value& value, const Value& size)                                    \
     687             :   F(TableInit, const TableInitImmediate<validate>& imm, Vector<Value> args)   \
     688             :   F(TableDrop, const TableDropImmediate<validate>& imm)                       \
     689             :   F(TableCopy, const TableIndexImmediate<validate>& imm, Vector<Value> args)
     690             : 
     691             : // Generic Wasm bytecode decoder with utilities for decoding immediates,
     692             : // lengths, etc.
     693             : template <Decoder::ValidateFlag validate>
     694     4832776 : class WasmDecoder : public Decoder {
     695             :  public:
     696             :   WasmDecoder(const WasmModule* module, const WasmFeatures& enabled,
     697             :               WasmFeatures* detected, FunctionSig* sig, const byte* start,
     698             :               const byte* end, uint32_t buffer_offset = 0)
     699             :       : Decoder(start, end, buffer_offset),
     700             :         module_(module),
     701             :         enabled_(enabled),
     702             :         detected_(detected),
     703             :         sig_(sig),
     704     4832739 :         local_types_(nullptr) {}
     705             :   const WasmModule* module_;
     706             :   const WasmFeatures enabled_;
     707             :   WasmFeatures* detected_;
     708             :   FunctionSig* sig_;
     709             : 
     710             :   ZoneVector<ValueType>* local_types_;
     711             : 
     712             :   uint32_t total_locals() const {
     713             :     return local_types_ == nullptr
     714             :                ? 0
     715     3926266 :                : static_cast<uint32_t>(local_types_->size());
     716             :   }
     717             : 
     718     2488916 :   static bool DecodeLocals(const WasmFeatures& enabled, Decoder* decoder,
     719             :                            const FunctionSig* sig,
     720             :                            ZoneVector<ValueType>* type_list) {
     721             :     DCHECK_NOT_NULL(type_list);
     722             :     DCHECK_EQ(0, type_list->size());
     723             :     // Initialize from signature.
     724     2412563 :     if (sig != nullptr) {
     725     2030389 :       type_list->assign(sig->parameters().begin(), sig->parameters().end());
     726             :     }
     727             :     // Decode local declarations, if any.
     728             :     uint32_t entries = decoder->consume_u32v("local decls count");
     729     2412705 :     if (decoder->failed()) return false;
     730             : 
     731             :     TRACE("local decls count: %u\n", entries);
     732     2641415 :     while (entries-- > 0 && VALIDATE(decoder->ok()) && decoder->more()) {
     733             :       uint32_t count = decoder->consume_u32v("local count");
     734       76349 :       if (decoder->failed()) return false;
     735             : 
     736             :       DCHECK_LE(type_list->size(), kV8MaxWasmFunctionLocals);
     737      152524 :       if (count > kV8MaxWasmFunctionLocals - type_list->size()) {
     738          48 :         decoder->error(decoder->pc() - 1, "local count too large");
     739          48 :         return false;
     740             :       }
     741             :       byte code = decoder->consume_u8("local type");
     742       76214 :       if (decoder->failed()) return false;
     743             : 
     744             :       ValueType type;
     745       76214 :       switch (code) {
     746             :         case kLocalI32:
     747       35915 :           type = kWasmI32;
     748       35915 :           break;
     749             :         case kLocalI64:
     750       30490 :           type = kWasmI64;
     751       30490 :           break;
     752             :         case kLocalF32:
     753        1626 :           type = kWasmF32;
     754        1626 :           break;
     755             :         case kLocalF64:
     756        2647 :           type = kWasmF64;
     757        2647 :           break;
     758             :         case kLocalAnyRef:
     759          38 :           if (enabled.anyref) {
     760          38 :             type = kWasmAnyRef;
     761          38 :             break;
     762             :           }
     763           0 :           decoder->error(decoder->pc() - 1, "invalid local type");
     764           0 :           return false;
     765             :         case kLocalExceptRef:
     766         145 :           if (enabled.eh) {
     767         145 :             type = kWasmExceptRef;
     768         145 :             break;
     769             :           }
     770           0 :           decoder->error(decoder->pc() - 1, "invalid local type");
     771           0 :           return false;
     772             :         case kLocalS128:
     773        5320 :           if (enabled.simd) {
     774        5311 :             type = kWasmS128;
     775        5311 :             break;
     776             :           }
     777             :           V8_FALLTHROUGH;
     778             :         default:
     779          42 :           decoder->error(decoder->pc() - 1, "invalid local type");
     780          39 :           return false;
     781             :       }
     782       76172 :       type_list->insert(type_list->end(), count, type);
     783             :     }
     784             :     DCHECK(decoder->ok());
     785             :     return true;
     786             :   }
     787             : 
     788     1879491 :   static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc,
     789             :                                           uint32_t locals_count, Zone* zone) {
     790       10751 :     if (pc >= decoder->end()) return nullptr;
     791       10750 :     if (*pc != kExprLoop) return nullptr;
     792             : 
     793             :     // The number of locals_count is augmented by 2 so that 'locals_count - 2'
     794             :     // can be used to track mem_size, and 'locals_count - 1' to track mem_start.
     795      143150 :     BitVector* assigned = new (zone) BitVector(locals_count, zone);
     796             :     int depth = 0;
     797             :     // Iteratively process all AST nodes nested inside the loop.
     798     3748211 :     while (pc < decoder->end() && VALIDATE(decoder->ok())) {
     799     1868727 :       WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
     800             :       uint32_t length = 1;
     801     1868727 :       switch (opcode) {
     802             :         case kExprLoop:
     803             :         case kExprIf:
     804             :         case kExprBlock:
     805             :         case kExprTry:
     806       98008 :           length = OpcodeLength(decoder, pc);
     807       98013 :           depth++;
     808       98013 :           break;
     809             :         case kExprSetLocal:  // fallthru
     810             :         case kExprTeeLocal: {
     811             :           LocalIndexImmediate<validate> imm(decoder, pc);
     812      132399 :           if (assigned->length() > 0 &&
     813             :               imm.index < static_cast<uint32_t>(assigned->length())) {
     814             :             // Unverified code might have an out-of-bounds index.
     815      132397 :             assigned->Add(imm.index);
     816             :           }
     817      132399 :           length = 1 + imm.length;
     818             :           break;
     819             :         }
     820             :         case kExprMemoryGrow:
     821             :         case kExprCallFunction:
     822             :         case kExprCallIndirect:
     823             :           // Add instance cache nodes to the assigned set.
     824             :           // TODO(titzer): make this more clear.
     825       20966 :           assigned->Add(locals_count - 1);
     826       20966 :           length = OpcodeLength(decoder, pc);
     827       20966 :           break;
     828             :         case kExprEnd:
     829       97999 :           depth--;
     830       97999 :           break;
     831             :         default:
     832     1519355 :           length = OpcodeLength(decoder, pc);
     833     1519362 :           break;
     834             :       }
     835     1868739 :       if (depth <= 0) break;
     836     1857997 :       pc += length;
     837             :     }
     838       10755 :     return VALIDATE(decoder->ok()) ? assigned : nullptr;
     839             :   }
     840             : 
     841     3883648 :   inline bool Validate(const byte* pc, LocalIndexImmediate<validate>& imm) {
     842     3883648 :     if (!VALIDATE(imm.index < total_locals())) {
     843         563 :       errorf(pc + 1, "invalid local index: %u", imm.index);
     844         563 :       return false;
     845             :     }
     846     3882494 :     imm.type = local_types_ ? local_types_->at(imm.index) : kWasmStmt;
     847     1941261 :     return true;
     848             :   }
     849             : 
     850        1117 :   inline bool Validate(const byte* pc, ExceptionIndexImmediate<validate>& imm) {
     851        3350 :     if (!VALIDATE(module_ != nullptr &&
     852             :                   imm.index < module_->exceptions.size())) {
     853           1 :       errorf(pc + 1, "Invalid exception index: %u", imm.index);
     854             :       return false;
     855             :     }
     856        2232 :     imm.exception = &module_->exceptions[imm.index];
     857             :     return true;
     858             :   }
     859             : 
     860       89250 :   inline bool Validate(const byte* pc, GlobalIndexImmediate<validate>& imm) {
     861      267722 :     if (!VALIDATE(module_ != nullptr && imm.index < module_->globals.size())) {
     862          27 :       errorf(pc + 1, "invalid global index: %u", imm.index);
     863          27 :       return false;
     864             :     }
     865      178446 :     imm.global = &module_->globals[imm.index];
     866       89223 :     imm.type = imm.global->type;
     867       89223 :     return true;
     868             :   }
     869             : 
     870             :   inline bool Complete(const byte* pc, CallFunctionImmediate<validate>& imm) {
     871      905010 :     if (!VALIDATE(module_ != nullptr &&
     872             :                   imm.index < module_->functions.size())) {
     873             :       return false;
     874             :     }
     875      608986 :     imm.sig = module_->functions[imm.index].sig;
     876             :     return true;
     877             :   }
     878             : 
     879      301690 :   inline bool Validate(const byte* pc, CallFunctionImmediate<validate>& imm) {
     880      301690 :     if (Complete(pc, imm)) {
     881             :       return true;
     882             :     }
     883          81 :     errorf(pc + 1, "invalid function index: %u", imm.index);
     884          81 :     return false;
     885             :   }
     886             : 
     887             :   inline bool Complete(const byte* pc, CallIndirectImmediate<validate>& imm) {
     888       29065 :     if (!VALIDATE(module_ != nullptr &&
     889             :                   imm.sig_index < module_->signatures.size())) {
     890             :       return false;
     891             :     }
     892       19866 :     imm.sig = module_->signatures[imm.sig_index];
     893             :     return true;
     894             :   }
     895             : 
     896        9740 :   inline bool Validate(const byte* pc, CallIndirectImmediate<validate>& imm) {
     897       19480 :     if (!VALIDATE(module_ != nullptr && !module_->tables.empty())) {
     898          30 :       error("function table has to exist to execute call_indirect");
     899          30 :       return false;
     900             :     }
     901        9710 :     if (!Complete(pc, imm)) {
     902          67 :       errorf(pc + 1, "invalid signature index: #%u", imm.sig_index);
     903          67 :       return false;
     904             :     }
     905             :     return true;
     906             :   }
     907             : 
     908             :   inline bool Validate(const byte* pc, BranchDepthImmediate<validate>& imm,
     909             :                        size_t control_depth) {
     910      307470 :     if (!VALIDATE(imm.depth < control_depth)) {
     911         651 :       errorf(pc + 1, "invalid branch depth: %u", imm.depth);
     912             :       return false;
     913             :     }
     914             :     return true;
     915             :   }
     916             : 
     917       20648 :   bool Validate(const byte* pc, BranchTableImmediate<validate>& imm,
     918             :                 size_t block_depth) {
     919       20648 :     if (!VALIDATE(imm.table_count < kV8MaxWasmFunctionSize)) {
     920          18 :       errorf(pc + 1, "invalid table count (> max function size): %u",
     921             :              imm.table_count);
     922             :       return false;
     923             :     }
     924       20630 :     return checkAvailable(imm.table_count);
     925             :   }
     926             : 
     927       34880 :   inline bool Validate(const byte* pc, WasmOpcode opcode,
     928             :                        SimdLaneImmediate<validate>& imm) {
     929             :     uint8_t num_lanes = 0;
     930       34880 :     switch (opcode) {
     931             :       case kExprF32x4ExtractLane:
     932             :       case kExprF32x4ReplaceLane:
     933             :       case kExprI32x4ExtractLane:
     934             :       case kExprI32x4ReplaceLane:
     935             :         num_lanes = 4;
     936             :         break;
     937             :       case kExprI16x8ExtractLane:
     938             :       case kExprI16x8ReplaceLane:
     939             :         num_lanes = 8;
     940             :         break;
     941             :       case kExprI8x16ExtractLane:
     942             :       case kExprI8x16ReplaceLane:
     943             :         num_lanes = 16;
     944             :         break;
     945             :       default:
     946           0 :         UNREACHABLE();
     947             :         break;
     948             :     }
     949       34880 :     if (!VALIDATE(imm.lane >= 0 && imm.lane < num_lanes)) {
     950           0 :       error(pc_ + 2, "invalid lane index");
     951             :       return false;
     952             :     } else {
     953             :       return true;
     954             :     }
     955             :   }
     956             : 
     957        2385 :   inline bool Validate(const byte* pc, WasmOpcode opcode,
     958             :                        SimdShiftImmediate<validate>& imm) {
     959             :     uint8_t max_shift = 0;
     960        2385 :     switch (opcode) {
     961             :       case kExprI32x4Shl:
     962             :       case kExprI32x4ShrS:
     963             :       case kExprI32x4ShrU:
     964             :         max_shift = 32;
     965             :         break;
     966             :       case kExprI16x8Shl:
     967             :       case kExprI16x8ShrS:
     968             :       case kExprI16x8ShrU:
     969             :         max_shift = 16;
     970             :         break;
     971             :       case kExprI8x16Shl:
     972             :       case kExprI8x16ShrS:
     973             :       case kExprI8x16ShrU:
     974             :         max_shift = 8;
     975             :         break;
     976             :       default:
     977           0 :         UNREACHABLE();
     978             :         break;
     979             :     }
     980        2385 :     if (!VALIDATE(imm.shift >= 0 && imm.shift < max_shift)) {
     981           0 :       error(pc_ + 2, "invalid shift amount");
     982             :       return false;
     983             :     } else {
     984             :       return true;
     985             :     }
     986             :   }
     987             : 
     988       33781 :   inline bool Validate(const byte* pc,
     989             :                        Simd8x16ShuffleImmediate<validate>& imm) {
     990       33781 :     uint8_t max_lane = 0;
     991      540496 :     for (uint32_t i = 0; i < kSimd128Size; ++i) {
     992     1080992 :       max_lane = std::max(max_lane, imm.shuffle[i]);
     993             :     }
     994             :     // Shuffle indices must be in [0..31] for a 16 lane shuffle.
     995       33781 :     if (!VALIDATE(max_lane <= 2 * kSimd128Size)) {
     996           0 :       error(pc_ + 2, "invalid shuffle mask");
     997             :       return false;
     998             :     }
     999             :     return true;
    1000             :   }
    1001             : 
    1002      489511 :   inline bool Complete(BlockTypeImmediate<validate>& imm) {
    1003      489511 :     if (imm.type != kWasmVar) return true;
    1004         872 :     if (!VALIDATE((module_ && imm.sig_index < module_->signatures.size()))) {
    1005             :       return false;
    1006             :     }
    1007         570 :     imm.sig = module_->signatures[imm.sig_index];
    1008             :     return true;
    1009             :   }
    1010             : 
    1011      489510 :   inline bool Validate(BlockTypeImmediate<validate>& imm) {
    1012      489510 :     if (!Complete(imm)) {
    1013          34 :       errorf(pc_, "block type index %u out of bounds (%zu signatures)",
    1014           0 :              imm.sig_index, module_ ? module_->signatures.size() : 0);
    1015          17 :       return false;
    1016             :     }
    1017             :     return true;
    1018             :   }
    1019             : 
    1020         199 :   inline bool Validate(MemoryIndexImmediate<validate>& imm) {
    1021         199 :     if (!VALIDATE(module_ != nullptr && module_->has_memory)) {
    1022           3 :       errorf(pc_ + 1, "memory instruction with no memory");
    1023             :       return false;
    1024             :     }
    1025             :     return true;
    1026             :   }
    1027             : 
    1028          87 :   inline bool Validate(MemoryInitImmediate<validate>& imm) {
    1029          87 :     if (!Validate(imm.memory)) return false;
    1030          86 :     if (!VALIDATE(module_ != nullptr &&
    1031             :                   imm.data_segment_index <
    1032             :                       module_->num_declared_data_segments)) {
    1033           0 :       errorf(pc_ + 2, "invalid data segment index: %u", imm.data_segment_index);
    1034             :       return false;
    1035             :     }
    1036             :     return true;
    1037             :   }
    1038             : 
    1039          47 :   inline bool Validate(MemoryDropImmediate<validate>& imm) {
    1040          47 :     if (!VALIDATE(module_ != nullptr &&
    1041             :                   imm.index < module_->num_declared_data_segments)) {
    1042           1 :       errorf(pc_ + 2, "invalid data segment index: %u", imm.index);
    1043             :       return false;
    1044             :     }
    1045             :     return true;
    1046             :   }
    1047             : 
    1048         145 :   inline bool Validate(const byte* pc, TableIndexImmediate<validate>& imm) {
    1049         288 :     if (!VALIDATE(module_ != nullptr && imm.index < module_->tables.size())) {
    1050           3 :       errorf(pc_ + 1, "invalid table index: %u", imm.index);
    1051             :       return false;
    1052             :     }
    1053             :     return true;
    1054             :   }
    1055             : 
    1056          26 :   inline bool Validate(TableInitImmediate<validate>& imm) {
    1057          26 :     if (!Validate(pc_ + 1, imm.table)) return false;
    1058          48 :     if (!VALIDATE(module_ != nullptr &&
    1059             :                   imm.elem_segment_index < module_->elem_segments.size())) {
    1060           1 :       errorf(pc_ + 2, "invalid element segment index: %u",
    1061             :              imm.elem_segment_index);
    1062           1 :       return false;
    1063             :     }
    1064             :     return true;
    1065             :   }
    1066             : 
    1067          39 :   inline bool Validate(TableDropImmediate<validate>& imm) {
    1068          77 :     if (!VALIDATE(module_ != nullptr &&
    1069             :                   imm.index < module_->elem_segments.size())) {
    1070           2 :       errorf(pc_ + 2, "invalid element segment index: %u", imm.index);
    1071           2 :       return false;
    1072             :     }
    1073             :     return true;
    1074             :   }
    1075             : 
    1076     4557774 :   static uint32_t OpcodeLength(Decoder* decoder, const byte* pc) {
    1077     4557774 :     WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
    1078     4557774 :     switch (opcode) {
    1079             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1080             :       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1081             :       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1082             : #undef DECLARE_OPCODE_CASE
    1083             :       {
    1084      179018 :         MemoryAccessImmediate<validate> imm(decoder, pc, UINT32_MAX);
    1085      179018 :         return 1 + imm.length;
    1086             :       }
    1087             :       case kExprBr:
    1088             :       case kExprBrIf: {
    1089             :         BranchDepthImmediate<validate> imm(decoder, pc);
    1090       65057 :         return 1 + imm.length;
    1091             :       }
    1092             :       case kExprSetGlobal:
    1093             :       case kExprGetGlobal: {
    1094        3977 :         GlobalIndexImmediate<validate> imm(decoder, pc);
    1095       28036 :         return 1 + imm.length;
    1096             :       }
    1097             : 
    1098             :       case kExprCallFunction: {
    1099             :         CallFunctionImmediate<validate> imm(decoder, pc);
    1100       22719 :         return 1 + imm.length;
    1101             :       }
    1102             :       case kExprCallIndirect: {
    1103        1398 :         CallIndirectImmediate<validate> imm(decoder, pc);
    1104        1398 :         return 1 + imm.length;
    1105             :       }
    1106             : 
    1107             :       case kExprTry:
    1108             :       case kExprIf:  // fall through
    1109             :       case kExprLoop:
    1110             :       case kExprBlock: {
    1111      136687 :         BlockTypeImmediate<validate> imm(kAllWasmFeatures, decoder, pc);
    1112      136690 :         return 1 + imm.length;
    1113             :       }
    1114             : 
    1115             :       case kExprThrow: {
    1116             :         ExceptionIndexImmediate<validate> imm(decoder, pc);
    1117           1 :         return 1 + imm.length;
    1118             :       }
    1119             : 
    1120             :       case kExprBrOnExn: {
    1121             :         BranchDepthImmediate<validate> imm_br(decoder, pc);
    1122           9 :         if (!VALIDATE(decoder->ok())) return 1 + imm_br.length;
    1123           1 :         ExceptionIndexImmediate<validate> imm_idx(decoder, pc + imm_br.length);
    1124           1 :         return 1 + imm_br.length + imm_idx.length;
    1125             :       }
    1126             : 
    1127             :       case kExprSetLocal:
    1128             :       case kExprTeeLocal:
    1129             :       case kExprGetLocal: {
    1130             :         LocalIndexImmediate<validate> imm(decoder, pc);
    1131      594774 :         return 1 + imm.length;
    1132             :       }
    1133             :       case kExprBrTable: {
    1134        5366 :         BranchTableImmediate<validate> imm(decoder, pc);
    1135             :         BranchTableIterator<validate> iterator(decoder, imm);
    1136        5366 :         return 1 + iterator.length();
    1137             :       }
    1138             :       case kExprI32Const: {
    1139             :         ImmI32Immediate<validate> imm(decoder, pc);
    1140     1436849 :         return 1 + imm.length;
    1141             :       }
    1142             :       case kExprI64Const: {
    1143             :         ImmI64Immediate<validate> imm(decoder, pc);
    1144        3285 :         return 1 + imm.length;
    1145             :       }
    1146             :       case kExprRefNull: {
    1147             :         return 1;
    1148             :       }
    1149             :       case kExprMemoryGrow:
    1150             :       case kExprMemorySize: {
    1151          72 :         MemoryIndexImmediate<validate> imm(decoder, pc);
    1152          72 :         return 1 + imm.length;
    1153             :       }
    1154             :       case kExprF32Const:
    1155         630 :         return 5;
    1156             :       case kExprF64Const:
    1157        4374 :         return 9;
    1158             :       case kNumericPrefix: {
    1159             :         byte numeric_index =
    1160       30725 :             decoder->read_u8<validate>(pc + 1, "numeric_index");
    1161           0 :         if (!VALIDATE(decoder->ok())) return 2;
    1162             :         WasmOpcode opcode =
    1163          40 :             static_cast<WasmOpcode>(kNumericPrefix << 8 | numeric_index);
    1164          40 :         switch (opcode) {
    1165             :           case kExprI32SConvertSatF32:
    1166             :           case kExprI32UConvertSatF32:
    1167             :           case kExprI32SConvertSatF64:
    1168             :           case kExprI32UConvertSatF64:
    1169             :           case kExprI64SConvertSatF32:
    1170             :           case kExprI64UConvertSatF32:
    1171             :           case kExprI64SConvertSatF64:
    1172             :           case kExprI64UConvertSatF64:
    1173             :             return 2;
    1174             :           case kExprMemoryInit: {
    1175           0 :             MemoryInitImmediate<validate> imm(decoder, pc);
    1176           0 :             return 2 + imm.length;
    1177             :           }
    1178             :           case kExprMemoryDrop: {
    1179             :             MemoryDropImmediate<validate> imm(decoder, pc);
    1180           0 :             return 2 + imm.length;
    1181             :           }
    1182             :           case kExprMemoryCopy:
    1183             :           case kExprMemoryFill: {
    1184           0 :             MemoryIndexImmediate<validate> imm(decoder, pc + 1);
    1185           0 :             return 2 + imm.length;
    1186             :           }
    1187             :           case kExprTableInit: {
    1188           0 :             TableInitImmediate<validate> imm(decoder, pc);
    1189           0 :             return 2 + imm.length;
    1190             :           }
    1191             :           case kExprTableDrop: {
    1192             :             TableDropImmediate<validate> imm(decoder, pc);
    1193           0 :             return 2 + imm.length;
    1194             :           }
    1195             :           case kExprTableCopy: {
    1196           0 :             TableIndexImmediate<validate> imm(decoder, pc + 1);
    1197           0 :             return 2 + imm.length;
    1198             :           }
    1199             :           default:
    1200           0 :             decoder->error(pc, "invalid numeric opcode");
    1201           0 :             return 2;
    1202             :         }
    1203             :       }
    1204             :       case kSimdPrefix: {
    1205          60 :         byte simd_index = decoder->read_u8<validate>(pc + 1, "simd_index");
    1206          60 :         if (!VALIDATE(decoder->ok())) return 2;
    1207             :         WasmOpcode opcode =
    1208       30280 :             static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
    1209       30280 :         switch (opcode) {
    1210             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1211             :           FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
    1212             : #undef DECLARE_OPCODE_CASE
    1213             :           return 2;
    1214             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1215             :           FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
    1216             : #undef DECLARE_OPCODE_CASE
    1217       12347 :           return 3;
    1218             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1219             :           FOREACH_SIMD_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1220             : #undef DECLARE_OPCODE_CASE
    1221             :           {
    1222           0 :             MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
    1223           0 :             return 2 + imm.length;
    1224             :           }
    1225             :           // Shuffles require a byte per lane, or 16 immediate bytes.
    1226             :           case kExprS8x16Shuffle:
    1227       15281 :             return 2 + kSimd128Size;
    1228             :           default:
    1229           1 :             decoder->error(pc, "invalid SIMD opcode");
    1230           1 :             return 2;
    1231             :         }
    1232             :       }
    1233             :       case kAtomicPrefix: {
    1234          84 :         byte atomic_index = decoder->read_u8<validate>(pc + 1, "atomic_index");
    1235          84 :         if (!VALIDATE(decoder->ok())) return 2;
    1236             :         WasmOpcode opcode =
    1237         549 :             static_cast<WasmOpcode>(kAtomicPrefix << 8 | atomic_index);
    1238         549 :         switch (opcode) {
    1239             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1240             :           FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE)
    1241             : #undef DECLARE_OPCODE_CASE
    1242             :           {
    1243         549 :             MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
    1244         549 :             return 2 + imm.length;
    1245             :           }
    1246             :           default:
    1247           0 :             decoder->error(pc, "invalid Atomics opcode");
    1248           0 :             return 2;
    1249             :         }
    1250             :       }
    1251             :       default:
    1252             :         return 1;
    1253             :     }
    1254             :   }
    1255             : 
    1256     2881705 :   std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) {
    1257     2878547 :     WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
    1258             :     // Handle "simple" opcodes with a fixed signature first.
    1259     3331418 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    1260     2878547 :     if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode);
    1261     3328443 :     if (sig) return {sig->parameter_count(), sig->return_count()};
    1262             : 
    1263             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1264             :     // clang-format off
    1265     2428651 :     switch (opcode) {
    1266             :       case kExprSelect:
    1267          25 :         return {3, 1};
    1268             :       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1269       93120 :         return {2, 0};
    1270             :       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1271             :       case kExprTeeLocal:
    1272             :       case kExprMemoryGrow:
    1273       85659 :         return {1, 1};
    1274             :       case kExprSetLocal:
    1275             :       case kExprSetGlobal:
    1276             :       case kExprDrop:
    1277             :       case kExprBrIf:
    1278             :       case kExprBrTable:
    1279             :       case kExprIf:
    1280      105123 :         return {1, 0};
    1281             :       case kExprGetLocal:
    1282             :       case kExprGetGlobal:
    1283             :       case kExprI32Const:
    1284             :       case kExprI64Const:
    1285             :       case kExprF32Const:
    1286             :       case kExprF64Const:
    1287             :       case kExprRefNull:
    1288             :       case kExprMemorySize:
    1289     1262302 :         return {0, 1};
    1290             :       case kExprCallFunction: {
    1291             :         CallFunctionImmediate<validate> imm(this, pc);
    1292             :         CHECK(Complete(pc, imm));
    1293        5740 :         return {imm.sig->parameter_count(), imm.sig->return_count()};
    1294             :       }
    1295             :       case kExprCallIndirect: {
    1296         288 :         CallIndirectImmediate<validate> imm(this, pc);
    1297         288 :         CHECK(Complete(pc, imm));
    1298             :         // Indirect calls pop an additional argument for the table index.
    1299             :         return {imm.sig->parameter_count() + 1,
    1300         576 :                 imm.sig->return_count()};
    1301             :       }
    1302             :       case kExprBr:
    1303             :       case kExprBlock:
    1304             :       case kExprLoop:
    1305             :       case kExprEnd:
    1306             :       case kExprElse:
    1307             :       case kExprNop:
    1308             :       case kExprReturn:
    1309             :       case kExprUnreachable:
    1310      848679 :         return {0, 0};
    1311             :       case kNumericPrefix:
    1312             :       case kAtomicPrefix:
    1313             :       case kSimdPrefix: {
    1314       30585 :         opcode = static_cast<WasmOpcode>(opcode << 8 | *(pc + 1));
    1315       30585 :         switch (opcode) {
    1316             :           FOREACH_SIMD_1_OPERAND_1_PARAM_OPCODE(DECLARE_OPCODE_CASE)
    1317       12100 :             return {1, 1};
    1318             :           FOREACH_SIMD_1_OPERAND_2_PARAM_OPCODE(DECLARE_OPCODE_CASE)
    1319             :           FOREACH_SIMD_MASK_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
    1320       15510 :             return {2, 1};
    1321             :           default: {
    1322        2975 :             sig = WasmOpcodes::Signature(opcode);
    1323        2975 :             if (sig) {
    1324        2975 :               return {sig->parameter_count(), sig->return_count()};
    1325             :             }
    1326             :           }
    1327             :         }
    1328             :         V8_FALLTHROUGH;
    1329             :       }
    1330             :       default:
    1331           0 :         V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x (%s)", opcode,
    1332           0 :                  WasmOpcodes::OpcodeName(opcode));
    1333             :         return {0, 0};
    1334             :     }
    1335             : #undef DECLARE_OPCODE_CASE
    1336             :     // clang-format on
    1337             :   }
    1338             : };
    1339             : 
    1340             : #define CALL_INTERFACE(name, ...) interface_.name(this, ##__VA_ARGS__)
    1341             : #define CALL_INTERFACE_IF_REACHABLE(name, ...)                 \
    1342             :   do {                                                         \
    1343             :     DCHECK(!control_.empty());                                 \
    1344             :     if (VALIDATE(this->ok()) && control_.back().reachable()) { \
    1345             :       interface_.name(this, ##__VA_ARGS__);                    \
    1346             :     }                                                          \
    1347             :   } while (false)
    1348             : #define CALL_INTERFACE_IF_PARENT_REACHABLE(name, ...)           \
    1349             :   do {                                                          \
    1350             :     DCHECK(!control_.empty());                                  \
    1351             :     if (VALIDATE(this->ok()) &&                                 \
    1352             :         (control_.size() == 1 || control_at(1)->reachable())) { \
    1353             :       interface_.name(this, ##__VA_ARGS__);                     \
    1354             :     }                                                           \
    1355             :   } while (false)
    1356             : 
    1357             : template <Decoder::ValidateFlag validate, typename Interface>
    1358     3378130 : class WasmFullDecoder : public WasmDecoder<validate> {
    1359             :   using Value = typename Interface::Value;
    1360             :   using Control = typename Interface::Control;
    1361             :   using MergeValues = Merge<Value>;
    1362             : 
    1363             :   // All Value types should be trivially copyable for performance. We push, pop,
    1364             :   // and store them in local variables.
    1365             :   ASSERT_TRIVIALLY_COPYABLE(Value);
    1366             : 
    1367             :  public:
    1368             :   template <typename... InterfaceArgs>
    1369     1954192 :   WasmFullDecoder(Zone* zone, const WasmModule* module,
    1370             :                   const WasmFeatures& enabled, WasmFeatures* detected,
    1371             :                   const FunctionBody& body, InterfaceArgs&&... interface_args)
    1372             :       : WasmDecoder<validate>(module, enabled, detected, body.sig, body.start,
    1373             :                               body.end, body.offset),
    1374             :         zone_(zone),
    1375             :         interface_(std::forward<InterfaceArgs>(interface_args)...),
    1376             :         local_type_vec_(zone),
    1377             :         stack_(zone),
    1378             :         control_(zone),
    1379     3908384 :         args_(zone) {
    1380     1954144 :     this->local_types_ = &local_type_vec_;
    1381     1954144 :   }
    1382             : 
    1383             :   Interface& interface() { return interface_; }
    1384             : 
    1385     1954143 :   bool Decode() {
    1386             :     DCHECK(stack_.empty());
    1387             :     DCHECK(control_.empty());
    1388             : 
    1389             :     base::ElapsedTimer decode_timer;
    1390             :     if (FLAG_trace_wasm_decode_time) {
    1391             :       decode_timer.Start();
    1392             :     }
    1393             : 
    1394     1954143 :     if (this->end_ < this->pc_) {
    1395           0 :       this->error("function body end < start");
    1396           0 :       return false;
    1397             :     }
    1398             : 
    1399             :     DCHECK_EQ(0, this->local_types_->size());
    1400     1954143 :     WasmDecoder<validate>::DecodeLocals(this->enabled_, this, this->sig_,
    1401     1954143 :                                         this->local_types_);
    1402     2840083 :     CALL_INTERFACE(StartFunction);
    1403     1954197 :     DecodeFunctionBody();
    1404     1779052 :     if (!this->failed()) CALL_INTERFACE(FinishFunction);
    1405             : 
    1406             :     // Generate a better error message whether the unterminated control
    1407             :     // structure is the function body block or an innner structure.
    1408     3907248 :     if (control_.size() > 1) {
    1409        8046 :       this->error(control_.back().pc, "unterminated control structure");
    1410     1945578 :     } else if (control_.size() == 1) {
    1411       47906 :       this->error("function body must end with \"end\" opcode");
    1412             :     }
    1413             : 
    1414     1953774 :     if (this->failed()) return this->TraceFailed();
    1415             : 
    1416             :     if (FLAG_trace_wasm_decode_time) {
    1417             :       double ms = decode_timer.Elapsed().InMillisecondsF();
    1418             :       PrintF("wasm-decode %s (%0.3f ms)\n\n",
    1419             :              VALIDATE(this->ok()) ? "ok" : "failed", ms);
    1420             :     } else {
    1421             :       TRACE("wasm-decode %s\n\n", VALIDATE(this->ok()) ? "ok" : "failed");
    1422             :     }
    1423             : 
    1424     1897141 :     return true;
    1425             :   }
    1426             : 
    1427             :   bool TraceFailed() {
    1428             :     TRACE("wasm-error module+%-6d func+%d: %s\n\n", this->error_.offset(),
    1429             :           this->GetBufferRelativeOffset(this->error_.offset()),
    1430             :           this->error_.message().c_str());
    1431             :     return false;
    1432             :   }
    1433             : 
    1434       71272 :   const char* SafeOpcodeNameAt(const byte* pc) {
    1435       71272 :     if (pc >= this->end_) return "<end>";
    1436       58913 :     return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(*pc));
    1437             :   }
    1438             : 
    1439             :   inline Zone* zone() const { return zone_; }
    1440             : 
    1441             :   inline uint32_t num_locals() const {
    1442     4933204 :     return static_cast<uint32_t>(local_type_vec_.size());
    1443             :   }
    1444             : 
    1445             :   inline ValueType GetLocalType(uint32_t index) {
    1446     5154888 :     return local_type_vec_[index];
    1447             :   }
    1448             : 
    1449             :   inline WasmCodePosition position() {
    1450     2602826 :     int offset = static_cast<int>(this->pc_ - this->start_);
    1451             :     DCHECK_EQ(this->pc_ - this->start_, offset);  // overflows cannot happen
    1452             :     return offset;
    1453             :   }
    1454             : 
    1455             :   inline uint32_t control_depth() const {
    1456      908152 :     return static_cast<uint32_t>(control_.size());
    1457             :   }
    1458             : 
    1459             :   inline Control* control_at(uint32_t depth) {
    1460             :     DCHECK_GT(control_.size(), depth);
    1461      839438 :     return &control_.back() - depth;
    1462             :   }
    1463             : 
    1464             :   inline uint32_t stack_size() const {
    1465             :     DCHECK_GE(kMaxUInt32, stack_.size());
    1466     4926692 :     return static_cast<uint32_t>(stack_.size());
    1467             :   }
    1468             : 
    1469             :   inline Value* stack_value(uint32_t depth) {
    1470             :     DCHECK_LT(0, depth);
    1471             :     DCHECK_GE(stack_.size(), depth);
    1472             :     return &*(stack_.end() - depth);
    1473             :   }
    1474             : 
    1475             :  private:
    1476             :   Zone* zone_;
    1477             : 
    1478             :   Interface interface_;
    1479             : 
    1480             :   ZoneVector<ValueType> local_type_vec_;  // types of local variables.
    1481             :   ZoneVector<Value> stack_;               // stack of values.
    1482             :   ZoneVector<Control> control_;           // stack of blocks, loops, and ifs.
    1483             :   ZoneVector<Value> args_;                // parameters of current block or call
    1484             : 
    1485      869787 :   static Value UnreachableValue(const uint8_t* pc) {
    1486      869787 :     return Value{pc, kWasmVar};
    1487             :   }
    1488             : 
    1489      726814 :   bool CheckHasMemory() {
    1490      726814 :     if (!VALIDATE(this->module_->has_memory)) {
    1491         180 :       this->error(this->pc_ - 1, "memory instruction with no memory");
    1492         180 :       return false;
    1493             :     }
    1494             :     return true;
    1495             :   }
    1496             : 
    1497       48560 :   bool CheckHasSharedMemory() {
    1498       48560 :     if (!VALIDATE(this->module_->has_shared_memory)) {
    1499          18 :       this->error(this->pc_ - 1, "Atomic opcodes used without shared memory");
    1500          18 :       return false;
    1501             :     }
    1502             :     return true;
    1503             :   }
    1504             : 
    1505             :   class TraceLine {
    1506             :    public:
    1507             :     static constexpr int kMaxLen = 512;
    1508             :     ~TraceLine() {
    1509             :       if (!FLAG_trace_wasm_decoder) return;
    1510             :       PrintF("%.*s\n", len_, buffer_);
    1511             :     }
    1512             : 
    1513             :     // Appends a formatted string.
    1514             :     PRINTF_FORMAT(2, 3)
    1515             :     void Append(const char* format, ...) {
    1516             :       if (!FLAG_trace_wasm_decoder) return;
    1517             :       va_list va_args;
    1518             :       va_start(va_args, format);
    1519             :       size_t remaining_len = kMaxLen - len_;
    1520             :       Vector<char> remaining_msg_space(buffer_ + len_, remaining_len);
    1521             :       int len = VSNPrintF(remaining_msg_space, format, va_args);
    1522             :       va_end(va_args);
    1523             :       len_ += len < 0 ? remaining_len : len;
    1524             :     }
    1525             : 
    1526             :    private:
    1527             :     char buffer_[kMaxLen];
    1528             :     int len_ = 0;
    1529             :   };
    1530             : 
    1531             :   // Decodes the body of a function.
    1532     1954127 :   void DecodeFunctionBody() {
    1533             :     TRACE("wasm-decode %p...%p (module+%u, %d bytes)\n",
    1534             :           reinterpret_cast<const void*>(this->start()),
    1535             :           reinterpret_cast<const void*>(this->end()), this->pc_offset(),
    1536             :           static_cast<int>(this->end() - this->start()));
    1537             : 
    1538             :     // Set up initial function block.
    1539             :     {
    1540     1954127 :       auto* c = PushControl(kControlBlock);
    1541     1954045 :       InitMerge(&c->start_merge, 0, [](uint32_t) -> Value { UNREACHABLE(); });
    1542     3908116 :       InitMerge(&c->end_merge,
    1543             :                 static_cast<uint32_t>(this->sig_->return_count()),
    1544             :                 [&](uint32_t i) {
    1545             :                   return Value{this->pc_, this->sig_->GetReturn(i)};
    1546     4227387 :                 });
    1547     5166566 :       CALL_INTERFACE(StartFunctionBody, c);
    1548             :     }
    1549             : 
    1550    19646432 :     while (this->pc_ < this->end_) {  // decoding loop.
    1551             :       uint32_t len = 1;
    1552    16980887 :       WasmOpcode opcode = static_cast<WasmOpcode>(*this->pc_);
    1553             : 
    1554     3497879 :       CALL_INTERFACE_IF_REACHABLE(NextInstruction, opcode);
    1555             : 
    1556             : #if DEBUG
    1557             :       TraceLine trace_msg;
    1558             : #define TRACE_PART(...) trace_msg.Append(__VA_ARGS__)
    1559             :       if (!WasmOpcodes::IsPrefixOpcode(opcode)) {
    1560             :         TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    1561             :                    WasmOpcodes::OpcodeName(opcode));
    1562             :       }
    1563             : #else
    1564             : #define TRACE_PART(...)
    1565             : #endif
    1566             : 
    1567    16980887 :       switch (opcode) {
    1568             : #define BUILD_SIMPLE_OPCODE(op, _, sig) \
    1569             :   case kExpr##op:                       \
    1570             :     BuildSimpleOperator_##sig(opcode);  \
    1571             :     break;
    1572             :         FOREACH_SIMPLE_OPCODE(BUILD_SIMPLE_OPCODE)
    1573             : #undef BUILD_SIMPLE_OPCODE
    1574             :         case kExprNop:
    1575             :           break;
    1576             :         case kExprBlock: {
    1577      385515 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1578      385518 :           if (!this->Validate(imm)) break;
    1579      385512 :           PopArgs(imm.sig);
    1580      771024 :           auto* block = PushControl(kControlBlock);
    1581      385521 :           SetBlockType(block, imm);
    1582      195633 :           CALL_INTERFACE_IF_REACHABLE(Block, block);
    1583      771026 :           PushMergeValues(block, &block->start_merge);
    1584      385517 :           len = 1 + imm.length;
    1585      385517 :           break;
    1586             :         }
    1587             :         case kExprRethrow: {
    1588         481 :           CHECK_PROTOTYPE_OPCODE(eh);
    1589             :           auto exception = Pop(0, kWasmExceptRef);
    1590         954 :           CALL_INTERFACE_IF_REACHABLE(Rethrow, exception);
    1591         481 :           EndControl();
    1592         481 :           break;
    1593             :         }
    1594             :         case kExprThrow: {
    1595         685 :           CHECK_PROTOTYPE_OPCODE(eh);
    1596         685 :           ExceptionIndexImmediate<validate> imm(this, this->pc_);
    1597         686 :           len = 1 + imm.length;
    1598         686 :           if (!this->Validate(this->pc_, imm)) break;
    1599         685 :           PopArgs(imm.exception->ToFunctionSig());
    1600        1904 :           CALL_INTERFACE_IF_REACHABLE(Throw, imm, VectorOf(args_));
    1601         685 :           EndControl();
    1602         686 :           break;
    1603             :         }
    1604             :         case kExprTry: {
    1605         742 :           CHECK_PROTOTYPE_OPCODE(eh);
    1606         742 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1607         742 :           if (!this->Validate(imm)) break;
    1608         742 :           PopArgs(imm.sig);
    1609        1483 :           auto* try_block = PushControl(kControlTry);
    1610         743 :           SetBlockType(try_block, imm);
    1611         743 :           len = 1 + imm.length;
    1612        1458 :           CALL_INTERFACE_IF_REACHABLE(Try, try_block);
    1613        1482 :           PushMergeValues(try_block, &try_block->start_merge);
    1614         740 :           break;
    1615             :         }
    1616             :         case kExprCatch: {
    1617         517 :           CHECK_PROTOTYPE_OPCODE(eh);
    1618         517 :           if (!VALIDATE(!control_.empty())) {
    1619           0 :             this->error("catch does not match any try");
    1620           0 :             break;
    1621             :           }
    1622         517 :           Control* c = &control_.back();
    1623         517 :           if (!VALIDATE(c->is_try())) {
    1624           1 :             this->error("catch does not match any try");
    1625           1 :             break;
    1626             :           }
    1627         516 :           if (!VALIDATE(c->is_incomplete_try())) {
    1628           1 :             this->error("catch already present for try");
    1629           1 :             break;
    1630             :           }
    1631         515 :           c->kind = kControlTryCatch;
    1632         515 :           FallThruTo(c);
    1633        1032 :           stack_.erase(stack_.begin() + c->stack_depth, stack_.end());
    1634        1032 :           c->reachability = control_at(1)->innerReachability();
    1635             :           auto* exception = Push(kWasmExceptRef);
    1636        1032 :           CALL_INTERFACE_IF_PARENT_REACHABLE(Catch, c, exception);
    1637             :           break;
    1638             :         }
    1639             :         case kExprBrOnExn: {
    1640         432 :           CHECK_PROTOTYPE_OPCODE(eh);
    1641         432 :           BranchDepthImmediate<validate> imm_br(this, this->pc_);
    1642         864 :           if (!this->Validate(this->pc_, imm_br, control_.size())) break;
    1643             :           ExceptionIndexImmediate<validate> imm_idx(this,
    1644         431 :                                                     this->pc_ + imm_br.length);
    1645         431 :           if (!this->Validate(this->pc_ + imm_br.length, imm_idx)) break;
    1646         431 :           Control* c = control_at(imm_br.depth);
    1647             :           auto exception = Pop(0, kWasmExceptRef);
    1648         711 :           const WasmExceptionSig* sig = imm_idx.exception->sig;
    1649             :           size_t value_count = sig->parameter_count();
    1650             :           // TODO(mstarzinger): This operand stack mutation is an ugly hack to
    1651             :           // make both type checking here as well as environment merging in the
    1652             :           // graph builder interface work out of the box. We should introduce
    1653             :           // special handling for both and do minimal/no stack mutation here.
    1654         711 :           for (size_t i = 0; i < value_count; ++i) Push(sig->GetParam(i));
    1655         423 :           Vector<Value> values(stack_.data() + c->stack_depth, value_count);
    1656         431 :           if (!TypeCheckBranch(c)) break;
    1657         431 :           if (control_.back().reachable()) {
    1658         423 :             CALL_INTERFACE(BrOnException, exception, imm_idx, imm_br.depth,
    1659             :                            values);
    1660         431 :             c->br_merge()->reached = true;
    1661             :           }
    1662         431 :           len = 1 + imm_br.length + imm_idx.length;
    1663         711 :           for (size_t i = 0; i < value_count; ++i) Pop();
    1664             :           auto* pexception = Push(kWasmExceptRef);
    1665         431 :           *pexception = exception;
    1666         431 :           break;
    1667             :         }
    1668             :         case kExprLoop: {
    1669       17955 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1670       17958 :           if (!this->Validate(imm)) break;
    1671       17960 :           PopArgs(imm.sig);
    1672       35920 :           auto* block = PushControl(kControlLoop);
    1673       17961 :           SetBlockType(&control_.back(), imm);
    1674       17961 :           len = 1 + imm.length;
    1675       26457 :           CALL_INTERFACE_IF_REACHABLE(Loop, block);
    1676       35926 :           PushMergeValues(block, &block->start_merge);
    1677       17958 :           break;
    1678             :         }
    1679             :         case kExprIf: {
    1680       85294 :           BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
    1681       85295 :           if (!this->Validate(imm)) break;
    1682             :           auto cond = Pop(0, kWasmI32);
    1683       85284 :           PopArgs(imm.sig);
    1684       85283 :           if (!VALIDATE(this->ok())) break;
    1685      170231 :           auto* if_block = PushControl(kControlIf);
    1686       85118 :           SetBlockType(if_block, imm);
    1687      164607 :           CALL_INTERFACE_IF_REACHABLE(If, cond, if_block);
    1688       85120 :           len = 1 + imm.length;
    1689      170240 :           PushMergeValues(if_block, &if_block->start_merge);
    1690       85115 :           break;
    1691             :         }
    1692             :         case kExprElse: {
    1693       24841 :           if (!VALIDATE(!control_.empty())) {
    1694           0 :             this->error("else does not match any if");
    1695           0 :             break;
    1696             :           }
    1697       51099 :           Control* c = &control_.back();
    1698       47813 :           if (!VALIDATE(c->is_if())) {
    1699           0 :             this->error(this->pc_, "else does not match an if");
    1700           0 :             break;
    1701             :           }
    1702       24841 :           if (c->is_if_else()) {
    1703           2 :             this->error(this->pc_, "else already present for if");
    1704           2 :             break;
    1705             :           }
    1706       24839 :           if (!TypeCheckFallThru(c)) break;
    1707       24617 :           c->kind = kControlIfElse;
    1708       45949 :           CALL_INTERFACE_IF_PARENT_REACHABLE(Else, c);
    1709       24615 :           if (c->reachable()) c->end_merge.reached = true;
    1710       49230 :           PushMergeValues(c, &c->start_merge);
    1711       49234 :           c->reachability = control_at(1)->innerReachability();
    1712       24617 :           break;
    1713             :         }
    1714             :         case kExprEnd: {
    1715     2382588 :           if (!VALIDATE(!control_.empty())) {
    1716           0 :             this->error("end does not match any if, try, or block");
    1717           0 :             break;
    1718             :           }
    1719     2382588 :           Control* c = &control_.back();
    1720     2382588 :           if (!VALIDATE(!c->is_incomplete_try())) {
    1721           1 :             this->error(this->pc_, "missing catch or catch-all in try");
    1722           1 :             break;
    1723             :           }
    1724     2382587 :           if (c->is_onearmed_if()) {
    1725       59703 :             if (!VALIDATE(c->end_merge.arity == c->start_merge.arity)) {
    1726         109 :               this->error(
    1727             :                   c->pc,
    1728             :                   "start-arity and end-arity of one-armed if must match");
    1729         109 :               break;
    1730             :             }
    1731             :           }
    1732             : 
    1733     2382478 :           if (!TypeCheckFallThru(c)) break;
    1734             : 
    1735     2375526 :           if (control_.size() == 1) {
    1736             :             // If at the last (implicit) control, check we are at end.
    1737     1897905 :             if (!VALIDATE(this->pc_ + 1 == this->end_)) {
    1738           2 :               this->error(this->pc_ + 1, "trailing code after function end");
    1739           2 :               break;
    1740             :             }
    1741             :             // The result of the block is the return value.
    1742             :             TRACE_PART("\n" TRACE_INST_FORMAT, startrel(this->pc_),
    1743             :                        "(implicit) return");
    1744     1748416 :             DoReturn();
    1745             :             control_.clear();
    1746             :             break;
    1747             :           }
    1748             : 
    1749      477621 :           PopControl(c);
    1750      477627 :           break;
    1751             :         }
    1752             :         case kExprSelect: {
    1753             :           auto cond = Pop(2, kWasmI32);
    1754             :           auto fval = Pop();
    1755        1387 :           auto tval = Pop(0, fval.type);
    1756        4147 :           auto* result = Push(tval.type == kWasmVar ? fval.type : tval.type);
    1757        5476 :           CALL_INTERFACE_IF_REACHABLE(Select, cond, fval, tval, result);
    1758             :           break;
    1759             :         }
    1760             :         case kExprBr: {
    1761       36329 :           BranchDepthImmediate<validate> imm(this, this->pc_);
    1762       72657 :           if (!this->Validate(this->pc_, imm, control_.size())) break;
    1763       35760 :           Control* c = control_at(imm.depth);
    1764       35760 :           if (!TypeCheckBranch(c)) break;
    1765       66876 :           if (imm.depth == control_.size() - 1) {
    1766         322 :             DoReturn();
    1767       32905 :           } else if (control_.back().reachable()) {
    1768       26989 :             CALL_INTERFACE(Br, c);
    1769       32221 :             c->br_merge()->reached = true;
    1770             :           }
    1771       33438 :           len = 1 + imm.length;
    1772       33438 :           EndControl();
    1773       33435 :           break;
    1774             :         }
    1775             :         case kExprBrIf: {
    1776      270949 :           BranchDepthImmediate<validate> imm(this, this->pc_);
    1777             :           auto cond = Pop(0, kWasmI32);
    1778      270945 :           if (this->failed()) break;
    1779      541422 :           if (!this->Validate(this->pc_, imm, control_.size())) break;
    1780      270630 :           Control* c = control_at(imm.depth);
    1781      270630 :           if (!TypeCheckBranch(c)) break;
    1782      270384 :           if (control_.back().reachable()) {
    1783      150665 :             CALL_INTERFACE(BrIf, cond, imm.depth);
    1784      269659 :             c->br_merge()->reached = true;
    1785             :           }
    1786      270389 :           len = 1 + imm.length;
    1787      270389 :           break;
    1788             :         }
    1789             :         case kExprBrTable: {
    1790       20784 :           BranchTableImmediate<validate> imm(this, this->pc_);
    1791             :           BranchTableIterator<validate> iterator(this, imm);
    1792             :           auto key = Pop(0, kWasmI32);
    1793       20735 :           if (this->failed()) break;
    1794       20647 :           if (!this->Validate(this->pc_, imm, control_.size())) break;
    1795             :           uint32_t br_arity = 0;
    1796       20613 :           std::vector<bool> br_targets(control_.size());
    1797      778168 :           while (iterator.has_next()) {
    1798      737296 :             const uint32_t i = iterator.cur_index();
    1799      737296 :             const byte* pos = iterator.pc();
    1800      737296 :             uint32_t target = iterator.next();
    1801     1474688 :             if (!VALIDATE(target < control_.size())) {
    1802         199 :               this->errorf(pos,
    1803             :                            "improper branch in br_table target %u (depth %u)",
    1804             :                            i, target);
    1805         199 :               break;
    1806             :             }
    1807             :             // Avoid redundant branch target checks.
    1808     1474290 :             if (br_targets[target]) continue;
    1809             :             br_targets[target] = true;
    1810             :             // Check that label types match up.
    1811             :             Control* c = control_at(target);
    1812       50106 :             uint32_t arity = c->br_merge()->arity;
    1813       50106 :             if (i == 0) {
    1814             :               br_arity = arity;
    1815       29559 :             } else if (!VALIDATE(br_arity == arity)) {
    1816          76 :               this->errorf(pos,
    1817             :                            "inconsistent arity in br_table target %u"
    1818             :                            " (previous was %u, this one %u)",
    1819             :                            i, br_arity, arity);
    1820             :             }
    1821       50106 :             if (!TypeCheckBranch(c)) break;
    1822             :           }
    1823       20661 :           if (this->failed()) break;
    1824             : 
    1825       20134 :           if (control_.back().reachable()) {
    1826       18241 :             CALL_INTERFACE(BrTable, imm, key);
    1827             : 
    1828      142892 :             for (uint32_t depth = control_depth(); depth-- > 0;) {
    1829      207660 :               if (!br_targets[depth]) continue;
    1830       48930 :               control_at(depth)->br_merge()->reached = true;
    1831             :             }
    1832             :           }
    1833             : 
    1834       20136 :           len = 1 + iterator.length();
    1835       20133 :           EndControl();
    1836       20133 :           break;
    1837             :         }
    1838             :         case kExprReturn: {
    1839      398510 :           if (!TypeCheckReturn()) break;
    1840      276587 :           DoReturn();
    1841      398016 :           EndControl();
    1842      398018 :           break;
    1843             :         }
    1844             :         case kExprUnreachable: {
    1845      249450 :           CALL_INTERFACE_IF_REACHABLE(Unreachable);
    1846      246959 :           EndControl();
    1847      246960 :           break;
    1848             :         }
    1849             :         case kExprI32Const: {
    1850     4778354 :           ImmI32Immediate<validate> imm(this, this->pc_);
    1851             :           auto* value = Push(kWasmI32);
    1852     9319498 :           CALL_INTERFACE_IF_REACHABLE(I32Const, value, imm.value);
    1853     4778377 :           len = 1 + imm.length;
    1854             :           break;
    1855             :         }
    1856             :         case kExprI64Const: {
    1857      108375 :           ImmI64Immediate<validate> imm(this, this->pc_);
    1858             :           auto* value = Push(kWasmI64);
    1859      142539 :           CALL_INTERFACE_IF_REACHABLE(I64Const, value, imm.value);
    1860      108374 :           len = 1 + imm.length;
    1861             :           break;
    1862             :         }
    1863             :         case kExprF32Const: {
    1864      269470 :           ImmF32Immediate<validate> imm(this, this->pc_);
    1865             :           auto* value = Push(kWasmF32);
    1866      274898 :           CALL_INTERFACE_IF_REACHABLE(F32Const, value, imm.value);
    1867      269472 :           len = 1 + imm.length;
    1868             :           break;
    1869             :         }
    1870             :         case kExprF64Const: {
    1871      277863 :           ImmF64Immediate<validate> imm(this, this->pc_);
    1872             :           auto* value = Push(kWasmF64);
    1873      291934 :           CALL_INTERFACE_IF_REACHABLE(F64Const, value, imm.value);
    1874      277865 :           len = 1 + imm.length;
    1875             :           break;
    1876             :         }
    1877             :         case kExprRefNull: {
    1878          83 :           CHECK_PROTOTYPE_OPCODE(anyref);
    1879             :           auto* value = Push(kWasmAnyRef);
    1880         164 :           CALL_INTERFACE_IF_REACHABLE(RefNull, value);
    1881             :           len = 1;
    1882             :           break;
    1883             :         }
    1884             :         case kExprGetLocal: {
    1885     1205988 :           LocalIndexImmediate<validate> imm(this, this->pc_);
    1886     1205999 :           if (!this->Validate(this->pc_, imm)) break;
    1887     1205630 :           auto* value = Push(imm.type);
    1888     2288883 :           CALL_INTERFACE_IF_REACHABLE(GetLocal, value, imm);
    1889     1205629 :           len = 1 + imm.length;
    1890     1205629 :           break;
    1891             :         }
    1892             :         case kExprSetLocal: {
    1893      618230 :           LocalIndexImmediate<validate> imm(this, this->pc_);
    1894      618239 :           if (!this->Validate(this->pc_, imm)) break;
    1895     1354313 :           auto value = Pop(0, local_type_vec_[imm.index]);
    1896     1211107 :           CALL_INTERFACE_IF_REACHABLE(SetLocal, value, imm);
    1897      618055 :           len = 1 + imm.length;
    1898      618055 :           break;
    1899             :         }
    1900             :         case kExprTeeLocal: {
    1901      118185 :           LocalIndexImmediate<validate> imm(this, this->pc_);
    1902      118184 :           if (!this->Validate(this->pc_, imm)) break;
    1903      236366 :           auto value = Pop(0, local_type_vec_[imm.index]);
    1904             :           auto* result = Push(value.type);
    1905      233817 :           CALL_INTERFACE_IF_REACHABLE(TeeLocal, value, result, imm);
    1906      118185 :           len = 1 + imm.length;
    1907      118185 :           break;
    1908             :         }
    1909             :         case kExprDrop: {
    1910             :           auto value = Pop();
    1911        7488 :           CALL_INTERFACE_IF_REACHABLE(Drop, value);
    1912             :           break;
    1913             :         }
    1914             :         case kExprGetGlobal: {
    1915       65709 :           GlobalIndexImmediate<validate> imm(this, this->pc_);
    1916       65709 :           len = 1 + imm.length;
    1917       65709 :           if (!this->Validate(this->pc_, imm)) break;
    1918       65682 :           auto* result = Push(imm.type);
    1919      130216 :           CALL_INTERFACE_IF_REACHABLE(GetGlobal, result, imm);
    1920             :           break;
    1921             :         }
    1922             :         case kExprSetGlobal: {
    1923       23542 :           GlobalIndexImmediate<validate> imm(this, this->pc_);
    1924       23542 :           len = 1 + imm.length;
    1925       23542 :           if (!this->Validate(this->pc_, imm)) break;
    1926       23542 :           if (!VALIDATE(imm.global->mutability)) {
    1927          28 :             this->errorf(this->pc_, "immutable global #%u cannot be assigned",
    1928             :                          imm.index);
    1929          28 :             break;
    1930             :           }
    1931       23514 :           auto value = Pop(0, imm.type);
    1932       46542 :           CALL_INTERFACE_IF_REACHABLE(SetGlobal, value, imm);
    1933             :           break;
    1934             :         }
    1935             :         case kExprI32LoadMem8S:
    1936        3640 :           len = 1 + DecodeLoadMem(LoadType::kI32Load8S);
    1937        3640 :           break;
    1938             :         case kExprI32LoadMem8U:
    1939        2301 :           len = 1 + DecodeLoadMem(LoadType::kI32Load8U);
    1940        2301 :           break;
    1941             :         case kExprI32LoadMem16S:
    1942         547 :           len = 1 + DecodeLoadMem(LoadType::kI32Load16S);
    1943         547 :           break;
    1944             :         case kExprI32LoadMem16U:
    1945         904 :           len = 1 + DecodeLoadMem(LoadType::kI32Load16U);
    1946         904 :           break;
    1947             :         case kExprI32LoadMem:
    1948      147299 :           len = 1 + DecodeLoadMem(LoadType::kI32Load);
    1949      147299 :           break;
    1950             :         case kExprI64LoadMem8S:
    1951         566 :           len = 1 + DecodeLoadMem(LoadType::kI64Load8S);
    1952         566 :           break;
    1953             :         case kExprI64LoadMem8U:
    1954         434 :           len = 1 + DecodeLoadMem(LoadType::kI64Load8U);
    1955         434 :           break;
    1956             :         case kExprI64LoadMem16S:
    1957         512 :           len = 1 + DecodeLoadMem(LoadType::kI64Load16S);
    1958         512 :           break;
    1959             :         case kExprI64LoadMem16U:
    1960         488 :           len = 1 + DecodeLoadMem(LoadType::kI64Load16U);
    1961         488 :           break;
    1962             :         case kExprI64LoadMem32S:
    1963         539 :           len = 1 + DecodeLoadMem(LoadType::kI64Load32S);
    1964         539 :           break;
    1965             :         case kExprI64LoadMem32U:
    1966         515 :           len = 1 + DecodeLoadMem(LoadType::kI64Load32U);
    1967         515 :           break;
    1968             :         case kExprI64LoadMem:
    1969      149007 :           len = 1 + DecodeLoadMem(LoadType::kI64Load);
    1970      149007 :           break;
    1971             :         case kExprF32LoadMem:
    1972        4582 :           len = 1 + DecodeLoadMem(LoadType::kF32Load);
    1973        4580 :           break;
    1974             :         case kExprF64LoadMem:
    1975        5906 :           len = 1 + DecodeLoadMem(LoadType::kF64Load);
    1976        5907 :           break;
    1977             :         case kExprI32StoreMem8:
    1978        2736 :           len = 1 + DecodeStoreMem(StoreType::kI32Store8);
    1979        2736 :           break;
    1980             :         case kExprI32StoreMem16:
    1981         985 :           len = 1 + DecodeStoreMem(StoreType::kI32Store16);
    1982         985 :           break;
    1983             :         case kExprI32StoreMem:
    1984      226358 :           len = 1 + DecodeStoreMem(StoreType::kI32Store);
    1985      226345 :           break;
    1986             :         case kExprI64StoreMem8:
    1987         366 :           len = 1 + DecodeStoreMem(StoreType::kI64Store8);
    1988         366 :           break;
    1989             :         case kExprI64StoreMem16:
    1990         546 :           len = 1 + DecodeStoreMem(StoreType::kI64Store16);
    1991         546 :           break;
    1992             :         case kExprI64StoreMem32:
    1993         492 :           len = 1 + DecodeStoreMem(StoreType::kI64Store32);
    1994         492 :           break;
    1995             :         case kExprI64StoreMem:
    1996      170212 :           len = 1 + DecodeStoreMem(StoreType::kI64Store);
    1997      170216 :           break;
    1998             :         case kExprF32StoreMem:
    1999        1015 :           len = 1 + DecodeStoreMem(StoreType::kF32Store);
    2000        1015 :           break;
    2001             :         case kExprF64StoreMem:
    2002        2083 :           len = 1 + DecodeStoreMem(StoreType::kF64Store);
    2003        2083 :           break;
    2004             :         case kExprMemoryGrow: {
    2005        3585 :           if (!CheckHasMemory()) break;
    2006        3540 :           MemoryIndexImmediate<validate> imm(this, this->pc_);
    2007        3540 :           len = 1 + imm.length;
    2008             :           DCHECK_NOT_NULL(this->module_);
    2009        3540 :           if (!VALIDATE(this->module_->origin == kWasmOrigin)) {
    2010           1 :             this->error("grow_memory is not supported for asmjs modules");
    2011           1 :             break;
    2012             :           }
    2013             :           auto value = Pop(0, kWasmI32);
    2014             :           auto* result = Push(kWasmI32);
    2015        6915 :           CALL_INTERFACE_IF_REACHABLE(MemoryGrow, value, result);
    2016             :           break;
    2017             :         }
    2018             :         case kExprMemorySize: {
    2019        1196 :           if (!CheckHasMemory()) break;
    2020        1169 :           MemoryIndexImmediate<validate> imm(this, this->pc_);
    2021             :           auto* result = Push(kWasmI32);
    2022        1169 :           len = 1 + imm.length;
    2023        2185 :           CALL_INTERFACE_IF_REACHABLE(CurrentMemoryPages, result);
    2024             :           break;
    2025             :         }
    2026             :         case kExprCallFunction: {
    2027      301697 :           CallFunctionImmediate<validate> imm(this, this->pc_);
    2028      301690 :           len = 1 + imm.length;
    2029      301690 :           if (!this->Validate(this->pc_, imm)) break;
    2030             :           // TODO(clemensh): Better memory management.
    2031      301623 :           PopArgs(imm.sig);
    2032      301624 :           auto* returns = PushReturns(imm.sig);
    2033      382715 :           CALL_INTERFACE_IF_REACHABLE(CallDirect, imm, args_.data(), returns);
    2034             :           break;
    2035             :         }
    2036             :         case kExprCallIndirect: {
    2037        9741 :           CallIndirectImmediate<validate> imm(this, this->pc_);
    2038        9740 :           len = 1 + imm.length;
    2039        9740 :           if (!this->Validate(this->pc_, imm)) break;
    2040             :           auto index = Pop(0, kWasmI32);
    2041        9643 :           PopArgs(imm.sig);
    2042        9641 :           auto* returns = PushReturns(imm.sig);
    2043       19037 :           CALL_INTERFACE_IF_REACHABLE(CallIndirect, index, imm, args_.data(),
    2044             :                                       returns);
    2045             :           break;
    2046             :         }
    2047             :         case kNumericPrefix: {
    2048             :           ++len;
    2049             :           byte numeric_index =
    2050         599 :               this->template read_u8<validate>(this->pc_ + 1, "numeric index");
    2051         599 :           opcode = static_cast<WasmOpcode>(opcode << 8 | numeric_index);
    2052         599 :           if (opcode < kExprMemoryInit) {
    2053         162 :             CHECK_PROTOTYPE_OPCODE(sat_f2i_conversions);
    2054             :           } else {
    2055         437 :             CHECK_PROTOTYPE_OPCODE(bulk_memory);
    2056             :           }
    2057             :           TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    2058             :                      WasmOpcodes::OpcodeName(opcode));
    2059         590 :           len += DecodeNumericOpcode(opcode);
    2060         590 :           break;
    2061             :         }
    2062             :         case kSimdPrefix: {
    2063       78761 :           CHECK_PROTOTYPE_OPCODE(simd);
    2064             :           len++;
    2065             :           byte simd_index =
    2066       78761 :               this->template read_u8<validate>(this->pc_ + 1, "simd index");
    2067       78761 :           opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
    2068             :           TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    2069             :                      WasmOpcodes::OpcodeName(opcode));
    2070       78761 :           len += DecodeSimdOpcode(opcode);
    2071       78761 :           break;
    2072             :         }
    2073             :         case kAtomicPrefix: {
    2074       48560 :           CHECK_PROTOTYPE_OPCODE(threads);
    2075       48560 :           if (!CheckHasSharedMemory()) break;
    2076             :           len++;
    2077             :           byte atomic_index =
    2078       48556 :               this->template read_u8<validate>(this->pc_ + 1, "atomic index");
    2079       48555 :           opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_index);
    2080             :           TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
    2081             :                      WasmOpcodes::OpcodeName(opcode));
    2082       48555 :           len += DecodeAtomicOpcode(opcode);
    2083       48580 :           break;
    2084             :         }
    2085             : // Note that prototype opcodes are not handled in the fastpath
    2086             : // above this switch, to avoid checking a feature flag.
    2087             : #define SIMPLE_PROTOTYPE_CASE(name, opc, sig) \
    2088             :   case kExpr##name: /* fallthrough */
    2089             :           FOREACH_SIMPLE_PROTOTYPE_OPCODE(SIMPLE_PROTOTYPE_CASE)
    2090             : #undef SIMPLE_PROTOTYPE_CASE
    2091         129 :           BuildSimplePrototypeOperator(opcode);
    2092         129 :           break;
    2093             :         default: {
    2094             :           // Deal with special asmjs opcodes.
    2095      117444 :           if (this->module_ != nullptr &&
    2096             :               this->module_->origin == kAsmJsOrigin) {
    2097      117413 :             FunctionSig* sig = WasmOpcodes::AsmjsSignature(opcode);
    2098      117413 :             if (sig) {
    2099      117413 :               BuildSimpleOperator(opcode, sig);
    2100             :             }
    2101             :           } else {
    2102          31 :             this->error("Invalid opcode");
    2103     1953967 :             return;
    2104             :           }
    2105             :         }
    2106             :       }
    2107             : 
    2108             : #if DEBUG
    2109             :       if (FLAG_trace_wasm_decoder) {
    2110             :         TRACE_PART(" ");
    2111             :         for (Control& c : control_) {
    2112             :           switch (c.kind) {
    2113             :             case kControlIf:
    2114             :               TRACE_PART("I");
    2115             :               break;
    2116             :             case kControlBlock:
    2117             :               TRACE_PART("B");
    2118             :               break;
    2119             :             case kControlLoop:
    2120             :               TRACE_PART("L");
    2121             :               break;
    2122             :             case kControlTry:
    2123             :               TRACE_PART("T");
    2124             :               break;
    2125             :             default:
    2126             :               break;
    2127             :           }
    2128             :           if (c.start_merge.arity) TRACE_PART("%u-", c.start_merge.arity);
    2129             :           TRACE_PART("%u", c.end_merge.arity);
    2130             :           if (!c.reachable()) TRACE_PART("%c", c.unreachable() ? '*' : '#');
    2131             :         }
    2132             :         TRACE_PART(" | ");
    2133             :         for (size_t i = 0; i < stack_.size(); ++i) {
    2134             :           auto& val = stack_[i];
    2135             :           WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
    2136             :           if (WasmOpcodes::IsPrefixOpcode(opcode)) {
    2137             :             opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1));
    2138             :           }
    2139             :           TRACE_PART(" %c@%d:%s", ValueTypes::ShortNameOf(val.type),
    2140             :                      static_cast<int>(val.pc - this->start_),
    2141             :                      WasmOpcodes::OpcodeName(opcode));
    2142             :           // If the decoder failed, don't try to decode the immediates, as this
    2143             :           // can trigger a DCHECK failure.
    2144             :           if (this->failed()) continue;
    2145             :           switch (opcode) {
    2146             :             case kExprI32Const: {
    2147             :               ImmI32Immediate<Decoder::kNoValidate> imm(this, val.pc);
    2148             :               TRACE_PART("[%d]", imm.value);
    2149             :               break;
    2150             :             }
    2151             :             case kExprGetLocal:
    2152             :             case kExprSetLocal:
    2153             :             case kExprTeeLocal: {
    2154             :               LocalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
    2155             :               TRACE_PART("[%u]", imm.index);
    2156             :               break;
    2157             :             }
    2158             :             case kExprGetGlobal:
    2159             :             case kExprSetGlobal: {
    2160             :               GlobalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
    2161             :               TRACE_PART("[%u]", imm.index);
    2162             :               break;
    2163             :             }
    2164             :             default:
    2165             :               break;
    2166             :           }
    2167             :         }
    2168             :       }
    2169             : #endif
    2170    16980913 :       this->pc_ += len;
    2171             :     }  // end decode loop
    2172     2010117 :     if (!VALIDATE(this->pc_ == this->end_) && this->ok()) {
    2173           0 :       this->error("Beyond end of code");
    2174             :     }
    2175             :   }
    2176             : 
    2177      699709 :   void EndControl() {
    2178             :     DCHECK(!control_.empty());
    2179             :     auto* current = &control_.back();
    2180     1399418 :     stack_.erase(stack_.begin() + current->stack_depth, stack_.end());
    2181      353733 :     CALL_INTERFACE_IF_REACHABLE(EndControl, current);
    2182      699714 :     current->reachability = kUnreachable;
    2183      699714 :   }
    2184             : 
    2185             :   template<typename func>
    2186     4886665 :   void InitMerge(Merge<Value>* merge, uint32_t arity, func get_val) {
    2187     4886665 :     merge->arity = arity;
    2188     4886665 :     if (arity == 1) {
    2189     1680681 :       merge->vals.first = get_val(0);
    2190     3205984 :     } else if (arity > 1) {
    2191        8500 :       merge->vals.array = zone_->NewArray<Value>(arity);
    2192        9825 :       for (uint32_t i = 0; i < arity; i++) {
    2193       17062 :         merge->vals.array[i] = get_val(i);
    2194             :       }
    2195             :     }
    2196     4886665 :   }
    2197             : 
    2198     1467993 :   void SetBlockType(Control* c, BlockTypeImmediate<validate>& imm) {
    2199             :     DCHECK_EQ(imm.in_arity(), this->args_.size());
    2200      489331 :     const byte* pc = this->pc_;
    2201             :     Value* args = this->args_.data();
    2202      978662 :     InitMerge(&c->end_merge, imm.out_arity(), [pc, &imm](uint32_t i) {
    2203             :       return Value{pc, imm.out_type(i)};
    2204      522117 :     });
    2205      978662 :     InitMerge(&c->start_merge, imm.in_arity(),
    2206      489545 :               [args](uint32_t i) { return args[i]; });
    2207      489332 :   }
    2208             : 
    2209             :   // Pops arguments as required by signature into {args_}.
    2210      357654 :   V8_INLINE void PopArgs(FunctionSig* sig) {
    2211      987879 :     int count = sig ? static_cast<int>(sig->parameter_count()) : 0;
    2212      857826 :     args_.resize(count, UnreachableValue(nullptr));
    2213     1591777 :     for (int i = count - 1; i >= 0; --i) {
    2214     1695529 :       args_[i] = Pop(i, sig->GetParam(i));
    2215             :     }
    2216             :   }
    2217             : 
    2218      177235 :   ValueType GetReturnType(FunctionSig* sig) {
    2219             :     DCHECK_GE(1, sig->return_count());
    2220       92457 :     return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn();
    2221             :   }
    2222             : 
    2223     2443356 :   Control* PushControl(ControlKind kind) {
    2224             :     Reachability reachability =
    2225     4886712 :         control_.empty() ? kReachable : control_.back().innerReachability();
    2226     4886712 :     control_.emplace_back(kind, stack_size(), this->pc_, reachability);
    2227     2443370 :     return &control_.back();
    2228             :   }
    2229             : 
    2230     1079704 :   void PopControl(Control* c) {
    2231             :     DCHECK_EQ(c, &control_.back());
    2232      687268 :     CALL_INTERFACE_IF_PARENT_REACHABLE(PopControl, c);
    2233             : 
    2234             :     // A loop just leaves the values on the stack.
    2235     1037110 :     if (!c->is_loop()) PushMergeValues(c, &c->end_merge);
    2236             : 
    2237             :     bool parent_reached =
    2238      581623 :         c->reachable() || c->end_merge.reached || c->is_onearmed_if();
    2239             :     control_.pop_back();
    2240             :     // If the parent block was reachable before, but the popped control does not
    2241             :     // return to here, this block becomes "spec only reachable".
    2242      493418 :     if (!parent_reached && control_.back().reachable()) {
    2243       56451 :       control_.back().reachability = kSpecOnlyReachable;
    2244             :     }
    2245      477628 :   }
    2246             : 
    2247      317257 :   int DecodeLoadMem(LoadType type, int prefix_len = 0) {
    2248      317257 :     if (!CheckHasMemory()) return 0;
    2249             :     MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
    2250      317203 :                                         type.size_log_2());
    2251             :     auto index = Pop(0, kWasmI32);
    2252             :     auto* result = Push(type.value_type());
    2253      607431 :     CALL_INTERFACE_IF_REACHABLE(LoadMem, type, imm, index, result);
    2254      317203 :     return imm.length;
    2255             :   }
    2256             : 
    2257      404794 :   int DecodeStoreMem(StoreType store, int prefix_len = 0) {
    2258      404794 :     if (!CheckHasMemory()) return 0;
    2259             :     MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
    2260      404750 :                                         store.size_log_2());
    2261             :     auto value = Pop(1, store.value_type());
    2262             :     auto index = Pop(0, kWasmI32);
    2263      785072 :     CALL_INTERFACE_IF_REACHABLE(StoreMem, store, imm, index, value);
    2264      404750 :     return imm.length;
    2265             :   }
    2266             : 
    2267       34130 :   uint32_t SimdExtractLane(WasmOpcode opcode, ValueType type) {
    2268       34130 :     SimdLaneImmediate<validate> imm(this, this->pc_);
    2269       34130 :     if (this->Validate(this->pc_, opcode, imm)) {
    2270           0 :       Value inputs[] = {Pop(0, kWasmS128)};
    2271             :       auto* result = Push(type);
    2272       68260 :       CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
    2273             :                                   result);
    2274             :     }
    2275       34130 :     return imm.length;
    2276             :   }
    2277             : 
    2278         750 :   uint32_t SimdReplaceLane(WasmOpcode opcode, ValueType type) {
    2279         750 :     SimdLaneImmediate<validate> imm(this, this->pc_);
    2280         750 :     if (this->Validate(this->pc_, opcode, imm)) {
    2281         750 :       Value inputs[2] = {UnreachableValue(this->pc_),
    2282           0 :                          UnreachableValue(this->pc_)};
    2283         750 :       inputs[1] = Pop(1, type);
    2284         750 :       inputs[0] = Pop(0, kWasmS128);
    2285             :       auto* result = Push(kWasmS128);
    2286        1500 :       CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
    2287             :                                   result);
    2288             :     }
    2289         750 :     return imm.length;
    2290             :   }
    2291             : 
    2292        2385 :   uint32_t SimdShiftOp(WasmOpcode opcode) {
    2293        2385 :     SimdShiftImmediate<validate> imm(this, this->pc_);
    2294        2385 :     if (this->Validate(this->pc_, opcode, imm)) {
    2295             :       auto input = Pop(0, kWasmS128);
    2296             :       auto* result = Push(kWasmS128);
    2297        4770 :       CALL_INTERFACE_IF_REACHABLE(SimdShiftOp, opcode, imm, input, result);
    2298             :     }
    2299        2385 :     return imm.length;
    2300             :   }
    2301             : 
    2302       33781 :   uint32_t Simd8x16ShuffleOp() {
    2303       33781 :     Simd8x16ShuffleImmediate<validate> imm(this, this->pc_);
    2304       33781 :     if (this->Validate(this->pc_, imm)) {
    2305             :       auto input1 = Pop(1, kWasmS128);
    2306             :       auto input0 = Pop(0, kWasmS128);
    2307             :       auto* result = Push(kWasmS128);
    2308       67560 :       CALL_INTERFACE_IF_REACHABLE(Simd8x16ShuffleOp, imm, input0, input1,
    2309             :                                   result);
    2310             :     }
    2311       33781 :     return 16;
    2312             :   }
    2313             : 
    2314       78761 :   uint32_t DecodeSimdOpcode(WasmOpcode opcode) {
    2315             :     uint32_t len = 0;
    2316       78761 :     switch (opcode) {
    2317             :       case kExprF32x4ExtractLane: {
    2318        1280 :         len = SimdExtractLane(opcode, kWasmF32);
    2319        1280 :         break;
    2320             :       }
    2321             :       case kExprI32x4ExtractLane:
    2322             :       case kExprI16x8ExtractLane:
    2323             :       case kExprI8x16ExtractLane: {
    2324       32850 :         len = SimdExtractLane(opcode, kWasmI32);
    2325       32850 :         break;
    2326             :       }
    2327             :       case kExprF32x4ReplaceLane: {
    2328         120 :         len = SimdReplaceLane(opcode, kWasmF32);
    2329         120 :         break;
    2330             :       }
    2331             :       case kExprI32x4ReplaceLane:
    2332             :       case kExprI16x8ReplaceLane:
    2333             :       case kExprI8x16ReplaceLane: {
    2334         630 :         len = SimdReplaceLane(opcode, kWasmI32);
    2335         630 :         break;
    2336             :       }
    2337             :       case kExprI32x4Shl:
    2338             :       case kExprI32x4ShrS:
    2339             :       case kExprI32x4ShrU:
    2340             :       case kExprI16x8Shl:
    2341             :       case kExprI16x8ShrS:
    2342             :       case kExprI16x8ShrU:
    2343             :       case kExprI8x16Shl:
    2344             :       case kExprI8x16ShrS:
    2345             :       case kExprI8x16ShrU: {
    2346        2385 :         len = SimdShiftOp(opcode);
    2347        2385 :         break;
    2348             :       }
    2349             :       case kExprS8x16Shuffle: {
    2350       33781 :         len = Simd8x16ShuffleOp();
    2351       33781 :         break;
    2352             :       }
    2353             :       case kExprS128LoadMem:
    2354          20 :         len = DecodeLoadMem(LoadType::kS128Load, 1);
    2355          20 :         break;
    2356             :       case kExprS128StoreMem:
    2357          10 :         len = DecodeStoreMem(StoreType::kS128Store, 1);
    2358          10 :         break;
    2359             :       default: {
    2360       15370 :         FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2361        7685 :         if (!VALIDATE(sig != nullptr)) {
    2362           0 :           this->error("invalid simd opcode");
    2363           0 :           break;
    2364             :         }
    2365             :         PopArgs(sig);
    2366             :         auto* results =
    2367       15370 :             sig->return_count() == 0 ? nullptr : Push(GetReturnType(sig));
    2368       23055 :         CALL_INTERFACE_IF_REACHABLE(SimdOp, opcode, VectorOf(args_), results);
    2369             :       }
    2370             :     }
    2371       78761 :     return len;
    2372             :   }
    2373             : 
    2374       48553 :   uint32_t DecodeAtomicOpcode(WasmOpcode opcode) {
    2375             :     uint32_t len = 0;
    2376             :     ValueType ret_type;
    2377       48553 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2378       48552 :     if (sig != nullptr) {
    2379             :       MachineType memtype;
    2380       48552 :       switch (opcode) {
    2381             : #define CASE_ATOMIC_STORE_OP(Name, Type) \
    2382             :   case kExpr##Name: {                    \
    2383             :     memtype = MachineType::Type();       \
    2384             :     ret_type = kWasmStmt;                \
    2385             :     break;                               \
    2386             :   }
    2387         454 :         ATOMIC_STORE_OP_LIST(CASE_ATOMIC_STORE_OP)
    2388             : #undef CASE_ATOMIC_OP
    2389             : #define CASE_ATOMIC_OP(Name, Type) \
    2390             :   case kExpr##Name: {              \
    2391             :     memtype = MachineType::Type(); \
    2392             :     ret_type = GetReturnType(sig); \
    2393             :     break;                         \
    2394             :   }
    2395       42396 :         ATOMIC_OP_LIST(CASE_ATOMIC_OP)
    2396             : #undef CASE_ATOMIC_OP
    2397             :         default:
    2398           0 :           this->error("invalid atomic opcode");
    2399           0 :           return 0;
    2400             :       }
    2401             :       MemoryAccessImmediate<validate> imm(
    2402       48552 :           this, this->pc_ + 1, ElementSizeLog2Of(memtype.representation()));
    2403       48556 :       len += imm.length;
    2404             :       PopArgs(sig);
    2405       77836 :       auto result = ret_type == kWasmStmt ? nullptr : Push(GetReturnType(sig));
    2406      130710 :       CALL_INTERFACE_IF_REACHABLE(AtomicOp, opcode, VectorOf(args_), imm,
    2407             :                                   result);
    2408             :     } else {
    2409           0 :       this->error("invalid atomic opcode");
    2410             :     }
    2411       48584 :     return len;
    2412             :   }
    2413             : 
    2414         590 :   unsigned DecodeNumericOpcode(WasmOpcode opcode) {
    2415             :     unsigned len = 0;
    2416        1178 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2417         590 :     if (sig != nullptr) {
    2418         590 :       switch (opcode) {
    2419             :         case kExprI32SConvertSatF32:
    2420             :         case kExprI32UConvertSatF32:
    2421             :         case kExprI32SConvertSatF64:
    2422             :         case kExprI32UConvertSatF64:
    2423             :         case kExprI64SConvertSatF32:
    2424             :         case kExprI64UConvertSatF32:
    2425             :         case kExprI64SConvertSatF64:
    2426             :         case kExprI64UConvertSatF64:
    2427         160 :           BuildSimpleOperator(opcode, sig);
    2428         160 :           break;
    2429             :         case kExprMemoryInit: {
    2430          87 :           MemoryInitImmediate<validate> imm(this, this->pc_);
    2431          87 :           if (!this->Validate(imm)) break;
    2432          86 :           len += imm.length;
    2433             :           auto size = Pop(2, sig->GetParam(2));
    2434             :           auto src = Pop(1, sig->GetParam(1));
    2435             :           auto dst = Pop(0, sig->GetParam(0));
    2436         170 :           CALL_INTERFACE_IF_REACHABLE(MemoryInit, imm, dst, src, size);
    2437             :           break;
    2438             :         }
    2439             :         case kExprMemoryDrop: {
    2440          47 :           MemoryDropImmediate<validate> imm(this, this->pc_);
    2441          47 :           if (!this->Validate(imm)) break;
    2442          46 :           len += imm.length;
    2443          92 :           CALL_INTERFACE_IF_REACHABLE(MemoryDrop, imm);
    2444             :           break;
    2445             :         }
    2446             :         case kExprMemoryCopy: {
    2447          56 :           MemoryIndexImmediate<validate> imm(this, this->pc_ + 1);
    2448          56 :           if (!this->Validate(imm)) break;
    2449          55 :           len += imm.length;
    2450             :           auto size = Pop(2, sig->GetParam(2));
    2451             :           auto src = Pop(1, sig->GetParam(1));
    2452             :           auto dst = Pop(0, sig->GetParam(0));
    2453         110 :           CALL_INTERFACE_IF_REACHABLE(MemoryCopy, imm, dst, src, size);
    2454             :           break;
    2455             :         }
    2456             :         case kExprMemoryFill: {
    2457          56 :           MemoryIndexImmediate<validate> imm(this, this->pc_ + 1);
    2458          56 :           if (!this->Validate(imm)) break;
    2459          55 :           len += imm.length;
    2460             :           auto size = Pop(2, sig->GetParam(2));
    2461             :           auto value = Pop(1, sig->GetParam(1));
    2462             :           auto dst = Pop(0, sig->GetParam(0));
    2463         110 :           CALL_INTERFACE_IF_REACHABLE(MemoryFill, imm, dst, value, size);
    2464             :           break;
    2465             :         }
    2466             :         case kExprTableInit: {
    2467          26 :           TableInitImmediate<validate> imm(this, this->pc_);
    2468          26 :           if (!this->Validate(imm)) break;
    2469          23 :           len += imm.length;
    2470             :           PopArgs(sig);
    2471          53 :           CALL_INTERFACE_IF_REACHABLE(TableInit, imm, VectorOf(args_));
    2472             :           break;
    2473             :         }
    2474             :         case kExprTableDrop: {
    2475          39 :           TableDropImmediate<validate> imm(this, this->pc_);
    2476          39 :           if (!this->Validate(imm)) break;
    2477          37 :           len += imm.length;
    2478          74 :           CALL_INTERFACE_IF_REACHABLE(TableDrop, imm);
    2479             :           break;
    2480             :         }
    2481             :         case kExprTableCopy: {
    2482         119 :           TableIndexImmediate<validate> imm(this, this->pc_ + 1);
    2483         119 :           if (!this->Validate(this->pc_ + 1, imm)) break;
    2484         118 :           len += imm.length;
    2485             :           PopArgs(sig);
    2486         308 :           CALL_INTERFACE_IF_REACHABLE(TableCopy, imm, VectorOf(args_));
    2487             :           break;
    2488             :         }
    2489             :         default:
    2490           0 :           this->error("invalid numeric opcode");
    2491           0 :           break;
    2492             :       }
    2493             :     } else {
    2494           0 :       this->error("invalid numeric opcode");
    2495             :     }
    2496         590 :     return len;
    2497             :   }
    2498             : 
    2499     2025314 :   void DoReturn() {
    2500     1194742 :     size_t return_count = this->sig_->return_count();
    2501             :     DCHECK_GE(stack_.size(), return_count);
    2502             :     Vector<Value> return_values =
    2503             :         return_count == 0
    2504             :             ? Vector<Value>{}
    2505     1194742 :             : Vector<Value>{&*(stack_.end() - return_count), return_count};
    2506             : 
    2507     4050695 :     CALL_INTERFACE_IF_REACHABLE(DoReturn, return_values);
    2508     2025270 :   }
    2509             : 
    2510             :   inline Value* Push(ValueType type) {
    2511             :     DCHECK_NE(kWasmStmt, type);
    2512    10592249 :     stack_.emplace_back(this->pc_, type);
    2513             :     return &stack_.back();
    2514             :   }
    2515             : 
    2516      975721 :   void PushMergeValues(Control* c, Merge<Value>* merge) {
    2517             :     DCHECK_EQ(c, &control_.back());
    2518             :     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
    2519     1951442 :     stack_.erase(stack_.begin() + c->stack_depth, stack_.end());
    2520      975731 :     if (merge->arity == 1) {
    2521       23889 :       stack_.push_back(merge->vals.first);
    2522             :     } else {
    2523         372 :       for (uint32_t i = 0; i < merge->arity; i++) {
    2524         372 :         stack_.push_back(merge->vals.array[i]);
    2525             :       }
    2526             :     }
    2527             :     DCHECK_EQ(c->stack_depth + merge->arity, stack_.size());
    2528      975731 :   }
    2529             : 
    2530      594258 :   Value* PushReturns(FunctionSig* sig) {
    2531             :     size_t return_count = sig->return_count();
    2532      311266 :     if (return_count == 0) return nullptr;
    2533      278968 :     size_t old_size = stack_.size();
    2534      561957 :     for (size_t i = 0; i < return_count; ++i) {
    2535             :       Push(sig->GetReturn(i));
    2536             :     }
    2537      278965 :     return stack_.data() + old_size;
    2538             :   }
    2539             : 
    2540             :   V8_INLINE Value Pop(int index, ValueType expected) {
    2541             :     auto val = Pop();
    2542     8581607 :     if (!VALIDATE(val.type == expected || val.type == kWasmVar ||
    2543             :                   expected == kWasmVar)) {
    2544       34278 :       this->errorf(val.pc, "%s[%d] expected type %s, found %s of type %s",
    2545             :                    SafeOpcodeNameAt(this->pc_), index,
    2546             :                    ValueTypes::TypeName(expected), SafeOpcodeNameAt(val.pc),
    2547             :                    ValueTypes::TypeName(val.type));
    2548             :     }
    2549             :     return val;
    2550             :   }
    2551             : 
    2552             :   V8_INLINE Value Pop() {
    2553             :     DCHECK(!control_.empty());
    2554     8795041 :     uint32_t limit = control_.back().stack_depth;
    2555     8795057 :     if (stack_.size() <= limit) {
    2556             :       // Popping past the current control start in reachable code.
    2557       11976 :       if (!VALIDATE(control_.back().unreachable())) {
    2558        2716 :         this->errorf(this->pc_, "%s found empty stack",
    2559             :                      SafeOpcodeNameAt(this->pc_));
    2560             :       }
    2561       11976 :       return UnreachableValue(this->pc_);
    2562             :     }
    2563     8783052 :     auto val = stack_.back();
    2564     8783043 :     stack_.pop_back();
    2565     3734457 :     return val;
    2566             :   }
    2567             : 
    2568        5341 :   int startrel(const byte* ptr) { return static_cast<int>(ptr - this->start_); }
    2569             : 
    2570         527 :   void FallThruTo(Control* c) {
    2571             :     DCHECK_EQ(c, &control_.back());
    2572         515 :     if (!TypeCheckFallThru(c)) return;
    2573         516 :     if (!c->reachable()) return;
    2574             : 
    2575         279 :     if (!c->is_loop()) CALL_INTERFACE(FallThruTo, c);
    2576         291 :     c->end_merge.reached = true;
    2577             :   }
    2578             : 
    2579     1670798 :   bool TypeCheckMergeValues(Control* c, Merge<Value>* merge) {
    2580             :     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
    2581             :     DCHECK_GE(stack_.size(), c->stack_depth + merge->arity);
    2582             :     // The computation of {stack_values} is only valid if {merge->arity} is >0.
    2583             :     DCHECK_LT(0, merge->arity);
    2584     1670798 :     Value* stack_values = &*(stack_.end() - merge->arity);
    2585             :     // Typecheck the topmost {merge->arity} values on the stack.
    2586     1708678 :     for (uint32_t i = 0; i < merge->arity; ++i) {
    2587     1674572 :       Value& val = stack_values[i];
    2588             :       Value& old = (*merge)[i];
    2589     1674572 :       if (val.type == old.type) continue;
    2590             :       // If {val.type} is polymorphic, which results from unreachable, make
    2591             :       // it more specific by using the merge value's expected type.
    2592             :       // If it is not polymorphic, this is a type error.
    2593       30945 :       if (!VALIDATE(val.type == kWasmVar)) {
    2594        4602 :         this->errorf(this->pc_, "type error in merge[%u] (expected %s, got %s)",
    2595             :                      i, ValueTypes::TypeName(old.type),
    2596             :                      ValueTypes::TypeName(val.type));
    2597        2611 :         return false;
    2598             :       }
    2599       26343 :       val.type = old.type;
    2600             :     }
    2601             : 
    2602             :     return true;
    2603             :   }
    2604             : 
    2605     2411693 :   bool TypeCheckFallThru(Control* c) {
    2606             :     DCHECK_EQ(c, &control_.back());
    2607             :     if (!validate) return true;
    2608     2407742 :     uint32_t expected = c->end_merge.arity;
    2609             :     DCHECK_GE(stack_.size(), c->stack_depth);
    2610     4815484 :     uint32_t actual = static_cast<uint32_t>(stack_.size()) - c->stack_depth;
    2611             :     // Fallthrus must match the arity of the control exactly.
    2612     2407742 :     if (!InsertUnreachablesIfNecessary(expected, actual) || actual > expected) {
    2613        7902 :       this->errorf(
    2614             :           this->pc_,
    2615             :           "expected %u elements on the stack for fallthru to @%d, found %u",
    2616             :           expected, startrel(c->pc), actual);
    2617        3951 :       return false;
    2618             :     }
    2619     2404011 :     if (expected == 0) return true;  // Fast path.
    2620             : 
    2621     1657588 :     return TypeCheckMergeValues(c, &c->end_merge);
    2622             :   }
    2623             : 
    2624      358311 :   bool TypeCheckBranch(Control* c) {
    2625             :     // Branches must have at least the number of values expected; can have more.
    2626      356921 :     uint32_t expected = c->br_merge()->arity;
    2627      356921 :     if (expected == 0) return true;  // Fast path.
    2628             :     DCHECK_GE(stack_.size(), control_.back().stack_depth);
    2629             :     uint32_t actual =
    2630       43947 :         static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth;
    2631       14649 :     if (!InsertUnreachablesIfNecessary(expected, actual)) {
    2632        2780 :       this->errorf(this->pc_,
    2633             :                    "expected %u elements on the stack for br to @%d, found %u",
    2634             :                    expected, startrel(c->pc), actual);
    2635        1390 :       return false;
    2636             :     }
    2637       13259 :     return TypeCheckMergeValues(c, c->br_merge());
    2638             :   }
    2639             : 
    2640      398510 :   bool TypeCheckReturn() {
    2641             :     // Returns must have at least the number of values expected; can have more.
    2642      538710 :     uint32_t num_returns = static_cast<uint32_t>(this->sig_->return_count());
    2643             :     DCHECK_GE(stack_.size(), control_.back().stack_depth);
    2644             :     uint32_t actual =
    2645     1195530 :         static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth;
    2646      398510 :     if (!InsertUnreachablesIfNecessary(num_returns, actual)) {
    2647         326 :       this->errorf(this->pc_,
    2648             :                    "expected %u elements on the stack for return, found %u",
    2649             :                    num_returns, actual);
    2650         326 :       return false;
    2651             :     }
    2652             : 
    2653             :     // Typecheck the topmost {num_returns} values on the stack.
    2654      398185 :     if (num_returns == 0) return true;
    2655             :     // This line requires num_returns > 0.
    2656             :     Value* stack_values = &*(stack_.end() - num_returns);
    2657      280207 :     for (uint32_t i = 0; i < num_returns; ++i) {
    2658      140200 :       auto& val = stack_values[i];
    2659      140200 :       ValueType expected_type = this->sig_->GetReturn(i);
    2660      140200 :       if (val.type == expected_type) continue;
    2661             :       // If {val.type} is polymorphic, which results from unreachable,
    2662             :       // make it more specific by using the return's expected type.
    2663             :       // If it is not polymorphic, this is a type error.
    2664         271 :       if (!VALIDATE(val.type == kWasmVar)) {
    2665         163 :         this->errorf(this->pc_,
    2666             :                      "type error in return[%u] (expected %s, got %s)", i,
    2667             :                      ValueTypes::TypeName(expected_type),
    2668             :                      ValueTypes::TypeName(val.type));
    2669         163 :         return false;
    2670             :       }
    2671         108 :       val.type = expected_type;
    2672             :     }
    2673             :     return true;
    2674             :   }
    2675             : 
    2676     2820898 :   inline bool InsertUnreachablesIfNecessary(uint32_t expected,
    2677             :                                             uint32_t actual) {
    2678     2820898 :     if (V8_LIKELY(actual >= expected)) {
    2679             :       return true;  // enough actual values are there.
    2680             :     }
    2681       28885 :     if (!VALIDATE(control_.back().unreachable())) {
    2682             :       // There aren't enough values on the stack.
    2683             :       return false;
    2684             :     }
    2685             :     // A slow path. When the actual number of values on the stack is less
    2686             :     // than the expected number of values and the current control is
    2687             :     // unreachable, insert unreachable values below the actual values.
    2688             :     // This simplifies {TypeCheckMergeValues}.
    2689       50948 :     auto pos = stack_.begin() + (stack_.size() - actual);
    2690       71847 :     stack_.insert(pos, expected - actual, UnreachableValue(this->pc_));
    2691       25474 :     return true;
    2692             :   }
    2693             : 
    2694       56623 :   void onFirstError() override {
    2695       56623 :     this->end_ = this->pc_;  // Terminate decoding loop.
    2696             :     TRACE(" !%s\n", this->error_.message().c_str());
    2697             :     CALL_INTERFACE(OnFirstError);
    2698       56623 :   }
    2699             : 
    2700         129 :   void BuildSimplePrototypeOperator(WasmOpcode opcode) {
    2701         129 :     if (WasmOpcodes::IsSignExtensionOpcode(opcode)) {
    2702          93 :       RET_ON_PROTOTYPE_OPCODE(se);
    2703             :     }
    2704         129 :     if (WasmOpcodes::IsAnyRefOpcode(opcode)) {
    2705          36 :       RET_ON_PROTOTYPE_OPCODE(anyref);
    2706             :     }
    2707         129 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2708         129 :     BuildSimpleOperator(opcode, sig);
    2709         129 :   }
    2710             : 
    2711      520973 :   void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
    2712      117702 :     switch (sig->parameter_count()) {
    2713             :       case 1: {
    2714             :         auto val = Pop(0, sig->GetParam(0));
    2715             :         auto* ret =
    2716      134481 :             sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
    2717      134124 :         CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, val, ret);
    2718             :         break;
    2719             :       }
    2720             :       case 2: {
    2721             :         auto rval = Pop(1, sig->GetParam(1));
    2722             :         auto lval = Pop(0, sig->GetParam(0));
    2723             :         auto* ret =
    2724       98705 :             sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
    2725       97330 :         CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, lval, rval, ret);
    2726             :         break;
    2727             :       }
    2728             :       default:
    2729           0 :         UNREACHABLE();
    2730             :     }
    2731      117702 :   }
    2732             : 
    2733      551243 :   void BuildSimpleOperator(WasmOpcode opcode, ValueType return_type,
    2734             :                            ValueType arg_type) {
    2735             :     auto val = Pop(0, arg_type);
    2736      611536 :     auto* ret = return_type == kWasmStmt ? nullptr : Push(return_type);
    2737      625394 :     CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, val, ret);
    2738      551256 :   }
    2739             : 
    2740     2368233 :   void BuildSimpleOperator(WasmOpcode opcode, ValueType return_type,
    2741             :                            ValueType lhs_type, ValueType rhs_type) {
    2742             :     auto rval = Pop(1, rhs_type);
    2743             :     auto lval = Pop(0, lhs_type);
    2744     3673745 :     auto* ret = return_type == kWasmStmt ? nullptr : Push(return_type);
    2745     4415515 :     CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, lval, rval, ret);
    2746     2368251 :   }
    2747             : 
    2748             : #define DEFINE_SIMPLE_SIG_OPERATOR(sig, ...)          \
    2749             :   void BuildSimpleOperator_##sig(WasmOpcode opcode) { \
    2750             :     BuildSimpleOperator(opcode, __VA_ARGS__);         \
    2751             :   }
    2752      249113 :   FOREACH_SIGNATURE(DEFINE_SIMPLE_SIG_OPERATOR)
    2753             : #undef DEFINE_SIMPLE_SIG_OPERATOR
    2754             : };
    2755             : 
    2756             : #undef CALL_INTERFACE
    2757             : #undef CALL_INTERFACE_IF_REACHABLE
    2758             : #undef CALL_INTERFACE_IF_PARENT_REACHABLE
    2759             : 
    2760             : class EmptyInterface {
    2761             :  public:
    2762             :   static constexpr Decoder::ValidateFlag validate = Decoder::kValidate;
    2763             :   using Value = ValueBase;
    2764             :   using Control = ControlBase<Value>;
    2765             :   using FullDecoder = WasmFullDecoder<validate, EmptyInterface>;
    2766             : 
    2767             : #define DEFINE_EMPTY_CALLBACK(name, ...) \
    2768             :   void name(FullDecoder* decoder, ##__VA_ARGS__) {}
    2769             :   INTERFACE_FUNCTIONS(DEFINE_EMPTY_CALLBACK)
    2770             : #undef DEFINE_EMPTY_CALLBACK
    2771             : };
    2772             : 
    2773             : #undef TRACE
    2774             : #undef TRACE_INST_FORMAT
    2775             : #undef VALIDATE
    2776             : #undef CHECK_PROTOTYPE_OPCODE
    2777             : #undef OPCODE_ERROR
    2778             : 
    2779             : }  // namespace wasm
    2780             : }  // namespace internal
    2781             : }  // namespace v8
    2782             : 
    2783             : #endif  // V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_

Generated by: LCOV version 1.10