LCOV - code coverage report
Current view: top level - src/wasm - function-body-decoder-impl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 766 824 93.0 %
Date: 2017-10-20 Functions: 95 116 81.9 %

          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/bit-vector.h"
      12             : #include "src/wasm/decoder.h"
      13             : #include "src/wasm/function-body-decoder.h"
      14             : #include "src/wasm/wasm-limits.h"
      15             : #include "src/wasm/wasm-module.h"
      16             : #include "src/wasm/wasm-opcodes.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : namespace wasm {
      21             : 
      22             : struct WasmGlobal;
      23             : struct WasmException;
      24             : 
      25             : #if DEBUG
      26             : #define TRACE(...)                                    \
      27             :   do {                                                \
      28             :     if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
      29             :   } while (false)
      30             : #else
      31             : #define TRACE(...)
      32             : #endif
      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 CHECK_PROTOTYPE_OPCODE(flag)                                           \
      43             :   DCHECK(!this->module_ || !this->module_->is_asm_js());                       \
      44             :   if (!FLAG_experimental_wasm_##flag) {                                        \
      45             :     this->error("Invalid opcode (enable with --experimental-wasm-" #flag ")"); \
      46             :     break;                                                                     \
      47             :   }
      48             : 
      49             : #define OPCODE_ERROR(opcode, message)                                 \
      50             :   (this->errorf(this->pc_, "%s: %s", WasmOpcodes::OpcodeName(opcode), \
      51             :                 (message)))
      52             : 
      53             : #define ATOMIC_OP_LIST(V)              \
      54             :   V(I32AtomicLoad, Uint32)             \
      55             :   V(I32AtomicAdd, Uint32)              \
      56             :   V(I32AtomicSub, Uint32)              \
      57             :   V(I32AtomicAnd, Uint32)              \
      58             :   V(I32AtomicOr, Uint32)               \
      59             :   V(I32AtomicXor, Uint32)              \
      60             :   V(I32AtomicExchange, Uint32)         \
      61             :   V(I32AtomicLoad8U, Uint8)            \
      62             :   V(I32AtomicAdd8U, Uint8)             \
      63             :   V(I32AtomicSub8U, Uint8)             \
      64             :   V(I32AtomicAnd8U, Uint8)             \
      65             :   V(I32AtomicOr8U, Uint8)              \
      66             :   V(I32AtomicXor8U, Uint8)             \
      67             :   V(I32AtomicExchange8U, Uint8)        \
      68             :   V(I32AtomicLoad16U, Uint16)          \
      69             :   V(I32AtomicAdd16U, Uint16)           \
      70             :   V(I32AtomicSub16U, Uint16)           \
      71             :   V(I32AtomicAnd16U, Uint16)           \
      72             :   V(I32AtomicOr16U, Uint16)            \
      73             :   V(I32AtomicXor16U, Uint16)           \
      74             :   V(I32AtomicExchange16U, Uint16)      \
      75             :   V(I32AtomicCompareExchange, Uint32)  \
      76             :   V(I32AtomicCompareExchange8U, Uint8) \
      77             :   V(I32AtomicCompareExchange16U, Uint16)
      78             : 
      79             : #define ATOMIC_STORE_OP_LIST(V) \
      80             :   V(I32AtomicStore, Uint32)     \
      81             :   V(I32AtomicStore8U, Uint8)    \
      82             :   V(I32AtomicStore16U, Uint16)
      83             : 
      84             : template <typename T>
      85      291841 : Vector<T> vec2vec(std::vector<T>& vec) {
      86             :   return Vector<T>(vec.data(), vec.size());
      87             : }
      88             : 
      89             : // Helpers for decoding different kinds of operands which follow bytecodes.
      90             : template <Decoder::ValidateFlag validate>
      91             : struct LocalIndexOperand {
      92             :   uint32_t index;
      93             :   ValueType type = kWasmStmt;
      94             :   unsigned length;
      95             : 
      96     6854197 :   inline LocalIndexOperand(Decoder* decoder, const byte* pc) {
      97    13708410 :     index = decoder->read_u32v<validate>(pc + 1, &length, "local index");
      98             :   }
      99             : };
     100             : 
     101             : template <Decoder::ValidateFlag validate>
     102             : struct ExceptionIndexOperand {
     103             :   uint32_t index;
     104             :   const WasmException* exception = nullptr;
     105             :   unsigned length;
     106             : 
     107         220 :   inline ExceptionIndexOperand(Decoder* decoder, const byte* pc) {
     108         440 :     index = decoder->read_u32v<validate>(pc + 1, &length, "exception index");
     109             :   }
     110             : };
     111             : 
     112             : template <Decoder::ValidateFlag validate>
     113             : struct ImmI32Operand {
     114             :   int32_t value;
     115             :   unsigned length;
     116             :   inline ImmI32Operand(Decoder* decoder, const byte* pc) {
     117     4125290 :     value = decoder->read_i32v<validate>(pc + 1, &length, "immi32");
     118             :   }
     119             : };
     120             : 
     121             : template <Decoder::ValidateFlag validate>
     122             : struct ImmI64Operand {
     123             :   int64_t value;
     124             :   unsigned length;
     125             :   inline ImmI64Operand(Decoder* decoder, const byte* pc) {
     126      198994 :     value = decoder->read_i64v<validate>(pc + 1, &length, "immi64");
     127             :   }
     128             : };
     129             : 
     130             : template <Decoder::ValidateFlag validate>
     131             : struct ImmF32Operand {
     132             :   float value;
     133             :   unsigned length = 4;
     134      728563 :   inline ImmF32Operand(Decoder* decoder, const byte* pc) {
     135             :     // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
     136     1457126 :     uint32_t tmp = decoder->read_u32<validate>(pc + 1, "immf32");
     137      728563 :     memcpy(&value, &tmp, sizeof(value));
     138      728563 :   }
     139             : };
     140             : 
     141             : template <Decoder::ValidateFlag validate>
     142             : struct ImmF64Operand {
     143             :   double value;
     144             :   unsigned length = 8;
     145      303622 :   inline ImmF64Operand(Decoder* decoder, const byte* pc) {
     146             :     // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
     147      607246 :     uint64_t tmp = decoder->read_u64<validate>(pc + 1, "immf64");
     148      303624 :     memcpy(&value, &tmp, sizeof(value));
     149      303624 :   }
     150             : };
     151             : 
     152             : template <Decoder::ValidateFlag validate>
     153             : struct GlobalIndexOperand {
     154             :   uint32_t index;
     155             :   ValueType type = kWasmStmt;
     156             :   const WasmGlobal* global = nullptr;
     157             :   unsigned length;
     158             : 
     159       37383 :   inline GlobalIndexOperand(Decoder* decoder, const byte* pc) {
     160       74766 :     index = decoder->read_u32v<validate>(pc + 1, &length, "global index");
     161       36618 :   }
     162             : };
     163             : 
     164             : template <Decoder::ValidateFlag validate>
     165             : struct BlockTypeOperand {
     166             :   unsigned length = 1;
     167             :   ValueType type = kWasmStmt;
     168             :   uint32_t sig_index = 0;
     169             :   FunctionSig* sig = nullptr;
     170             : 
     171     2421231 :   inline BlockTypeOperand(Decoder* decoder, const byte* pc) {
     172     2421231 :     uint8_t val = decoder->read_u8<validate>(pc + 1, "block type");
     173     2421236 :     if (!decode_local_type(val, &type)) {
     174             :       // Handle multi-value blocks.
     175          98 :       if (!VALIDATE(FLAG_experimental_wasm_mv)) {
     176             :         decoder->error(pc + 1, "invalid block type");
     177             :         return;
     178             :       }
     179             :       int32_t index =
     180       60652 :           decoder->read_i32v<validate>(pc + 1, &length, "block arity");
     181          64 :       if (!VALIDATE(length > 0 && index >= 0)) {
     182             :         decoder->error(pc + 1, "invalid block type index");
     183             :         return;
     184             :       }
     185       60652 :       sig_index = static_cast<uint32_t>(index);
     186             :     }
     187             :   }
     188             : 
     189             :   // Decode a byte representing a local type. Return {false} if the encoded
     190             :   // byte was invalid or the start of a type index.
     191     2421240 :   inline bool decode_local_type(uint8_t val, ValueType* result) {
     192     2421240 :     switch (static_cast<ValueTypeCode>(val)) {
     193             :       case kLocalVoid:
     194     2323056 :         *result = kWasmStmt;
     195             :         return true;
     196             :       case kLocalI32:
     197       32587 :         *result = kWasmI32;
     198             :         return true;
     199             :       case kLocalI64:
     200         553 :         *result = kWasmI64;
     201             :         return true;
     202             :       case kLocalF32:
     203        1996 :         *result = kWasmF32;
     204             :         return true;
     205             :       case kLocalF64:
     206        2362 :         *result = kWasmF64;
     207             :         return true;
     208             :       case kLocalS128:
     209           0 :         *result = kWasmS128;
     210             :         return true;
     211             :       default:
     212       60686 :         *result = kWasmVar;
     213             :         return false;
     214             :     }
     215             :   }
     216             : 
     217             :   uint32_t in_arity() const {
     218         220 :     if (type != kWasmVar) return 0;
     219           0 :     return static_cast<uint32_t>(sig->parameter_count());
     220             :   }
     221             :   uint32_t out_arity() const {
     222      527139 :     if (type == kWasmStmt) return 0;
     223       19706 :     if (type != kWasmVar) return 1;
     224         120 :     return static_cast<uint32_t>(sig->return_count());
     225             :   }
     226             :   ValueType in_type(uint32_t index) {
     227             :     DCHECK_EQ(kWasmVar, type);
     228             :     return sig->GetParam(index);
     229             :   }
     230             :   ValueType out_type(uint32_t index) {
     231       18446 :     if (type == kWasmVar) return sig->GetReturn(index);
     232             :     DCHECK_NE(kWasmStmt, type);
     233             :     DCHECK_EQ(0, index);
     234             :     return type;
     235             :   }
     236             : };
     237             : 
     238             : template <Decoder::ValidateFlag validate>
     239             : struct BreakDepthOperand {
     240             :   uint32_t depth;
     241             :   unsigned length;
     242             :   inline BreakDepthOperand(Decoder* decoder, const byte* pc) {
     243      944808 :     depth = decoder->read_u32v<validate>(pc + 1, &length, "break depth");
     244             :   }
     245             : };
     246             : 
     247             : template <Decoder::ValidateFlag validate>
     248             : struct CallIndirectOperand {
     249             :   uint32_t table_index;
     250             :   uint32_t index;
     251             :   FunctionSig* sig = nullptr;
     252             :   unsigned length;
     253        6051 :   inline CallIndirectOperand(Decoder* decoder, const byte* pc) {
     254        6051 :     unsigned len = 0;
     255       12102 :     index = decoder->read_u32v<validate>(pc + 1, &len, "signature index");
     256       11629 :     table_index = decoder->read_u8<validate>(pc + 1 + len, "table index");
     257        5578 :     if (!VALIDATE(table_index == 0)) {
     258           0 :       decoder->errorf(pc + 1 + len, "expected table index 0, found %u",
     259           0 :                       table_index);
     260             :     }
     261        6051 :     length = 1 + len;
     262        6051 :   }
     263             : };
     264             : 
     265             : template <Decoder::ValidateFlag validate>
     266             : struct CallFunctionOperand {
     267             :   uint32_t index;
     268             :   FunctionSig* sig = nullptr;
     269             :   unsigned length;
     270     1293125 :   inline CallFunctionOperand(Decoder* decoder, const byte* pc) {
     271     2586232 :     index = decoder->read_u32v<validate>(pc + 1, &length, "function index");
     272             :   }
     273             : };
     274             : 
     275             : template <Decoder::ValidateFlag validate>
     276             : struct MemoryIndexOperand {
     277             :   uint32_t index;
     278             :   unsigned length = 1;
     279        2007 :   inline MemoryIndexOperand(Decoder* decoder, const byte* pc) {
     280        4079 :     index = decoder->read_u8<validate>(pc + 1, "memory index");
     281        2008 :     if (!VALIDATE(index == 0)) {
     282          10 :       decoder->errorf(pc + 1, "expected memory index 0, found %u", index);
     283             :     }
     284        2008 :   }
     285             : };
     286             : 
     287             : template <Decoder::ValidateFlag validate>
     288             : struct BranchTableOperand {
     289             :   uint32_t table_count;
     290             :   const byte* start;
     291             :   const byte* table;
     292      361256 :   inline BranchTableOperand(Decoder* decoder, const byte* pc) {
     293             :     DCHECK_EQ(kExprBrTable, decoder->read_u8<validate>(pc, "opcode"));
     294      361256 :     start = pc + 1;
     295      361256 :     unsigned len = 0;
     296      361256 :     table_count = decoder->read_u32v<validate>(pc + 1, &len, "table count");
     297      361256 :     table = pc + 1 + len;
     298      361256 :   }
     299             : };
     300             : 
     301             : // A helper to iterate over a branch table.
     302             : template <Decoder::ValidateFlag validate>
     303             : class BranchTableIterator {
     304             :  public:
     305             :   unsigned cur_index() { return index_; }
     306     1906124 :   bool has_next() { return decoder_->ok() && index_ <= table_count_; }
     307     2186583 :   uint32_t next() {
     308             :     DCHECK(has_next());
     309     2186583 :     index_++;
     310             :     unsigned length;
     311             :     uint32_t result =
     312     2186583 :         decoder_->read_u32v<validate>(pc_, &length, "branch table entry");
     313     2186565 :     pc_ += length;
     314     2186565 :     return result;
     315             :   }
     316             :   // length, including the length of the {BranchTableOperand}, but not the
     317             :   // opcode.
     318       22045 :   unsigned length() {
     319       69549 :     while (has_next()) next();
     320       22045 :     return static_cast<unsigned>(pc_ - start_);
     321             :   }
     322             :   const byte* pc() { return pc_; }
     323             : 
     324             :   BranchTableIterator(Decoder* decoder,
     325             :                       const BranchTableOperand<validate>& operand)
     326             :       : decoder_(decoder),
     327             :         start_(operand.start),
     328             :         pc_(operand.table),
     329             :         index_(0),
     330      374867 :         table_count_(operand.table_count) {}
     331             : 
     332             :  private:
     333             :   Decoder* decoder_;
     334             :   const byte* start_;
     335             :   const byte* pc_;
     336             :   uint32_t index_;        // the current index.
     337             :   uint32_t table_count_;  // the count of entries, not including default.
     338             : };
     339             : 
     340             : template <Decoder::ValidateFlag validate>
     341             : struct MemoryAccessOperand {
     342             :   uint32_t alignment;
     343             :   uint32_t offset;
     344             :   unsigned length;
     345      202833 :   inline MemoryAccessOperand(Decoder* decoder, const byte* pc,
     346             :                              uint32_t max_alignment) {
     347             :     unsigned alignment_length;
     348      405670 :     alignment =
     349             :         decoder->read_u32v<validate>(pc + 1, &alignment_length, "alignment");
     350       73850 :     if (!VALIDATE(alignment <= max_alignment)) {
     351         218 :       decoder->errorf(pc + 1,
     352             :                       "invalid alignment; expected maximum alignment is %u, "
     353             :                       "actual alignment is %u",
     354             :                       max_alignment, alignment);
     355             :     }
     356             :     unsigned offset_length;
     357      405670 :     offset = decoder->read_u32v<validate>(pc + 1 + alignment_length,
     358             :                                           &offset_length, "offset");
     359      202833 :     length = alignment_length + offset_length;
     360      202833 :   }
     361             : };
     362             : 
     363             : // Operand for SIMD lane operations.
     364             : template <Decoder::ValidateFlag validate>
     365             : struct SimdLaneOperand {
     366             :   uint8_t lane;
     367             :   unsigned length = 1;
     368             : 
     369       12654 :   inline SimdLaneOperand(Decoder* decoder, const byte* pc) {
     370       25308 :     lane = decoder->read_u8<validate>(pc + 2, "lane");
     371             :   }
     372             : };
     373             : 
     374             : // Operand for SIMD shift operations.
     375             : template <Decoder::ValidateFlag validate>
     376             : struct SimdShiftOperand {
     377             :   uint8_t shift;
     378             :   unsigned length = 1;
     379             : 
     380          72 :   inline SimdShiftOperand(Decoder* decoder, const byte* pc) {
     381         144 :     shift = decoder->read_u8<validate>(pc + 2, "shift");
     382             :   }
     383             : };
     384             : 
     385             : // Operand for SIMD S8x16 shuffle operations.
     386             : template <Decoder::ValidateFlag validate>
     387             : struct Simd8x16ShuffleOperand {
     388             :   uint8_t shuffle[kSimd128Size];
     389             : 
     390           0 :   inline Simd8x16ShuffleOperand(Decoder* decoder, const byte* pc) {
     391           0 :     for (uint32_t i = 0; i < kSimd128Size; ++i) {
     392           0 :       shuffle[i] = decoder->read_u8<validate>(pc + 2 + i, "shuffle");
     393             :     }
     394           0 :   }
     395             : };
     396             : 
     397             : // An entry on the value stack.
     398             : struct ValueBase {
     399             :   const byte* pc;
     400             :   ValueType type;
     401             : 
     402             :   // Named constructors.
     403             :   static ValueBase Unreachable(const byte* pc) { return {pc, kWasmVar}; }
     404             : 
     405             :   static ValueBase New(const byte* pc, ValueType type) { return {pc, type}; }
     406             : };
     407             : 
     408             : template <typename Value>
     409             : struct Merge {
     410             :   uint32_t arity;
     411             :   union {
     412             :     Value* array;
     413             :     Value first;
     414             :   } vals;  // Either multiple values or a single value.
     415             : 
     416             :   // Tracks whether this merge was ever reached. Uses precise reachability, like
     417             :   // Reachability::kReachable.
     418             :   bool reached;
     419             : 
     420      867638 :   Merge(bool reached = false) : reached(reached) {}
     421             : 
     422             :   Value& operator[](uint32_t i) {
     423             :     DCHECK_GT(arity, i);
     424      227513 :     return arity == 1 ? vals.first : vals.array[i];
     425             :   }
     426             : };
     427             : 
     428             : enum ControlKind : uint8_t {
     429             :   kControlIf,
     430             :   kControlIfElse,
     431             :   kControlBlock,
     432             :   kControlLoop,
     433             :   kControlTry,
     434             :   kControlTryCatch
     435             : };
     436             : 
     437             : enum Reachability : uint8_t {
     438             :   // reachable code.
     439             :   kReachable,
     440             :   // reachable code in unreachable block (implies normal validation).
     441             :   kSpecOnlyReachable,
     442             :   // code unreachable in its own block (implies polymorphic validation).
     443             :   kUnreachable
     444             : };
     445             : 
     446             : // An entry on the control stack (i.e. if, block, loop, or try).
     447             : template <typename Value>
     448             : struct ControlBase {
     449             :   Reachability reachability = kReachable;
     450             :   ControlKind kind;
     451             :   uint32_t stack_depth;  // stack height at the beginning of the construct.
     452             :   const byte* pc;
     453             : 
     454             :   // Values merged into the end of this control construct.
     455             :   Merge<Value> merge;
     456             : 
     457      549948 :   ControlBase() = default;
     458             :   ControlBase(ControlKind kind, uint32_t stack_depth, const byte* pc,
     459             :               bool merge_reached = false)
     460      317690 :       : kind(kind), stack_depth(stack_depth), pc(pc), merge(merge_reached) {}
     461             : 
     462             :   // Check whether the current block is reachable.
     463       30584 :   bool reachable() const { return reachability == kReachable; }
     464             : 
     465             :   // Check whether the rest of the block is unreachable.
     466             :   // Note that this is different from {!reachable()}, as there is also the
     467             :   // "indirect unreachable state", for which both {reachable()} and
     468             :   // {unreachable()} return false.
     469             :   bool unreachable() const { return reachability == kUnreachable; }
     470             : 
     471             :   // Return the reachability of new control structs started in this block.
     472             :   Reachability innerReachability() const {
     473      487152 :     return reachability == kReachable ? kReachable : kSpecOnlyReachable;
     474             :   }
     475             : 
     476       24884 :   bool is_if() const { return is_onearmed_if() || is_if_else(); }
     477             :   bool is_onearmed_if() const { return kind == kControlIf; }
     478             :   bool is_if_else() const { return kind == kControlIfElse; }
     479             :   bool is_block() const { return kind == kControlBlock; }
     480             :   bool is_loop() const { return kind == kControlLoop; }
     481          74 :   bool is_try() const { return is_incomplete_try() || is_try_catch(); }
     482             :   bool is_incomplete_try() const { return kind == kControlTry; }
     483             :   bool is_try_catch() const { return kind == kControlTryCatch; }
     484             : 
     485             :   // Named constructors.
     486             :   static ControlBase Block(const byte* pc, uint32_t stack_depth) {
     487             :     return {kControlBlock, stack_depth, pc};
     488             :   }
     489             : 
     490             :   static ControlBase If(const byte* pc, uint32_t stack_depth) {
     491             :     return {kControlIf, stack_depth, pc};
     492             :   }
     493             : 
     494             :   static ControlBase Loop(const byte* pc, uint32_t stack_depth, bool reached) {
     495             :     return {kControlLoop, stack_depth, pc, reached};
     496             :   }
     497             : 
     498             :   static ControlBase Try(const byte* pc, uint32_t stack_depth) {
     499             :     return {kControlTry, stack_depth, pc};
     500             :   }
     501             : };
     502             : 
     503             : #define CONCRETE_NAMED_CONSTRUCTOR(concrete_type, abstract_type, name) \
     504             :   template <typename... Args>                                          \
     505             :   static concrete_type name(Args&&... args) {                          \
     506             :     concrete_type val;                                                 \
     507             :     static_cast<abstract_type&>(val) =                                 \
     508             :         abstract_type::name(std::forward<Args>(args)...);              \
     509             :     return val;                                                        \
     510             :   }
     511             : 
     512             : // Provide the default named constructors, which default-initialize the
     513             : // ConcreteType and the initialize the fields of ValueBase correctly.
     514             : // Use like this:
     515             : // struct Value : public ValueWithNamedConstructors<Value> { int new_field; };
     516             : template <typename ConcreteType>
     517             : struct ValueWithNamedConstructors : public ValueBase {
     518             :   // Named constructors.
     519       12342 :   CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ValueBase, Unreachable)
     520     3614188 :   CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ValueBase, New)
     521             : };
     522             : 
     523             : // Provide the default named constructors, which default-initialize the
     524             : // ConcreteType and the initialize the fields of ControlBase correctly.
     525             : // Use like this:
     526             : // struct Control : public ControlWithNamedConstructors<Control, Value> {
     527             : //   int my_uninitialized_field;
     528             : //   char* other_field = nullptr;
     529             : // };
     530             : template <typename ConcreteType, typename Value>
     531             : struct ControlWithNamedConstructors : public ControlBase<Value> {
     532             :   // Named constructors.
     533      476098 :   CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Block)
     534       62117 :   CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, If)
     535       11663 :   CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Loop)
     536          70 :   CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Try)
     537             : };
     538             : 
     539             : // This is the list of callback functions that an interface for the
     540             : // WasmFullDecoder should implement.
     541             : // F(Name, args...)
     542             : #define INTERFACE_FUNCTIONS(F)                                                 \
     543             :   /* General: */                                                               \
     544             :   F(StartFunction)                                                             \
     545             :   F(StartFunctionBody, Control* block)                                         \
     546             :   F(FinishFunction)                                                            \
     547             :   F(OnFirstError)                                                              \
     548             :   /* Control: */                                                               \
     549             :   F(Block, Control* block)                                                     \
     550             :   F(Loop, Control* block)                                                      \
     551             :   F(Try, Control* block)                                                       \
     552             :   F(If, const Value& cond, Control* if_block)                                  \
     553             :   F(FallThruTo, Control* c)                                                    \
     554             :   F(PopControl, Control* block)                                                \
     555             :   F(EndControl, Control* block)                                                \
     556             :   /* Instructions: */                                                          \
     557             :   F(UnOp, WasmOpcode opcode, FunctionSig*, const Value& value, Value* result)  \
     558             :   F(BinOp, WasmOpcode opcode, FunctionSig*, const Value& lhs,                  \
     559             :     const Value& rhs, Value* result)                                           \
     560             :   F(I32Const, Value* result, int32_t value)                                    \
     561             :   F(I64Const, Value* result, int64_t value)                                    \
     562             :   F(F32Const, Value* result, float value)                                      \
     563             :   F(F64Const, Value* result, double value)                                     \
     564             :   F(Drop, const Value& value)                                                  \
     565             :   F(DoReturn, Vector<Value> values, bool implicit)                             \
     566             :   F(GetLocal, Value* result, const LocalIndexOperand<validate>& operand)       \
     567             :   F(SetLocal, const Value& value, const LocalIndexOperand<validate>& operand)  \
     568             :   F(TeeLocal, const Value& value, Value* result,                               \
     569             :     const LocalIndexOperand<validate>& operand)                                \
     570             :   F(GetGlobal, Value* result, const GlobalIndexOperand<validate>& operand)     \
     571             :   F(SetGlobal, const Value& value,                                             \
     572             :     const GlobalIndexOperand<validate>& operand)                               \
     573             :   F(Unreachable)                                                               \
     574             :   F(Select, const Value& cond, const Value& fval, const Value& tval,           \
     575             :     Value* result)                                                             \
     576             :   F(BreakTo, Control* target)                                                  \
     577             :   F(BrIf, const Value& cond, Control* target)                                  \
     578             :   F(BrTable, const BranchTableOperand<validate>& operand, const Value& key)    \
     579             :   F(Else, Control* if_block)                                                   \
     580             :   F(LoadMem, ValueType type, MachineType mem_type,                             \
     581             :     const MemoryAccessOperand<validate>& operand, const Value& index,          \
     582             :     Value* result)                                                             \
     583             :   F(StoreMem, ValueType type, MachineType mem_type,                            \
     584             :     const MemoryAccessOperand<validate>& operand, const Value& index,          \
     585             :     const Value& value)                                                        \
     586             :   F(CurrentMemoryPages, Value* result)                                         \
     587             :   F(GrowMemory, const Value& value, Value* result)                             \
     588             :   F(CallDirect, const CallFunctionOperand<validate>& operand,                  \
     589             :     const Value args[], Value returns[])                                       \
     590             :   F(CallIndirect, const Value& index,                                          \
     591             :     const CallIndirectOperand<validate>& operand, const Value args[],          \
     592             :     Value returns[])                                                           \
     593             :   F(SimdOp, WasmOpcode opcode, Vector<Value> args, Value* result)              \
     594             :   F(SimdLaneOp, WasmOpcode opcode, const SimdLaneOperand<validate>& operand,   \
     595             :     const Vector<Value> inputs, Value* result)                                 \
     596             :   F(SimdShiftOp, WasmOpcode opcode, const SimdShiftOperand<validate>& operand, \
     597             :     const Value& input, Value* result)                                         \
     598             :   F(Simd8x16ShuffleOp, const Simd8x16ShuffleOperand<validate>& operand,        \
     599             :     const Value& input0, const Value& input1, Value* result)                   \
     600             :   F(Throw, const ExceptionIndexOperand<validate>&, Control* block,             \
     601             :     const Vector<Value>& args)                                                 \
     602             :   F(CatchException, const ExceptionIndexOperand<validate>& operand,            \
     603             :     Control* block, Vector<Value> caught_values)                               \
     604             :   F(AtomicOp, WasmOpcode opcode, Vector<Value> args,                           \
     605             :     const MemoryAccessOperand<validate>& operand, Value* result)
     606             : 
     607             : // Generic Wasm bytecode decoder with utilities for decoding operands,
     608             : // lengths, etc.
     609             : template <Decoder::ValidateFlag validate>
     610      584625 : class WasmDecoder : public Decoder {
     611             :  public:
     612             :   WasmDecoder(const WasmModule* module, FunctionSig* sig, const byte* start,
     613             :               const byte* end, uint32_t buffer_offset = 0)
     614             :       : Decoder(start, end, buffer_offset),
     615             :         module_(module),
     616             :         sig_(sig),
     617      584784 :         local_types_(nullptr) {}
     618             :   const WasmModule* module_;
     619             :   FunctionSig* sig_;
     620             : 
     621             :   ZoneVector<ValueType>* local_types_;
     622             : 
     623             :   uint32_t total_locals() const {
     624             :     return local_types_ == nullptr
     625             :                ? 0
     626     1687082 :                : static_cast<uint32_t>(local_types_->size());
     627             :   }
     628             : 
     629      439394 :   static bool DecodeLocals(Decoder* decoder, const FunctionSig* sig,
     630             :                            ZoneVector<ValueType>* type_list) {
     631             :     DCHECK_NOT_NULL(type_list);
     632             :     DCHECK_EQ(0, type_list->size());
     633             :     // Initialize from signature.
     634      425961 :     if (sig != nullptr) {
     635      418858 :       type_list->assign(sig->parameters().begin(), sig->parameters().end());
     636             :     }
     637             :     // Decode local declarations, if any.
     638             :     uint32_t entries = decoder->consume_u32v("local decls count");
     639      426074 :     if (decoder->failed()) return false;
     640             : 
     641             :     TRACE("local decls count: %u\n", entries);
     642      466196 :     while (entries-- > 0 && decoder->ok() && decoder->more()) {
     643             :       uint32_t count = decoder->consume_u32v("local count");
     644       13437 :       if (decoder->failed()) return false;
     645             : 
     646       13389 :       if ((count + type_list->size()) > kV8MaxWasmFunctionLocals) {
     647           3 :         decoder->error(decoder->pc() - 1, "local count too large");
     648           3 :         return false;
     649             :       }
     650             :       byte code = decoder->consume_u8("local type");
     651       13386 :       if (decoder->failed()) return false;
     652             : 
     653             :       ValueType type;
     654       13385 :       switch (code) {
     655             :         case kLocalI32:
     656        7236 :           type = kWasmI32;
     657        7236 :           break;
     658             :         case kLocalI64:
     659        1411 :           type = kWasmI64;
     660        1411 :           break;
     661             :         case kLocalF32:
     662        1267 :           type = kWasmF32;
     663        1267 :           break;
     664             :         case kLocalF64:
     665        2436 :           type = kWasmF64;
     666        2436 :           break;
     667             :         case kLocalS128:
     668        1006 :           if (FLAG_experimental_wasm_simd) {
     669         996 :             type = kWasmS128;
     670         996 :             break;
     671             :           }
     672             :         // else fall through to default.
     673             :         default:
     674          39 :           decoder->error(decoder->pc() - 1, "invalid local type");
     675          40 :           return false;
     676             :       }
     677       13346 :       type_list->insert(type_list->end(), count, type);
     678             :     }
     679             :     DCHECK(decoder->ok());
     680             :     return true;
     681             :   }
     682             : 
     683     2152493 :   static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc,
     684             :                                           uint32_t locals_count, Zone* zone) {
     685       11700 :     if (pc >= decoder->end()) return nullptr;
     686       11701 :     if (*pc != kExprLoop) return nullptr;
     687             : 
     688             :     // The number of locals_count is augmented by 2 so that 'locals_count - 2'
     689             :     // can be used to track mem_size, and 'locals_count - 1' to track mem_start.
     690      163750 :     BitVector* assigned = new (zone) BitVector(locals_count, zone);
     691             :     int depth = 0;
     692             :     // Iteratively process all AST nodes nested inside the loop.
     693     4293275 :     while (pc < decoder->end() && decoder->ok()) {
     694     2140807 :       WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
     695             :       unsigned length = 1;
     696     2140807 :       switch (opcode) {
     697             :         case kExprLoop:
     698             :         case kExprIf:
     699             :         case kExprBlock:
     700             :         case kExprTry:
     701      111290 :           length = OpcodeLength(decoder, pc);
     702      111294 :           depth++;
     703      111294 :           break;
     704             :         case kExprSetLocal:  // fallthru
     705             :         case kExprTeeLocal: {
     706             :           LocalIndexOperand<Decoder::kValidate> operand(decoder, pc);
     707      152049 :           if (assigned->length() > 0 &&
     708             :               operand.index < static_cast<uint32_t>(assigned->length())) {
     709             :             // Unverified code might have an out-of-bounds index.
     710      152048 :             assigned->Add(operand.index);
     711             :           }
     712      152049 :           length = 1 + operand.length;
     713             :           break;
     714             :         }
     715             :         case kExprGrowMemory:
     716             :         case kExprCallFunction:
     717             :         case kExprCallIndirect:
     718             :           // Add mem_size and mem_start to the assigned set.
     719       23269 :           assigned->Add(locals_count - 2);  // mem_size
     720       23269 :           assigned->Add(locals_count - 1);  // mem_start
     721       23269 :           length = OpcodeLength(decoder, pc);
     722       23269 :           break;
     723             :         case kExprEnd:
     724      111292 :           depth--;
     725      111292 :           break;
     726             :         default:
     727     1742907 :           length = OpcodeLength(decoder, pc);
     728     1742930 :           break;
     729             :       }
     730     2140834 :       if (depth <= 0) break;
     731     2129118 :       pc += length;
     732             :     }
     733       11702 :     return decoder->ok() ? assigned : nullptr;
     734             :   }
     735             : 
     736      808688 :   inline bool Validate(const byte* pc,
     737      808688 :                        LocalIndexOperand<Decoder::kValidate>& operand) {
     738     1617376 :     if (!VALIDATE(operand.index < total_locals())) {
     739         413 :       errorf(pc + 1, "invalid local index: %u", operand.index);
     740         413 :       return false;
     741             :     }
     742     1616528 :     operand.type = local_types_ ? local_types_->at(operand.index) : kWasmStmt;
     743      808275 :     return true;
     744             :   }
     745             : 
     746         218 :   inline bool Validate(const byte* pc,
     747             :                        ExceptionIndexOperand<validate>& operand) {
     748         653 :     if (!VALIDATE(module_ != nullptr &&
     749             :                   operand.index < module_->exceptions.size())) {
     750           1 :       errorf(pc + 1, "Invalid exception index: %u", operand.index);
     751             :       return false;
     752             :     }
     753         434 :     operand.exception = &module_->exceptions[operand.index];
     754             :     return true;
     755             :   }
     756             : 
     757       31880 :   inline bool Validate(const byte* pc, GlobalIndexOperand<validate>& operand) {
     758       95619 :     if (!VALIDATE(module_ != nullptr &&
     759             :                   operand.index < module_->globals.size())) {
     760          20 :       errorf(pc + 1, "invalid global index: %u", operand.index);
     761          20 :       return false;
     762             :     }
     763       63720 :     operand.global = &module_->globals[operand.index];
     764       31860 :     operand.type = operand.global->type;
     765       31860 :     return true;
     766             :   }
     767             : 
     768             :   inline bool Complete(const byte* pc, CallFunctionOperand<validate>& operand) {
     769      931711 :     if (!VALIDATE(module_ != nullptr &&
     770             :                   operand.index < module_->functions.size())) {
     771             :       return false;
     772             :     }
     773      627576 :     operand.sig = module_->functions[operand.index].sig;
     774             :     return true;
     775             :   }
     776             : 
     777      310561 :   inline bool Validate(const byte* pc, CallFunctionOperand<validate>& operand) {
     778      310561 :     if (Complete(pc, operand)) {
     779             :       return true;
     780             :     }
     781          60 :     errorf(pc + 1, "invalid function index: %u", operand.index);
     782          60 :     return false;
     783             :   }
     784             : 
     785             :   inline bool Complete(const byte* pc, CallIndirectOperand<validate>& operand) {
     786       13019 :     if (!VALIDATE(module_ != nullptr &&
     787             :                   operand.index < module_->signatures.size())) {
     788             :       return false;
     789             :     }
     790        8730 :     operand.sig = module_->signatures[operand.index];
     791             :     return true;
     792             :   }
     793             : 
     794        4380 :   inline bool Validate(const byte* pc, CallIndirectOperand<validate>& operand) {
     795        8760 :     if (!VALIDATE(module_ != nullptr && !module_->function_tables.empty())) {
     796          23 :       error("function table has to exist to execute call_indirect");
     797          23 :       return false;
     798             :     }
     799        4357 :     if (!Complete(pc, operand)) {
     800          52 :       errorf(pc + 1, "invalid signature index: #%u", operand.index);
     801          52 :       return false;
     802             :     }
     803             :     return true;
     804             :   }
     805             : 
     806             :   inline bool Validate(const byte* pc, BreakDepthOperand<validate>& operand,
     807             :                        size_t control_depth) {
     808      328071 :     if (!VALIDATE(operand.depth < control_depth)) {
     809         601 :       errorf(pc + 1, "invalid break depth: %u", operand.depth);
     810             :       return false;
     811             :     }
     812             :     return true;
     813             :   }
     814             : 
     815       15617 :   bool Validate(const byte* pc, BranchTableOperand<validate>& operand,
     816             :                 size_t block_depth) {
     817       15617 :     if (!VALIDATE(operand.table_count < kV8MaxWasmFunctionSize)) {
     818          20 :       errorf(pc + 1, "invalid table count (> max function size): %u",
     819             :              operand.table_count);
     820             :       return false;
     821             :     }
     822       15597 :     return checkAvailable(operand.table_count);
     823             :   }
     824             : 
     825       12654 :   inline bool Validate(const byte* pc, WasmOpcode opcode,
     826             :                        SimdLaneOperand<validate>& operand) {
     827             :     uint8_t num_lanes = 0;
     828       12654 :     switch (opcode) {
     829             :       case kExprF32x4ExtractLane:
     830             :       case kExprF32x4ReplaceLane:
     831             :       case kExprI32x4ExtractLane:
     832             :       case kExprI32x4ReplaceLane:
     833             :         num_lanes = 4;
     834             :         break;
     835             :       case kExprI16x8ExtractLane:
     836             :       case kExprI16x8ReplaceLane:
     837             :         num_lanes = 8;
     838             :         break;
     839             :       case kExprI8x16ExtractLane:
     840             :       case kExprI8x16ReplaceLane:
     841             :         num_lanes = 16;
     842             :         break;
     843             :       default:
     844           0 :         UNREACHABLE();
     845             :         break;
     846             :     }
     847       12654 :     if (!VALIDATE(operand.lane >= 0 && operand.lane < num_lanes)) {
     848           0 :       error(pc_ + 2, "invalid lane index");
     849             :       return false;
     850             :     } else {
     851             :       return true;
     852             :     }
     853             :   }
     854             : 
     855          72 :   inline bool Validate(const byte* pc, WasmOpcode opcode,
     856             :                        SimdShiftOperand<validate>& operand) {
     857             :     uint8_t max_shift = 0;
     858          72 :     switch (opcode) {
     859             :       case kExprI32x4Shl:
     860             :       case kExprI32x4ShrS:
     861             :       case kExprI32x4ShrU:
     862             :         max_shift = 32;
     863             :         break;
     864             :       case kExprI16x8Shl:
     865             :       case kExprI16x8ShrS:
     866             :       case kExprI16x8ShrU:
     867             :         max_shift = 16;
     868             :         break;
     869             :       case kExprI8x16Shl:
     870             :       case kExprI8x16ShrS:
     871             :       case kExprI8x16ShrU:
     872             :         max_shift = 8;
     873             :         break;
     874             :       default:
     875           0 :         UNREACHABLE();
     876             :         break;
     877             :     }
     878          72 :     if (!VALIDATE(operand.shift >= 0 && operand.shift < max_shift)) {
     879           0 :       error(pc_ + 2, "invalid shift amount");
     880             :       return false;
     881             :     } else {
     882             :       return true;
     883             :     }
     884             :   }
     885             : 
     886           0 :   inline bool Validate(const byte* pc,
     887             :                        Simd8x16ShuffleOperand<validate>& operand) {
     888           0 :     uint8_t max_lane = 0;
     889           0 :     for (uint32_t i = 0; i < kSimd128Size; ++i)
     890           0 :       max_lane = std::max(max_lane, operand.shuffle[i]);
     891             :     // Shuffle indices must be in [0..31] for a 16 lane shuffle.
     892           0 :     if (!VALIDATE(max_lane <= 2 * kSimd128Size)) {
     893           0 :       error(pc_ + 2, "invalid shuffle mask");
     894             :       return false;
     895             :     }
     896             :     return true;
     897             :   }
     898             : 
     899     2091788 :   static unsigned OpcodeLength(Decoder* decoder, const byte* pc) {
     900     2091788 :     WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
     901     2091788 :     switch (opcode) {
     902             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
     903             :       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
     904             :       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
     905             : #undef DECLARE_OPCODE_CASE
     906             :       {
     907        9467 :         MemoryAccessOperand<validate> operand(decoder, pc, UINT32_MAX);
     908        9465 :         return 1 + operand.length;
     909             :       }
     910             :       case kExprBr:
     911             :       case kExprBrIf: {
     912             :         BreakDepthOperand<validate> operand(decoder, pc);
     913       74085 :         return 1 + operand.length;
     914             :       }
     915             :       case kExprSetGlobal:
     916             :       case kExprGetGlobal: {
     917        4455 :         GlobalIndexOperand<validate> operand(decoder, pc);
     918        4668 :         return 1 + operand.length;
     919             :       }
     920             : 
     921             :       case kExprCallFunction: {
     922             :         CallFunctionOperand<validate> operand(decoder, pc);
     923       25280 :         return 1 + operand.length;
     924             :       }
     925             :       case kExprCallIndirect: {
     926        1264 :         CallIndirectOperand<validate> operand(decoder, pc);
     927        1264 :         return 1 + operand.length;
     928             :       }
     929             : 
     930             :       case kExprTry:
     931             :       case kExprIf:  // fall through
     932             :       case kExprLoop:
     933             :       case kExprBlock: {
     934      143920 :         BlockTypeOperand<validate> operand(decoder, pc);
     935      143922 :         return 1 + operand.length;
     936             :       }
     937             : 
     938             :       case kExprThrow:
     939             :       case kExprCatch: {
     940             :         ExceptionIndexOperand<validate> operand(decoder, pc);
     941           2 :         return 1 + operand.length;
     942             :       }
     943             : 
     944             :       case kExprSetLocal:
     945             :       case kExprTeeLocal:
     946             :       case kExprGetLocal: {
     947             :         LocalIndexOperand<Decoder::kValidate> operand(decoder, pc);
     948      431762 :         return 1 + operand.length;
     949             :       }
     950             :       case kExprBrTable: {
     951        6430 :         BranchTableOperand<validate> operand(decoder, pc);
     952             :         BranchTableIterator<validate> iterator(decoder, operand);
     953        6430 :         return 1 + iterator.length();
     954             :       }
     955             :       case kExprI32Const: {
     956             :         ImmI32Operand<validate> operand(decoder, pc);
     957      451809 :         return 1 + operand.length;
     958             :       }
     959             :       case kExprI64Const: {
     960             :         ImmI64Operand<validate> operand(decoder, pc);
     961        3889 :         return 1 + operand.length;
     962             :       }
     963             :       case kExprGrowMemory:
     964             :       case kExprMemorySize: {
     965          80 :         MemoryIndexOperand<validate> operand(decoder, pc);
     966          80 :         return 1 + operand.length;
     967             :       }
     968             :       case kExprF32Const:
     969             :         return 5;
     970             :       case kExprF64Const:
     971        5061 :         return 9;
     972             :       case kSimdPrefix: {
     973         166 :         byte simd_index = decoder->read_u8<validate>(pc + 1, "simd_index");
     974             :         WasmOpcode opcode =
     975         154 :             static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
     976         154 :         switch (opcode) {
     977             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
     978             :           FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
     979             : #undef DECLARE_OPCODE_CASE
     980             :           return 2;
     981             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
     982             :           FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
     983             : #undef DECLARE_OPCODE_CASE
     984          17 :           return 3;
     985             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
     986             :           FOREACH_SIMD_MEM_OPCODE(DECLARE_OPCODE_CASE)
     987             : #undef DECLARE_OPCODE_CASE
     988             :           {
     989           0 :             MemoryAccessOperand<validate> operand(decoder, pc + 1, UINT32_MAX);
     990           0 :             return 2 + operand.length;
     991             :           }
     992             :           // Shuffles require a byte per lane, or 16 immediate bytes.
     993             :           case kExprS8x16Shuffle:
     994           1 :             return 2 + kSimd128Size;
     995             :           default:
     996             :             decoder->error(pc, "invalid SIMD opcode");
     997           1 :             return 2;
     998             :         }
     999             :       }
    1000             :       case kAtomicPrefix: {
    1001          20 :         byte atomic_index = decoder->read_u8<validate>(pc + 1, "atomic_index");
    1002             :         WasmOpcode opcode =
    1003          32 :             static_cast<WasmOpcode>(kAtomicPrefix << 8 | atomic_index);
    1004             :         switch (opcode) {
    1005             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1006             :           FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE)
    1007             : #undef DECLARE_OPCODE_CASE
    1008             :           {
    1009          32 :             MemoryAccessOperand<validate> operand(decoder, pc + 1, UINT32_MAX);
    1010          32 :             return 2 + operand.length;
    1011             :           }
    1012             :           default:
    1013             :             decoder->error(pc, "invalid Atomics opcode");
    1014           0 :             return 2;
    1015             :         }
    1016             :       }
    1017             :       default:
    1018      933296 :         return 1;
    1019             :     }
    1020             :   }
    1021             : 
    1022      182613 :   std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) {
    1023      179323 :     WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
    1024             :     // Handle "simple" opcodes with a fixed signature first.
    1025      183939 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
    1026      179323 :     if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode);
    1027      183939 :     if (sig) return {sig->parameter_count(), sig->return_count()};
    1028      174707 :     if (WasmOpcodes::IsPrefixOpcode(opcode)) {
    1029           0 :       opcode = static_cast<WasmOpcode>(opcode << 8 | *(pc + 1));
    1030             :     }
    1031             : 
    1032             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
    1033             :     // clang-format off
    1034      174707 :     switch (opcode) {
    1035             :       case kExprSelect:
    1036          30 :         return {3, 1};
    1037             :       case kExprS128StoreMem:
    1038             :       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1039         798 :         return {2, 0};
    1040             :       case kExprS128LoadMem:
    1041             :       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
    1042             :       case kExprTeeLocal:
    1043             :       case kExprGrowMemory:
    1044        8308 :         return {1, 1};
    1045             :       case kExprSetLocal:
    1046             :       case kExprSetGlobal:
    1047             :       case kExprDrop:
    1048             :       case kExprBrIf:
    1049             :       case kExprBrTable:
    1050             :       case kExprIf:
    1051        9015 :         return {1, 0};
    1052             :       case kExprGetLocal:
    1053             :       case kExprGetGlobal:
    1054             :       case kExprI32Const:
    1055             :       case kExprI64Const:
    1056             :       case kExprF32Const:
    1057             :       case kExprF64Const:
    1058             :       case kExprMemorySize:
    1059       73004 :         return {0, 1};
    1060             :       case kExprCallFunction: {
    1061             :         CallFunctionOperand<validate> operand(this, pc);
    1062             :         CHECK(Complete(pc, operand));
    1063        6460 :         return {operand.sig->parameter_count(), operand.sig->return_count()};
    1064             :       }
    1065             :       case kExprCallIndirect: {
    1066          60 :         CallIndirectOperand<validate> operand(this, pc);
    1067          60 :         CHECK(Complete(pc, operand));
    1068             :         // Indirect calls pop an additional argument for the table index.
    1069             :         return {operand.sig->parameter_count() + 1,
    1070         120 :                 operand.sig->return_count()};
    1071             :       }
    1072             :       case kExprBr:
    1073             :       case kExprBlock:
    1074             :       case kExprLoop:
    1075             :       case kExprEnd:
    1076             :       case kExprElse:
    1077             :       case kExprNop:
    1078             :       case kExprReturn:
    1079             :       case kExprUnreachable:
    1080       80262 :         return {0, 0};
    1081             :       default:
    1082           0 :         V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x (%s)", opcode,
    1083           0 :                  WasmOpcodes::OpcodeName(opcode));
    1084             :         return {0, 0};
    1085             :     }
    1086             : #undef DECLARE_OPCODE_CASE
    1087             :     // clang-format on
    1088             :   }
    1089             : };
    1090             : 
    1091             : #define CALL_INTERFACE(name, ...) interface_.name(this, ##__VA_ARGS__)
    1092             : #define CALL_INTERFACE_IF_REACHABLE(name, ...)       \
    1093             :   do {                                               \
    1094             :     DCHECK(!control_.empty());                       \
    1095             :     if (this->ok() && control_.back().reachable()) { \
    1096             :       interface_.name(this, ##__VA_ARGS__);          \
    1097             :     }                                                \
    1098             :   } while (false)
    1099             : #define CALL_INTERFACE_IF_PARENT_REACHABLE(name, ...)                         \
    1100             :   do {                                                                        \
    1101             :     DCHECK(!control_.empty());                                                \
    1102             :     if (this->ok() && (control_.size() == 1 || control_at(1)->reachable())) { \
    1103             :       interface_.name(this, ##__VA_ARGS__);                                   \
    1104             :     }                                                                         \
    1105             :   } while (false)
    1106             : 
    1107             : template <Decoder::ValidateFlag validate, typename Interface>
    1108      405302 : class WasmFullDecoder : public WasmDecoder<validate> {
    1109             :   using Value = typename Interface::Value;
    1110             :   using Control = typename Interface::Control;
    1111             :   using MergeValues = Merge<Value>;
    1112             : 
    1113             :   // All Value types should be trivially copyable for performance. We push, pop,
    1114             :   // and store them in local variables.
    1115             :   static_assert(IS_TRIVIALLY_COPYABLE(Value),
    1116             :                 "all Value<...> types should be trivially copyable");
    1117             : 
    1118             :  public:
    1119             :   template <typename... InterfaceArgs>
    1120             :   WasmFullDecoder(Zone* zone, const wasm::WasmModule* module,
    1121             :                   const FunctionBody& body, InterfaceArgs&&... interface_args)
    1122             :       : WasmDecoder<validate>(module, body.sig, body.start, body.end,
    1123             :                               body.offset),
    1124             :         zone_(zone),
    1125             :         interface_(std::forward<InterfaceArgs>(interface_args)...),
    1126             :         local_type_vec_(zone),
    1127             :         stack_(zone),
    1128             :         control_(zone),
    1129     1216383 :         last_end_found_(false) {
    1130      405461 :     this->local_types_ = &local_type_vec_;
    1131             :   }
    1132             : 
    1133             :   Interface& interface() { return interface_; }
    1134             : 
    1135      405464 :   bool Decode() {
    1136             :     DCHECK(stack_.empty());
    1137             :     DCHECK(control_.empty());
    1138             : 
    1139      405464 :     if (FLAG_wasm_code_fuzzer_gen_test) {
    1140           0 :       PrintRawWasmCode(this->start_, this->end_);
    1141             :     }
    1142             :     base::ElapsedTimer decode_timer;
    1143      405504 :     if (FLAG_trace_wasm_decode_time) {
    1144             :       decode_timer.Start();
    1145             :     }
    1146             : 
    1147      405504 :     if (this->end_ < this->pc_) {
    1148           0 :       this->error("function body end < start");
    1149           0 :       return false;
    1150             :     }
    1151             : 
    1152             :     DCHECK_EQ(0, this->local_types_->size());
    1153      405504 :     WasmDecoder<validate>::DecodeLocals(this, this->sig_, this->local_types_);
    1154      463059 :     CALL_INTERFACE(StartFunction);
    1155      405476 :     DecodeFunctionBody();
    1156      234320 :     if (!this->failed()) CALL_INTERFACE(FinishFunction);
    1157             : 
    1158      405278 :     if (this->failed()) return this->TraceFailed();
    1159             : 
    1160      383652 :     if (!control_.empty()) {
    1161             :       // Generate a better error message whether the unterminated control
    1162             :       // structure is the function body block or an innner structure.
    1163          28 :       if (control_.size() > 1) {
    1164           0 :         this->error(control_.back().pc, "unterminated control structure");
    1165             :       } else {
    1166             :         this->error("function body must end with \"end\" opcode");
    1167             :       }
    1168             :       return TraceFailed();
    1169             :     }
    1170             : 
    1171      383624 :     if (!last_end_found_) {
    1172             :       this->error("function body must end with \"end\" opcode");
    1173           0 :       return false;
    1174             :     }
    1175             : 
    1176      383624 :     if (FLAG_trace_wasm_decode_time) {
    1177           0 :       double ms = decode_timer.Elapsed().InMillisecondsF();
    1178           0 :       PrintF("wasm-decode %s (%0.3f ms)\n\n", this->ok() ? "ok" : "failed", ms);
    1179             :     } else {
    1180             :       TRACE("wasm-decode %s\n\n", this->ok() ? "ok" : "failed");
    1181             :     }
    1182             : 
    1183             :     return true;
    1184             :   }
    1185             : 
    1186             :   bool TraceFailed() {
    1187             :     TRACE("wasm-error module+%-6d func+%d: %s\n\n", this->error_offset_,
    1188             :           this->GetBufferRelativeOffset(this->error_offset_),
    1189             :           this->error_msg_.c_str());
    1190             :     return false;
    1191             :   }
    1192             : 
    1193             :   const char* SafeOpcodeNameAt(const byte* pc) {
    1194       39892 :     if (pc >= this->end_) return "<end>";
    1195       33566 :     return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(*pc));
    1196             :   }
    1197             : 
    1198             :   inline Zone* zone() const { return zone_; }
    1199             : 
    1200             :   inline uint32_t NumLocals() {
    1201     2204014 :     return static_cast<uint32_t>(local_type_vec_.size());
    1202             :   }
    1203             : 
    1204             :   inline ValueType GetLocalType(uint32_t index) {
    1205     1838184 :     return local_type_vec_[index];
    1206             :   }
    1207             : 
    1208             :   inline wasm::WasmCodePosition position() {
    1209     1701281 :     int offset = static_cast<int>(this->pc_ - this->start_);
    1210             :     DCHECK_EQ(this->pc_ - this->start_, offset);  // overflows cannot happen
    1211             :     return offset;
    1212             :   }
    1213             : 
    1214             :   inline uint32_t control_depth() const {
    1215         320 :     return static_cast<uint32_t>(control_.size());
    1216             :   }
    1217             : 
    1218             :   inline Control* control_at(uint32_t depth) {
    1219             :     DCHECK_GT(control_.size(), depth);
    1220     1173732 :     return &control_.back() - depth;
    1221             :   }
    1222             : 
    1223             :   inline uint32_t stack_size() const {
    1224     2968496 :     return static_cast<uint32_t>(stack_.size());
    1225             :   }
    1226             : 
    1227             :   inline Value* stack_value(uint32_t depth) {
    1228             :     DCHECK_GT(stack_.size(), depth);
    1229             :     return &stack_[stack_.size() - depth - 1];
    1230             :   }
    1231             : 
    1232             :   inline Value& GetMergeValueFromStack(Control* c, uint32_t i) {
    1233             :     DCHECK_GT(c->merge.arity, i);
    1234             :     DCHECK_GE(stack_.size(), c->stack_depth + c->merge.arity);
    1235      455026 :     return stack_[stack_.size() - c->merge.arity + i];
    1236             :   }
    1237             : 
    1238             :  private:
    1239             :   static constexpr size_t kErrorMsgSize = 128;
    1240             : 
    1241             :   Zone* zone_;
    1242             : 
    1243             :   Interface interface_;
    1244             : 
    1245             :   ZoneVector<ValueType> local_type_vec_;  // types of local variables.
    1246             :   ZoneVector<Value> stack_;               // stack of values.
    1247             :   ZoneVector<Control> control_;           // stack of blocks, loops, and ifs.
    1248             :   bool last_end_found_;
    1249             : 
    1250       74934 :   bool CheckHasMemory() {
    1251       74934 :     if (!VALIDATE(this->module_->has_memory)) {
    1252         130 :       this->error(this->pc_ - 1, "memory instruction with no memory");
    1253         130 :       return false;
    1254             :     }
    1255             :     return true;
    1256             :   }
    1257             : 
    1258         521 :   bool CheckHasSharedMemory() {
    1259         521 :     if (!VALIDATE(this->module_->has_shared_memory)) {
    1260          10 :       this->error(this->pc_ - 1, "Atomic opcodes used without shared memory");
    1261          10 :       return false;
    1262             :     }
    1263             :     return true;
    1264             :   }
    1265             : 
    1266             :   // Decodes the body of a function.
    1267      405452 :   void DecodeFunctionBody() {
    1268             :     TRACE("wasm-decode %p...%p (module+%u, %d bytes)\n",
    1269             :           reinterpret_cast<const void*>(this->start()),
    1270             :           reinterpret_cast<const void*>(this->end()), this->pc_offset(),
    1271             :           static_cast<int>(this->end() - this->start()));
    1272             : 
    1273             :     // Set up initial function block.
    1274             :     {
    1275      405452 :       auto* c = PushBlock();
    1276      526713 :       c->merge.arity = static_cast<uint32_t>(this->sig_->return_count());
    1277             : 
    1278      405374 :       if (c->merge.arity == 1) {
    1279      237490 :         c->merge.vals.first = Value::New(this->pc_, this->sig_->GetReturn(0));
    1280      288177 :       } else if (c->merge.arity > 1) {
    1281        4138 :         c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity);
    1282        6211 :         for (unsigned i = 0; i < c->merge.arity; i++) {
    1283        8284 :           c->merge.vals.array[i] =
    1284        5188 :               Value::New(this->pc_, this->sig_->GetReturn(i));
    1285             :         }
    1286             :       }
    1287     2168129 :       CALL_INTERFACE(StartFunctionBody, c);
    1288             :     }
    1289             : 
    1290     8603461 :     while (this->pc_ < this->end_) {  // decoding loop.
    1291             :       unsigned len = 1;
    1292     7963727 :       WasmOpcode opcode = static_cast<WasmOpcode>(*this->pc_);
    1293             : #if DEBUG
    1294             :       if (FLAG_trace_wasm_decoder && !WasmOpcodes::IsPrefixOpcode(opcode)) {
    1295             :         TRACE("  @%-8d #%-20s|", startrel(this->pc_),
    1296             :               WasmOpcodes::OpcodeName(opcode));
    1297             :       }
    1298             : #endif
    1299             : 
    1300     7963727 :       FunctionSig* sig = WasmOpcodes::Signature(opcode);
    1301     7963817 :       if (sig) {
    1302     1630550 :         BuildSimpleOperator(opcode, sig);
    1303             :       } else {
    1304             :         // Complex bytecode.
    1305     6333267 :         switch (opcode) {
    1306             :           case kExprNop:
    1307             :             break;
    1308             :           case kExprBlock: {
    1309      382076 :             BlockTypeOperand<validate> operand(this, this->pc_);
    1310      382078 :             if (!LookupBlockType(&operand)) break;
    1311      382070 :             auto* block = PushBlock();
    1312      382074 :             SetBlockType(block, operand);
    1313      382073 :             len = 1 + operand.length;
    1314     2492138 :             CALL_INTERFACE_IF_REACHABLE(Block, block);
    1315             :             break;
    1316             :           }
    1317             :           case kExprRethrow: {
    1318             :             // TODO(kschimpf): Implement.
    1319           0 :             CHECK_PROTOTYPE_OPCODE(eh);
    1320           0 :             OPCODE_ERROR(opcode, "not implemented yet");
    1321           0 :             break;
    1322             :           }
    1323             :           case kExprThrow: {
    1324         144 :             CHECK_PROTOTYPE_OPCODE(eh);
    1325         144 :             ExceptionIndexOperand<Decoder::kValidate> operand(this, this->pc_);
    1326         144 :             len = 1 + operand.length;
    1327         144 :             if (!this->Validate(this->pc_, operand)) break;
    1328             :             std::vector<Value> args;
    1329         286 :             PopArgs(operand.exception->ToFunctionSig(), &args);
    1330         426 :             CALL_INTERFACE_IF_REACHABLE(Throw, operand, &control_.back(),
    1331             :                                         vec2vec(args));
    1332         140 :             EndControl();
    1333             :             break;
    1334             :           }
    1335             :           case kExprTry: {
    1336          74 :             CHECK_PROTOTYPE_OPCODE(eh);
    1337          74 :             BlockTypeOperand<validate> operand(this, this->pc_);
    1338          74 :             if (!LookupBlockType(&operand)) break;
    1339          74 :             auto* try_block = PushTry();
    1340          74 :             SetBlockType(try_block, operand);
    1341          74 :             len = 1 + operand.length;
    1342         148 :             CALL_INTERFACE_IF_REACHABLE(Try, try_block);
    1343             :             break;
    1344             :           }
    1345             :           case kExprCatch: {
    1346             :             // TODO(kschimpf): Fix to use type signature of exception.
    1347          74 :             CHECK_PROTOTYPE_OPCODE(eh);
    1348          74 :             ExceptionIndexOperand<Decoder::kValidate> operand(this, this->pc_);
    1349          74 :             len = 1 + operand.length;
    1350             : 
    1351          74 :             if (!this->Validate(this->pc_, operand)) break;
    1352             : 
    1353          74 :             if (!VALIDATE(!control_.empty())) {
    1354             :               this->error("catch does not match any try");
    1355             :               break;
    1356             :             }
    1357             : 
    1358         144 :             Control* c = &control_.back();
    1359          74 :             if (!VALIDATE(c->is_try())) {
    1360             :               this->error("catch does not match any try");
    1361             :               break;
    1362             :             }
    1363             : 
    1364          74 :             if (!VALIDATE(c->is_incomplete_try())) {
    1365           1 :               OPCODE_ERROR(opcode, "multiple catch blocks not implemented");
    1366           1 :               break;
    1367             :             }
    1368          73 :             c->kind = kControlTryCatch;
    1369          73 :             FallThruTo(c);
    1370       12387 :             stack_.resize(c->stack_depth);
    1371         183 :             const WasmExceptionSig* sig = operand.exception->sig;
    1372         113 :             for (size_t i = 0, e = sig->parameter_count(); i < e; ++i) {
    1373             :               Push(sig->GetParam(i));
    1374             :             }
    1375             :             Vector<Value> values(stack_.data() + c->stack_depth,
    1376          70 :                                  sig->parameter_count());
    1377         210 :             CALL_INTERFACE_IF_PARENT_REACHABLE(CatchException, operand, c,
    1378             :                                                values);
    1379         146 :             c->reachability = control_at(1)->innerReachability();
    1380          73 :             break;
    1381             :           }
    1382             :           case kExprCatchAll: {
    1383             :             // TODO(kschimpf): Implement.
    1384           0 :             CHECK_PROTOTYPE_OPCODE(eh);
    1385           0 :             OPCODE_ERROR(opcode, "not implemented yet");
    1386           0 :             break;
    1387             :           }
    1388             :           case kExprLoop: {
    1389       16029 :             BlockTypeOperand<validate> operand(this, this->pc_);
    1390       16028 :             if (!LookupBlockType(&operand)) break;
    1391       16028 :             auto* block = PushLoop();
    1392       16029 :             SetBlockType(&control_.back(), operand);
    1393       16029 :             len = 1 + operand.length;
    1394       32048 :             CALL_INTERFACE_IF_REACHABLE(Loop, block);
    1395             :             break;
    1396             :           }
    1397             :           case kExprIf: {
    1398       64169 :             BlockTypeOperand<validate> operand(this, this->pc_);
    1399       64166 :             if (!LookupBlockType(&operand)) break;
    1400       64158 :             auto cond = Pop(0, kWasmI32);
    1401       64153 :             if (!this->ok()) break;
    1402       64027 :             auto* if_block = PushIf();
    1403       64028 :             SetBlockType(if_block, operand);
    1404      124243 :             CALL_INTERFACE_IF_REACHABLE(If, cond, if_block);
    1405       64025 :             len = 1 + operand.length;
    1406       64025 :             break;
    1407             :           }
    1408             :           case kExprElse: {
    1409       24884 :             if (!VALIDATE(!control_.empty())) {
    1410           0 :               this->error("else does not match any if");
    1411             :               break;
    1412             :             }
    1413       48428 :             Control* c = &control_.back();
    1414       24884 :             if (!VALIDATE(c->is_if())) {
    1415           0 :               this->error(this->pc_, "else does not match an if");
    1416             :               break;
    1417             :             }
    1418       24884 :             if (c->is_if_else()) {
    1419           2 :               this->error(this->pc_, "else already present for if");
    1420             :               break;
    1421             :             }
    1422       24882 :             c->kind = kControlIfElse;
    1423       24882 :             FallThruTo(c);
    1424       24882 :             stack_.resize(c->stack_depth);
    1425       47274 :             CALL_INTERFACE_IF_PARENT_REACHABLE(Else, c);
    1426       49770 :             c->reachability = control_at(1)->innerReachability();
    1427       24885 :             break;
    1428             :           }
    1429             :           case kExprEnd: {
    1430      842803 :             if (!VALIDATE(!control_.empty())) {
    1431           0 :               this->error("end does not match any if, try, or block");
    1432             :               return;
    1433             :             }
    1434      843305 :             Control* c = &control_.back();
    1435      881072 :             if (c->is_loop()) {
    1436             :               // A loop just leaves the values on the stack.
    1437       14555 :               TypeCheckFallThru(c);
    1438       14555 :               PopControl(c);
    1439       14556 :               break;
    1440             :             }
    1441      828248 :             if (c->is_onearmed_if()) {
    1442             :               // The merge point is reached if the if is not taken.
    1443       38771 :               if (control_at(1)->reachable()) c->merge.reached = true;
    1444             :               // End the true branch of a one-armed if.
    1445       51085 :               if (!VALIDATE(c->unreachable() ||
    1446             :                             stack_.size() == c->stack_depth)) {
    1447         121 :                 this->error("end of if expected empty stack");
    1448         121 :                 stack_.resize(c->stack_depth);
    1449             :               }
    1450       38771 :               if (!VALIDATE(c->merge.arity == 0)) {
    1451          80 :                 this->error("non-void one-armed if");
    1452             :               }
    1453      789477 :             } else if (!VALIDATE(!c->is_incomplete_try())) {
    1454           1 :               this->error(this->pc_, "missing catch in try");
    1455             :               break;
    1456             :             }
    1457      828247 :             FallThruTo(c);
    1458      828150 :             PushEndValues(c);
    1459             : 
    1460      828246 :             if (control_.size() == 1) {
    1461             :               // If at the last (implicit) control, check we are at end.
    1462      386355 :               if (!VALIDATE(this->pc_ + 1 == this->end_)) {
    1463        2723 :                 this->error(this->pc_ + 1, "trailing code after function end");
    1464             :                 break;
    1465             :               }
    1466      383632 :               last_end_found_ = true;
    1467             :               // The result of the block is the return value.
    1468             :               TRACE("  @%-8d #xx:%-20s|", startrel(this->pc_),
    1469             :                     "(implicit) return");
    1470      383632 :               DoReturn(c, true);
    1471             :               TRACE("\n");
    1472             :             }
    1473             : 
    1474      825779 :             PopControl(c);
    1475      825595 :             break;
    1476             :           }
    1477             :           case kExprSelect: {
    1478        1425 :             auto cond = Pop(2, kWasmI32);
    1479        1425 :             auto fval = Pop();
    1480        1426 :             auto tval = Pop(0, fval.type);
    1481        1426 :             auto* result = Push(tval.type == kWasmVar ? fval.type : tval.type);
    1482        1471 :             CALL_INTERFACE_IF_REACHABLE(Select, cond, fval, tval, result);
    1483             :             break;
    1484             :           }
    1485             :           case kExprBr: {
    1486       34858 :             BreakDepthOperand<validate> operand(this, this->pc_);
    1487       69717 :             if (!this->Validate(this->pc_, operand, control_.size())) break;
    1488       34317 :             Control* c = control_at(operand.depth);
    1489       34317 :             if (!TypeCheckBreak(c)) break;
    1490       61842 :             CALL_INTERFACE_IF_REACHABLE(BreakTo, c);
    1491       33612 :             if (control_.back().reachable()) c->merge.reached = true;
    1492       33612 :             len = 1 + operand.length;
    1493       30923 :             EndControl();
    1494       30922 :             break;
    1495             :           }
    1496             :           case kExprBrIf: {
    1497      293214 :             BreakDepthOperand<validate> operand(this, this->pc_);
    1498      293214 :             auto cond = Pop(0, kWasmI32);
    1499      586429 :             if (!this->Validate(this->pc_, operand, control_.size())) break;
    1500      293154 :             Control* c = control_at(operand.depth);
    1501      293154 :             if (!TypeCheckBreak(c)) break;
    1502      327564 :             CALL_INTERFACE_IF_REACHABLE(BrIf, cond, c);
    1503      292972 :             if (control_.back().reachable()) c->merge.reached = true;
    1504      292972 :             len = 1 + operand.length;
    1505      292972 :             break;
    1506             :           }
    1507             :           case kExprBrTable: {
    1508       15617 :             BranchTableOperand<validate> operand(this, this->pc_);
    1509             :             BranchTableIterator<validate> iterator(this, operand);
    1510       15617 :             if (!this->Validate(this->pc_, operand, control_.size())) break;
    1511       15597 :             auto key = Pop(0, kWasmI32);
    1512             :             uint32_t br_arity = 0;
    1513      578900 :             while (iterator.has_next()) {
    1514      548023 :               const uint32_t i = iterator.cur_index();
    1515      548023 :               const byte* pos = iterator.pc();
    1516      548023 :               uint32_t target = iterator.next();
    1517     1096032 :               if (!VALIDATE(target < control_.size())) {
    1518             :                 this->error(pos, "improper branch in br_table");
    1519             :                 break;
    1520             :               }
    1521             :               // Check that label types match up.
    1522      248946 :               Control* c = control_at(target);
    1523      547866 :               uint32_t arity = c->is_loop() ? 0 : c->merge.arity;
    1524      547866 :               if (i == 0) {
    1525             :                 br_arity = arity;
    1526      532436 :               } else if (!VALIDATE(br_arity == arity)) {
    1527          64 :                 this->errorf(pos,
    1528             :                              "inconsistent arity in br_table target %d"
    1529             :                              " (previous was %u, this one %u)",
    1530             :                              i, br_arity, arity);
    1531             :               }
    1532      547866 :               if (!TypeCheckBreak(c)) break;
    1533      547706 :               if (control_.back().reachable()) c->merge.reached = true;
    1534             :             }
    1535             : 
    1536       27860 :             CALL_INTERFACE_IF_REACHABLE(BrTable, operand, key);
    1537             : 
    1538       15597 :             len = 1 + iterator.length();
    1539       14030 :             EndControl();
    1540       14030 :             break;
    1541             :           }
    1542             :           case kExprReturn: {
    1543      361284 :             DoReturn(&control_.back(), false);
    1544      361283 :             break;
    1545             :           }
    1546             :           case kExprUnreachable: {
    1547      265434 :             CALL_INTERFACE_IF_REACHABLE(Unreachable);
    1548      132715 :             EndControl();
    1549      132719 :             break;
    1550             :           }
    1551             :           case kExprI32Const: {
    1552     1114765 :             ImmI32Operand<validate> operand(this, this->pc_);
    1553             :             auto* value = Push(kWasmI32);
    1554     1996282 :             CALL_INTERFACE_IF_REACHABLE(I32Const, value, operand.value);
    1555     1114789 :             len = 1 + operand.length;
    1556             :             break;
    1557             :           }
    1558             :           case kExprI64Const: {
    1559       85239 :             ImmI64Operand<validate> operand(this, this->pc_);
    1560             :             auto* value = Push(kWasmI64);
    1561       92227 :             CALL_INTERFACE_IF_REACHABLE(I64Const, value, operand.value);
    1562       85243 :             len = 1 + operand.length;
    1563             :             break;
    1564             :           }
    1565             :           case kExprF32Const: {
    1566      292501 :             ImmF32Operand<validate> operand(this, this->pc_);
    1567             :             auto* value = Push(kWasmF32);
    1568      293947 :             CALL_INTERFACE_IF_REACHABLE(F32Const, value, operand.value);
    1569      292502 :             len = 1 + operand.length;
    1570             :             break;
    1571             :           }
    1572             :           case kExprF64Const: {
    1573      302918 :             ImmF64Operand<validate> operand(this, this->pc_);
    1574             :             auto* value = Push(kWasmF64);
    1575      315184 :             CALL_INTERFACE_IF_REACHABLE(F64Const, value, operand.value);
    1576      302918 :             len = 1 + operand.length;
    1577             :             break;
    1578             :           }
    1579             :           case kExprGetLocal: {
    1580      614034 :             LocalIndexOperand<Decoder::kValidate> operand(this, this->pc_);
    1581      614050 :             if (!this->Validate(this->pc_, operand)) break;
    1582      613628 :             auto* value = Push(operand.type);
    1583     1136272 :             CALL_INTERFACE_IF_REACHABLE(GetLocal, value, operand);
    1584      613642 :             len = 1 + operand.length;
    1585      613642 :             break;
    1586             :           }
    1587             :           case kExprSetLocal: {
    1588       61869 :             LocalIndexOperand<Decoder::kValidate> operand(this, this->pc_);
    1589       61869 :             if (!this->Validate(this->pc_, operand)) break;
    1590      256491 :             auto value = Pop(0, local_type_vec_[operand.index]);
    1591       97421 :             CALL_INTERFACE_IF_REACHABLE(SetLocal, value, operand);
    1592       61866 :             len = 1 + operand.length;
    1593       61866 :             break;
    1594             :           }
    1595             :           case kExprTeeLocal: {
    1596      132763 :             LocalIndexOperand<Decoder::kValidate> operand(this, this->pc_);
    1597      132762 :             if (!this->Validate(this->pc_, operand)) break;
    1598      265522 :             auto value = Pop(0, local_type_vec_[operand.index]);
    1599      132762 :             auto* result = Push(value.type);
    1600      264060 :             CALL_INTERFACE_IF_REACHABLE(TeeLocal, value, result, operand);
    1601      132765 :             len = 1 + operand.length;
    1602      132765 :             break;
    1603             :           }
    1604             :           case kExprDrop: {
    1605      205953 :             auto value = Pop();
    1606             :             CALL_INTERFACE_IF_REACHABLE(Drop, value);
    1607             :             break;
    1608             :           }
    1609             :           case kExprGetGlobal: {
    1610       19848 :             GlobalIndexOperand<validate> operand(this, this->pc_);
    1611       19847 :             len = 1 + operand.length;
    1612       19847 :             if (!this->Validate(this->pc_, operand)) break;
    1613       19827 :             auto* result = Push(operand.type);
    1614       39323 :             CALL_INTERFACE_IF_REACHABLE(GetGlobal, result, operand);
    1615             :             break;
    1616             :           }
    1617             :           case kExprSetGlobal: {
    1618       12033 :             GlobalIndexOperand<validate> operand(this, this->pc_);
    1619       12033 :             len = 1 + operand.length;
    1620       12033 :             if (!this->Validate(this->pc_, operand)) break;
    1621       12034 :             if (!VALIDATE(operand.global->mutability)) {
    1622          21 :               this->errorf(this->pc_, "immutable global #%u cannot be assigned",
    1623             :                            operand.index);
    1624          21 :               break;
    1625             :             }
    1626       12013 :             auto value = Pop(0, operand.type);
    1627       23892 :             CALL_INTERFACE_IF_REACHABLE(SetGlobal, value, operand);
    1628             :             break;
    1629             :           }
    1630             :           case kExprI32LoadMem8S:
    1631        3443 :             len = DecodeLoadMem(kWasmI32, MachineType::Int8());
    1632        3443 :             break;
    1633             :           case kExprI32LoadMem8U:
    1634         863 :             len = DecodeLoadMem(kWasmI32, MachineType::Uint8());
    1635         863 :             break;
    1636             :           case kExprI32LoadMem16S:
    1637         151 :             len = DecodeLoadMem(kWasmI32, MachineType::Int16());
    1638         151 :             break;
    1639             :           case kExprI32LoadMem16U:
    1640         501 :             len = DecodeLoadMem(kWasmI32, MachineType::Uint16());
    1641         501 :             break;
    1642             :           case kExprI32LoadMem:
    1643        9985 :             len = DecodeLoadMem(kWasmI32, MachineType::Int32());
    1644        9985 :             break;
    1645             :           case kExprI64LoadMem8S:
    1646         189 :             len = DecodeLoadMem(kWasmI64, MachineType::Int8());
    1647         189 :             break;
    1648             :           case kExprI64LoadMem8U:
    1649          85 :             len = DecodeLoadMem(kWasmI64, MachineType::Uint8());
    1650          85 :             break;
    1651             :           case kExprI64LoadMem16S:
    1652         129 :             len = DecodeLoadMem(kWasmI64, MachineType::Int16());
    1653         129 :             break;
    1654             :           case kExprI64LoadMem16U:
    1655         105 :             len = DecodeLoadMem(kWasmI64, MachineType::Uint16());
    1656         105 :             break;
    1657             :           case kExprI64LoadMem32S:
    1658         129 :             len = DecodeLoadMem(kWasmI64, MachineType::Int32());
    1659         129 :             break;
    1660             :           case kExprI64LoadMem32U:
    1661         105 :             len = DecodeLoadMem(kWasmI64, MachineType::Uint32());
    1662         105 :             break;
    1663             :           case kExprI64LoadMem:
    1664       23129 :             len = DecodeLoadMem(kWasmI64, MachineType::Int64());
    1665       23129 :             break;
    1666             :           case kExprF32LoadMem:
    1667        3320 :             len = DecodeLoadMem(kWasmF32, MachineType::Float32());
    1668        3320 :             break;
    1669             :           case kExprF64LoadMem:
    1670        3654 :             len = DecodeLoadMem(kWasmF64, MachineType::Float64());
    1671        3654 :             break;
    1672             :           case kExprI32StoreMem8:
    1673        1114 :             len = DecodeStoreMem(kWasmI32, MachineType::Int8());
    1674        1114 :             break;
    1675             :           case kExprI32StoreMem16:
    1676         408 :             len = DecodeStoreMem(kWasmI32, MachineType::Int16());
    1677         408 :             break;
    1678             :           case kExprI32StoreMem:
    1679        1953 :             len = DecodeStoreMem(kWasmI32, MachineType::Int32());
    1680        1950 :             break;
    1681             :           case kExprI64StoreMem8:
    1682         140 :             len = DecodeStoreMem(kWasmI64, MachineType::Int8());
    1683         140 :             break;
    1684             :           case kExprI64StoreMem16:
    1685         240 :             len = DecodeStoreMem(kWasmI64, MachineType::Int16());
    1686         240 :             break;
    1687             :           case kExprI64StoreMem32:
    1688         160 :             len = DecodeStoreMem(kWasmI64, MachineType::Int32());
    1689         160 :             break;
    1690             :           case kExprI64StoreMem:
    1691       21760 :             len = DecodeStoreMem(kWasmI64, MachineType::Int64());
    1692       21760 :             break;
    1693             :           case kExprF32StoreMem:
    1694         640 :             len = DecodeStoreMem(kWasmF32, MachineType::Float32());
    1695         640 :             break;
    1696             :           case kExprF64StoreMem:
    1697         754 :             len = DecodeStoreMem(kWasmF64, MachineType::Float64());
    1698         754 :             break;
    1699             :           case kExprGrowMemory: {
    1700        1319 :             if (!CheckHasMemory()) break;
    1701        1289 :             MemoryIndexOperand<validate> operand(this, this->pc_);
    1702        1289 :             len = 1 + operand.length;
    1703             :             DCHECK_NOT_NULL(this->module_);
    1704      134572 :             if (!VALIDATE(this->module_->is_wasm())) {
    1705             :               this->error("grow_memory is not supported for asmjs modules");
    1706             :               break;
    1707             :             }
    1708        1288 :             auto value = Pop(0, kWasmI32);
    1709             :             auto* result = Push(kWasmI32);
    1710        2555 :             CALL_INTERFACE_IF_REACHABLE(GrowMemory, value, result);
    1711             :             break;
    1712             :           }
    1713             :           case kExprMemorySize: {
    1714         660 :             if (!CheckHasMemory()) break;
    1715         640 :             MemoryIndexOperand<validate> operand(this, this->pc_);
    1716             :             auto* result = Push(kWasmI32);
    1717         640 :             len = 1 + operand.length;
    1718        1270 :             CALL_INTERFACE_IF_REACHABLE(CurrentMemoryPages, result);
    1719             :             break;
    1720             :           }
    1721             :           case kExprCallFunction: {
    1722      310607 :             CallFunctionOperand<validate> operand(this, this->pc_);
    1723      310589 :             len = 1 + operand.length;
    1724      310589 :             if (!this->Validate(this->pc_, operand)) break;
    1725             :             // TODO(clemensh): Better memory management.
    1726             :             std::vector<Value> args;
    1727      310557 :             PopArgs(operand.sig, &args);
    1728      310550 :             auto* returns = PushReturns(operand.sig);
    1729      345546 :             CALL_INTERFACE_IF_REACHABLE(CallDirect, operand, args.data(),
    1730             :                                         returns);
    1731             :             break;
    1732             :           }
    1733             :           case kExprCallIndirect: {
    1734        4380 :             CallIndirectOperand<validate> operand(this, this->pc_);
    1735        4380 :             len = 1 + operand.length;
    1736        4380 :             if (!this->Validate(this->pc_, operand)) break;
    1737        4305 :             auto index = Pop(0, kWasmI32);
    1738             :             // TODO(clemensh): Better memory management.
    1739             :             std::vector<Value> args;
    1740        4304 :             PopArgs(operand.sig, &args);
    1741        4305 :             auto* returns = PushReturns(operand.sig);
    1742        7000 :             CALL_INTERFACE_IF_REACHABLE(CallIndirect, index, operand,
    1743             :                                         args.data(), returns);
    1744             :             break;
    1745             :           }
    1746             :           case kSimdPrefix: {
    1747       15438 :             CHECK_PROTOTYPE_OPCODE(simd);
    1748             :             len++;
    1749             :             byte simd_index =
    1750       15438 :                 this->template read_u8<validate>(this->pc_ + 1, "simd index");
    1751       15438 :             opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
    1752             :             TRACE("  @%-4d #%-20s|", startrel(this->pc_),
    1753             :                   WasmOpcodes::OpcodeName(opcode));
    1754       15438 :             len += DecodeSimdOpcode(opcode);
    1755       15438 :             break;
    1756             :           }
    1757             :           case kAtomicPrefix: {
    1758         521 :             CHECK_PROTOTYPE_OPCODE(threads);
    1759         521 :             if (!CheckHasSharedMemory()) break;
    1760             :             len++;
    1761             :             byte atomic_index =
    1762         511 :                 this->template read_u8<validate>(this->pc_ + 1, "atomic index");
    1763         511 :             opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_index);
    1764             :             TRACE("  @%-4d #%-20s|", startrel(this->pc_),
    1765             :                   WasmOpcodes::OpcodeName(opcode));
    1766         511 :             len += DecodeAtomicOpcode(opcode);
    1767         512 :             break;
    1768             :           }
    1769             :           default: {
    1770             :             // Deal with special asmjs opcodes.
    1771      266566 :             if (this->module_ != nullptr && this->module_->is_asm_js()) {
    1772      133252 :               sig = WasmOpcodes::AsmjsSignature(opcode);
    1773      133252 :               if (sig) {
    1774      133252 :                 BuildSimpleOperator(opcode, sig);
    1775             :               }
    1776             :             } else {
    1777          31 :               this->error("Invalid opcode");
    1778             :               return;
    1779             :             }
    1780             :           }
    1781             :         }
    1782             :       }
    1783             : 
    1784             : #if DEBUG
    1785             :       if (FLAG_trace_wasm_decoder) {
    1786             :         PrintF(" ");
    1787             :         for (Control& c : control_) {
    1788             :           switch (c.kind) {
    1789             :             case kControlIf:
    1790             :               PrintF("I");
    1791             :               break;
    1792             :             case kControlBlock:
    1793             :               PrintF("B");
    1794             :               break;
    1795             :             case kControlLoop:
    1796             :               PrintF("L");
    1797             :               break;
    1798             :             case kControlTry:
    1799             :               PrintF("T");
    1800             :               break;
    1801             :             default:
    1802             :               break;
    1803             :           }
    1804             :           PrintF("%u", c.merge.arity);
    1805             :           if (!c.reachable()) PrintF("%c", c.unreachable() ? '*' : '#');
    1806             :         }
    1807             :         PrintF(" | ");
    1808             :         for (size_t i = 0; i < stack_.size(); ++i) {
    1809             :           auto& val = stack_[i];
    1810             :           WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
    1811             :           if (WasmOpcodes::IsPrefixOpcode(opcode)) {
    1812             :             opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1));
    1813             :           }
    1814             :           PrintF(" %c@%d:%s", WasmOpcodes::ShortNameOf(val.type),
    1815             :                  static_cast<int>(val.pc - this->start_),
    1816             :                  WasmOpcodes::OpcodeName(opcode));
    1817             :           switch (opcode) {
    1818             :             case kExprI32Const: {
    1819             :               ImmI32Operand<validate> operand(this, val.pc);
    1820             :               PrintF("[%d]", operand.value);
    1821             :               break;
    1822             :             }
    1823             :             case kExprGetLocal:
    1824             :             case kExprSetLocal:
    1825             :             case kExprTeeLocal: {
    1826             :               LocalIndexOperand<Decoder::kValidate> operand(this, val.pc);
    1827             :               PrintF("[%u]", operand.index);
    1828             :               break;
    1829             :             }
    1830             :             case kExprGetGlobal:
    1831             :             case kExprSetGlobal: {
    1832             :               GlobalIndexOperand<validate> operand(this, val.pc);
    1833             :               PrintF("[%u]", operand.index);
    1834             :               break;
    1835             :             }
    1836             :             default:
    1837             :               break;
    1838             :           }
    1839             :         }
    1840             :         PrintF("\n");
    1841             :       }
    1842             : #endif
    1843     7963801 :       this->pc_ += len;
    1844             :     }  // end decode loop
    1845      426957 :     if (this->pc_ > this->end_ && this->ok()) this->error("Beyond end of code");
    1846             :   }
    1847             : 
    1848      635235 :   void EndControl() {
    1849             :     DCHECK(!control_.empty());
    1850             :     auto* current = &control_.back();
    1851     1059802 :     stack_.resize(current->stack_depth);
    1852     1270568 :     CALL_INTERFACE_IF_REACHABLE(EndControl, current);
    1853     1060029 :     current->reachability = kUnreachable;
    1854      635462 :   }
    1855             : 
    1856      462342 :   bool LookupBlockType(BlockTypeOperand<validate>* operand) {
    1857      462342 :     if (operand->type == kWasmVar) {
    1858         266 :       if (!VALIDATE(this->module_ &&
    1859             :                     operand->sig_index < this->module_->signatures.size())) {
    1860          14 :         this->errorf(
    1861             :             this->pc_, "block type index %u out of bounds (%d signatures)",
    1862             :             operand->sig_index,
    1863             :             static_cast<int>(this->module_
    1864             :                                  ? this->module_->signatures.size() : 0));
    1865          14 :         return false;
    1866             :       }
    1867         168 :       operand->sig = this->module_->signatures[operand->sig_index];
    1868             :     }
    1869             :     return true;
    1870             :   }
    1871             : 
    1872      480650 :   void SetBlockType(Control* c, BlockTypeOperand<validate>& operand) {
    1873      462204 :     c->merge.arity = operand.out_arity();
    1874      462204 :     if (c->merge.arity == 1) {
    1875       18390 :       c->merge.vals.first = Value::New(this->pc_, operand.out_type(0));
    1876      443886 :     } else if (c->merge.arity > 1) {
    1877         128 :       c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity);
    1878         192 :       for (unsigned i = 0; i < c->merge.arity; i++) {
    1879         256 :         c->merge.vals.array[i] = Value::New(this->pc_, operand.out_type(i));
    1880             :       }
    1881             :     }
    1882      462204 :   }
    1883             : 
    1884             :   // TODO(clemensh): Better memory management.
    1885     1612296 :   void PopArgs(FunctionSig* sig, std::vector<Value>* result) {
    1886             :     DCHECK(result->empty());
    1887      317682 :     int count = static_cast<int>(sig->parameter_count());
    1888      317682 :     result->resize(count);
    1889      965001 :     for (int i = count - 1; i >= 0; --i) {
    1890     1294614 :       (*result)[i] = Pop(i, sig->GetParam(i));
    1891             :     }
    1892      317694 :   }
    1893             : 
    1894        4406 :   ValueType GetReturnType(FunctionSig* sig) {
    1895             :     DCHECK_GE(1, sig->return_count());
    1896        3550 :     return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn();
    1897             :   }
    1898             : 
    1899      867634 :   Control* PushControl(Control&& new_control) {
    1900             :     Reachability reachability =
    1901      867634 :         control_.empty() ? kReachable : control_.back().innerReachability();
    1902      867634 :     control_.emplace_back(std::move(new_control));
    1903      867608 :     Control* c = &control_.back();
    1904      867608 :     c->reachability = reachability;
    1905      867608 :     return c;
    1906             :   }
    1907             : 
    1908      787513 :   Control* PushBlock() {
    1909     1575026 :     return PushControl(Control::Block(this->pc_, stack_size()));
    1910             :   }
    1911       16028 :   Control* PushLoop() {
    1912             :     return PushControl(
    1913       48084 :         Control::Loop(this->pc_, stack_size(), control_.back().reachable()));
    1914             :   }
    1915       64023 :   Control* PushIf() {
    1916      128046 :     return PushControl(Control::If(this->pc_, stack_size()));
    1917             :   }
    1918          74 :   Control* PushTry() {
    1919             :     // current_catch_ = static_cast<int32_t>(control_.size() - 1);
    1920         148 :     return PushControl(Control::Try(this->pc_, stack_size()));
    1921             :   }
    1922             : 
    1923      843145 :   void PopControl(Control* c) {
    1924             :     DCHECK_EQ(c, &control_.back());
    1925     1085052 :     CALL_INTERFACE_IF_PARENT_REACHABLE(PopControl, c);
    1926     1665728 :     bool reached = c->is_loop() ? c->reachable() : c->merge.reached;
    1927             :     control_.pop_back();
    1928             :     // If the parent block was reachable before, but the popped control does not
    1929             :     // return to here, this block becomes indirectly unreachable.
    1930      840142 :     if (!control_.empty() && !reached && control_.back().reachable()) {
    1931       50087 :       control_.back().reachability = kSpecOnlyReachable;
    1932             :     }
    1933      840142 :   }
    1934             : 
    1935       45779 :   int DecodeLoadMem(ValueType type, MachineType mem_type) {
    1936       45779 :     if (!CheckHasMemory()) return 0;
    1937             :     MemoryAccessOperand<validate> operand(
    1938       45738 :         this, this->pc_, ElementSizeLog2Of(mem_type.representation()));
    1939             : 
    1940       45742 :     auto index = Pop(0, kWasmI32);
    1941             :     auto* result = Push(type);
    1942       66541 :     CALL_INTERFACE_IF_REACHABLE(LoadMem, type, mem_type, operand, index,
    1943             :                                 result);
    1944       45744 :     return 1 + operand.length;
    1945             :   }
    1946             : 
    1947       27162 :   int DecodeStoreMem(ValueType type, MachineType mem_type) {
    1948       27162 :     if (!CheckHasMemory()) return 0;
    1949             :     MemoryAccessOperand<validate> operand(
    1950       27122 :         this, this->pc_, ElementSizeLog2Of(mem_type.representation()));
    1951       27125 :     auto value = Pop(1, type);
    1952       27123 :     auto index = Pop(0, kWasmI32);
    1953       29642 :     CALL_INTERFACE_IF_REACHABLE(StoreMem, type, mem_type, operand, index,
    1954             :                                 value);
    1955       27123 :     return 1 + operand.length;
    1956             :   }
    1957             : 
    1958          12 :   int DecodePrefixedLoadMem(ValueType type, MachineType mem_type) {
    1959          12 :     if (!CheckHasMemory()) return 0;
    1960             :     MemoryAccessOperand<validate> operand(
    1961          12 :         this, this->pc_ + 1, ElementSizeLog2Of(mem_type.representation()));
    1962             : 
    1963          12 :     auto index = Pop(0, kWasmI32);
    1964             :     auto* result = Push(type);
    1965          24 :     CALL_INTERFACE_IF_REACHABLE(LoadMem, type, mem_type, operand, index,
    1966             :                                 result);
    1967          12 :     return operand.length;
    1968             :   }
    1969             : 
    1970           6 :   int DecodePrefixedStoreMem(ValueType type, MachineType mem_type) {
    1971           6 :     if (!CheckHasMemory()) return 0;
    1972             :     MemoryAccessOperand<validate> operand(
    1973           6 :         this, this->pc_ + 1, ElementSizeLog2Of(mem_type.representation()));
    1974           6 :     auto value = Pop(1, type);
    1975           6 :     auto index = Pop(0, kWasmI32);
    1976          12 :     CALL_INTERFACE_IF_REACHABLE(StoreMem, type, mem_type, operand, index,
    1977             :                                 value);
    1978           6 :     return operand.length;
    1979             :   }
    1980             : 
    1981       12186 :   unsigned SimdExtractLane(WasmOpcode opcode, ValueType type) {
    1982       12186 :     SimdLaneOperand<validate> operand(this, this->pc_);
    1983       12186 :     if (this->Validate(this->pc_, opcode, operand)) {
    1984       12186 :       Value inputs[] = {Pop(0, ValueType::kSimd128)};
    1985             :       auto* result = Push(type);
    1986       24372 :       CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, operand,
    1987             :                                   ArrayVector(inputs), result);
    1988             :     }
    1989       12186 :     return operand.length;
    1990             :   }
    1991             : 
    1992         468 :   unsigned SimdReplaceLane(WasmOpcode opcode, ValueType type) {
    1993         468 :     SimdLaneOperand<validate> operand(this, this->pc_);
    1994         468 :     if (this->Validate(this->pc_, opcode, operand)) {
    1995             :       Value inputs[2];
    1996         468 :       inputs[1] = Pop(1, type);
    1997         468 :       inputs[0] = Pop(0, ValueType::kSimd128);
    1998             :       auto* result = Push(ValueType::kSimd128);
    1999         936 :       CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, operand,
    2000             :                                   ArrayVector(inputs), result);
    2001             :     }
    2002         468 :     return operand.length;
    2003             :   }
    2004             : 
    2005          72 :   unsigned SimdShiftOp(WasmOpcode opcode) {
    2006          72 :     SimdShiftOperand<validate> operand(this, this->pc_);
    2007          72 :     if (this->Validate(this->pc_, opcode, operand)) {
    2008          72 :       auto input = Pop(0, ValueType::kSimd128);
    2009             :       auto* result = Push(ValueType::kSimd128);
    2010         144 :       CALL_INTERFACE_IF_REACHABLE(SimdShiftOp, opcode, operand, input, result);
    2011             :     }
    2012          72 :     return operand.length;
    2013             :   }
    2014             : 
    2015           0 :   unsigned Simd8x16ShuffleOp() {
    2016           0 :     Simd8x16ShuffleOperand<validate> operand(this, this->pc_);
    2017           0 :     if (this->Validate(this->pc_, operand)) {
    2018           0 :       auto input1 = Pop(1, ValueType::kSimd128);
    2019           0 :       auto input0 = Pop(0, ValueType::kSimd128);
    2020             :       auto* result = Push(ValueType::kSimd128);
    2021           0 :       CALL_INTERFACE_IF_REACHABLE(Simd8x16ShuffleOp, operand, input0, input1,
    2022             :                                   result);
    2023             :     }
    2024           0 :     return 16;
    2025             :   }
    2026             : 
    2027       15438 :   unsigned DecodeSimdOpcode(WasmOpcode opcode) {
    2028             :     unsigned len = 0;
    2029       15438 :     switch (opcode) {
    2030             :       case kExprF32x4ExtractLane: {
    2031           0 :         len = SimdExtractLane(opcode, ValueType::kFloat32);
    2032           0 :         break;
    2033             :       }
    2034             :       case kExprI32x4ExtractLane:
    2035             :       case kExprI16x8ExtractLane:
    2036             :       case kExprI8x16ExtractLane: {
    2037       12186 :         len = SimdExtractLane(opcode, ValueType::kWord32);
    2038       12186 :         break;
    2039             :       }
    2040             :       case kExprF32x4ReplaceLane: {
    2041           0 :         len = SimdReplaceLane(opcode, ValueType::kFloat32);
    2042           0 :         break;
    2043             :       }
    2044             :       case kExprI32x4ReplaceLane:
    2045             :       case kExprI16x8ReplaceLane:
    2046             :       case kExprI8x16ReplaceLane: {
    2047         468 :         len = SimdReplaceLane(opcode, ValueType::kWord32);
    2048         468 :         break;
    2049             :       }
    2050             :       case kExprI32x4Shl:
    2051             :       case kExprI32x4ShrS:
    2052             :       case kExprI32x4ShrU:
    2053             :       case kExprI16x8Shl:
    2054             :       case kExprI16x8ShrS:
    2055             :       case kExprI16x8ShrU:
    2056             :       case kExprI8x16Shl:
    2057             :       case kExprI8x16ShrS:
    2058             :       case kExprI8x16ShrU: {
    2059          72 :         len = SimdShiftOp(opcode);
    2060          72 :         break;
    2061             :       }
    2062             :       case kExprS8x16Shuffle: {
    2063           0 :         len = Simd8x16ShuffleOp();
    2064           0 :         break;
    2065             :       }
    2066             :       case kExprS128LoadMem:
    2067          12 :         len = DecodePrefixedLoadMem(kWasmS128, MachineType::Simd128());
    2068          12 :         break;
    2069             :       case kExprS128StoreMem:
    2070           6 :         len = DecodePrefixedStoreMem(kWasmS128, MachineType::Simd128());
    2071           6 :         break;
    2072             :       default: {
    2073        5388 :         FunctionSig* sig = WasmOpcodes::Signature(opcode);
    2074        2694 :         if (!VALIDATE(sig != nullptr)) {
    2075           0 :           this->error("invalid simd opcode");
    2076           0 :           break;
    2077             :         }
    2078             :         std::vector<Value> args;
    2079        2694 :         PopArgs(sig, &args);
    2080             :         auto* result =
    2081        5388 :             sig->return_count() == 0 ? nullptr : Push(GetReturnType(sig));
    2082        8082 :         CALL_INTERFACE_IF_REACHABLE(SimdOp, opcode, vec2vec(args), result);
    2083             :       }
    2084             :     }
    2085       15438 :     return len;
    2086             :   }
    2087             : 
    2088         512 :   unsigned DecodeAtomicOpcode(WasmOpcode opcode) {
    2089             :     unsigned len = 0;
    2090             :     ValueType ret_type;
    2091        2518 :     FunctionSig* sig = WasmOpcodes::AtomicSignature(opcode);
    2092         512 :     if (sig != nullptr) {
    2093             :       MachineType memtype;
    2094         512 :       switch (opcode) {
    2095             : #define CASE_ATOMIC_STORE_OP(Name, Type)     \
    2096             :   case kExpr##Name: {                        \
    2097             :     memtype = MachineType::Type();           \
    2098             :     ret_type = MachineRepresentation::kNone; \
    2099             :     break;                                   \
    2100             :   }
    2101          16 :         ATOMIC_STORE_OP_LIST(CASE_ATOMIC_STORE_OP)
    2102             : #undef CASE_ATOMIC_OP
    2103             : #define CASE_ATOMIC_OP(Name, Type) \
    2104             :   case kExpr##Name: {              \
    2105             :     memtype = MachineType::Type(); \
    2106             :     ret_type = GetReturnType(sig); \
    2107             :     break;                         \
    2108             :   }
    2109         428 :         ATOMIC_OP_LIST(CASE_ATOMIC_OP)
    2110             : #undef CASE_ATOMIC_OP
    2111             :         default:
    2112           0 :           this->error("invalid atomic opcode");
    2113             :           break;
    2114             :       }
    2115             :       // TODO(clemensh): Better memory management here.
    2116         512 :       std::vector<Value> args(sig->parameter_count());
    2117             :       MemoryAccessOperand<validate> operand(
    2118         511 :           this, this->pc_ + 1, ElementSizeLog2Of(memtype.representation()));
    2119         514 :       len += operand.length;
    2120        1492 :       for (int i = static_cast<int>(sig->parameter_count() - 1); i >= 0; --i) {
    2121        1960 :         args[i] = Pop(i, sig->GetParam(i));
    2122             :       }
    2123             :       auto result = ret_type == MachineRepresentation::kNone
    2124             :                         ? nullptr
    2125         940 :                         : Push(GetReturnType(sig));
    2126        1536 :       CALL_INTERFACE_IF_REACHABLE(AtomicOp, opcode, vec2vec(args), operand,
    2127             :                                   result);
    2128             :     } else {
    2129           0 :       this->error("invalid atomic opcode");
    2130             :     }
    2131         512 :     return len;
    2132             :   }
    2133             : 
    2134      744878 :   void DoReturn(Control* c, bool implicit) {
    2135             :     // TODO(clemensh): Optimize memory usage here (it will be mostly 0 or 1
    2136             :     // returned values).
    2137      948950 :     int return_count = static_cast<int>(this->sig_->return_count());
    2138      744878 :     std::vector<Value> values(return_count);
    2139             : 
    2140             :     // Pop return values off the stack in reverse order.
    2141      949222 :     for (int i = return_count - 1; i >= 0; --i) {
    2142      612216 :       values[i] = Pop(i, this->sig_->GetReturn(i));
    2143             :     }
    2144             : 
    2145      457655 :     if (this->ok() && (c->reachable() || (implicit && c->merge.reached))) {
    2146      576990 :       CALL_INTERFACE(DoReturn, vec2vec(values), implicit);
    2147             :     }
    2148             : 
    2149      457638 :     EndControl();
    2150      745158 :   }
    2151             : 
    2152             :   inline Value* Push(ValueType type) {
    2153             :     DCHECK_NE(kWasmStmt, type);
    2154    12975199 :     stack_.push_back(Value::New(this->pc_, type));
    2155             :     return &stack_.back();
    2156             :   }
    2157             : 
    2158      828133 :   void PushEndValues(Control* c) {
    2159             :     DCHECK_EQ(c, &control_.back());
    2160      828133 :     stack_.resize(c->stack_depth);
    2161      828220 :     if (c->merge.arity == 1) {
    2162      121662 :       stack_.push_back(c->merge.vals.first);
    2163             :     } else {
    2164        4241 :       for (unsigned i = 0; i < c->merge.arity; i++) {
    2165        4241 :         stack_.push_back(c->merge.vals.array[i]);
    2166             :       }
    2167             :     }
    2168             :     DCHECK_EQ(c->stack_depth + c->merge.arity, stack_.size());
    2169      828256 :   }
    2170             : 
    2171      604901 :   Value* PushReturns(FunctionSig* sig) {
    2172             :     size_t return_count = sig->return_count();
    2173      314846 :     if (return_count == 0) return nullptr;
    2174      287995 :     size_t old_size = stack_.size();
    2175      578041 :     for (size_t i = 0; i < return_count; ++i) {
    2176             :       Push(sig->GetReturn(i));
    2177             :     }
    2178      287986 :     return stack_.data() + old_size;
    2179             :   }
    2180             : 
    2181     4491907 :   Value Pop(int index, ValueType expected) {
    2182     4453873 :     auto val = Pop();
    2183     4453908 :     if (!VALIDATE(val.type == expected || val.type == kWasmVar ||
    2184             :                   expected == kWasmVar)) {
    2185       57051 :       this->errorf(val.pc, "%s[%d] expected type %s, found %s of type %s",
    2186             :                    SafeOpcodeNameAt(this->pc_), index,
    2187             :                    WasmOpcodes::TypeName(expected), SafeOpcodeNameAt(val.pc),
    2188             :                    WasmOpcodes::TypeName(val.type));
    2189             :     }
    2190     4453908 :     return val;
    2191             :   }
    2192             : 
    2193     4663093 :   Value Pop() {
    2194             :     DCHECK(!control_.empty());
    2195     4661235 :     uint32_t limit = control_.back().stack_depth;
    2196     9322470 :     if (stack_.size() <= limit) {
    2197             :       // Popping past the current control start in reachable code.
    2198        7977 :       if (!VALIDATE(control_.back().unreachable())) {
    2199        3716 :         this->errorf(this->pc_, "%s found empty stack",
    2200             :                      SafeOpcodeNameAt(this->pc_));
    2201             :       }
    2202        7977 :       return Value::Unreachable(this->pc_);
    2203             :     }
    2204     4653258 :     auto val = stack_.back();
    2205             :     stack_.pop_back();
    2206     4653258 :     return val;
    2207             :   }
    2208             : 
    2209        2997 :   int startrel(const byte* ptr) { return static_cast<int>(ptr - this->start_); }
    2210             : 
    2211     1148242 :   void FallThruTo(Control* c) {
    2212             :     DCHECK(!c->is_loop());
    2213             :     DCHECK_EQ(c, &control_.back());
    2214      853159 :     if (!TypeCheckFallThru(c)) return;
    2215      849586 :     if (!c->reachable()) return;
    2216             : 
    2217      135591 :     CALL_INTERFACE(FallThruTo, c);
    2218      161657 :     c->merge.reached = true;
    2219             :   }
    2220             : 
    2221     1728125 :   bool TypeCheckMergeValues(Control* c) {
    2222             :     DCHECK_GE(stack_.size(), c->stack_depth + c->merge.arity);
    2223             :     // Typecheck the topmost {c->merge.arity} values on the stack.
    2224     1868047 :     for (uint32_t i = 0; i < c->merge.arity; ++i) {
    2225             :       auto& val = GetMergeValueFromStack(c, i);
    2226             :       auto& old = c->merge[i];
    2227      142034 :       if (val.type != old.type) {
    2228             :         // If {val.type} is polymorphic, which results from unreachable, make
    2229             :         // it more specific by using the merge value's expected type.
    2230             :         // If it is not polymorphic, this is a type error.
    2231       12690 :         if (!VALIDATE(val.type == kWasmVar)) {
    2232        2112 :           this->errorf(
    2233             :               this->pc_, "type error in merge[%u] (expected %s, got %s)", i,
    2234             :               WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type));
    2235        2135 :           return false;
    2236             :         }
    2237       10578 :         val.type = old.type;
    2238             :       }
    2239             :     }
    2240             : 
    2241             :     return true;
    2242             :   }
    2243             : 
    2244      870023 :   bool TypeCheckFallThru(Control* c) {
    2245             :     DCHECK_EQ(c, &control_.back());
    2246             :     if (!validate) return true;
    2247      867708 :     uint32_t expected = c->merge.arity;
    2248             :     DCHECK_GE(stack_.size(), c->stack_depth);
    2249     1735416 :     uint32_t actual = static_cast<uint32_t>(stack_.size()) - c->stack_depth;
    2250             :     // Fallthrus must match the arity of the control exactly.
    2251      867708 :     if (!InsertUnreachablesIfNecessary(expected, actual) || actual > expected) {
    2252        4630 :       this->errorf(
    2253             :           this->pc_,
    2254             :           "expected %u elements on the stack for fallthru to @%d, found %u",
    2255             :           expected, startrel(c->pc), actual);
    2256        2315 :       return false;
    2257             :     }
    2258             : 
    2259      865594 :     return TypeCheckMergeValues(c);
    2260             :   }
    2261             : 
    2262      876021 :   bool TypeCheckBreak(Control* c) {
    2263      875339 :     if (c->is_loop()) {
    2264             :       // This is the inner loop block, which does not have a value.
    2265             :       return true;
    2266             :     }
    2267             :     // Breaks must have at least the number of values expected; can have more.
    2268      863278 :     uint32_t expected = c->merge.arity;
    2269             :     DCHECK_GE(stack_.size(), control_.back().stack_depth);
    2270             :     uint32_t actual =
    2271     2589834 :         static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth;
    2272      863278 :     if (!InsertUnreachablesIfNecessary(expected, actual)) {
    2273        1364 :       this->errorf(this->pc_,
    2274             :                    "expected %u elements on the stack for br to @%d, found %u",
    2275             :                    expected, startrel(c->pc), actual);
    2276         682 :       return false;
    2277             :     }
    2278      862597 :     return TypeCheckMergeValues(c);
    2279             :   }
    2280             : 
    2281     1730904 :   inline bool InsertUnreachablesIfNecessary(uint32_t expected,
    2282             :                                             uint32_t actual) {
    2283     1730904 :     if (V8_LIKELY(actual >= expected)) {
    2284             :       return true;  // enough actual values are there.
    2285             :     }
    2286       12098 :     if (!VALIDATE(control_.back().unreachable())) {
    2287             :       // There aren't enough values on the stack.
    2288             :       return false;
    2289             :     }
    2290             :     // A slow path. When the actual number of values on the stack is less
    2291             :     // than the expected number of values and the current control is
    2292             :     // unreachable, insert unreachable values below the actual values.
    2293             :     // This simplifies {TypeCheckMergeValues}.
    2294       20360 :     auto pos = stack_.begin() + (stack_.size() - actual);
    2295       28871 :     stack_.insert(pos, (expected - actual), Value::Unreachable(this->pc_));
    2296       10178 :     return true;
    2297             :   }
    2298             : 
    2299       21654 :   virtual void onFirstError() {
    2300       21654 :     this->end_ = this->pc_;  // Terminate decoding loop.
    2301             :     TRACE(" !%s\n", this->error_msg_.c_str());
    2302             :     CALL_INTERFACE(OnFirstError);
    2303       21654 :   }
    2304             : 
    2305     8191786 :   inline void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
    2306     1763786 :     switch (sig->parameter_count()) {
    2307             :       case 1: {
    2308      627210 :         auto val = Pop(0, sig->GetParam(0));
    2309             :         auto* ret =
    2310      995838 :             sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
    2311      736292 :         CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, sig, val, ret);
    2312             :         break;
    2313             :       }
    2314             :       case 2: {
    2315     1136576 :         auto rval = Pop(1, sig->GetParam(1));
    2316     1136577 :         auto lval = Pop(0, sig->GetParam(0));
    2317             :         auto* ret =
    2318     2106460 :             sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
    2319     1938771 :         CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, sig, lval, rval, ret);
    2320             :         break;
    2321             :       }
    2322             :       default:
    2323           0 :         UNREACHABLE();
    2324             :     }
    2325     1763814 :   }
    2326             : };
    2327             : 
    2328             : #undef CALL_INTERFACE
    2329             : #undef CALL_INTERFACE_IF_REACHABLE
    2330             : #undef CALL_INTERFACE_IF_PARENT_REACHABLE
    2331             : 
    2332             : class EmptyInterface {
    2333             :  public:
    2334             :   static constexpr wasm::Decoder::ValidateFlag validate =
    2335             :       wasm::Decoder::kValidate;
    2336             :   using Value = ValueBase;
    2337             :   using Control = ControlBase<Value>;
    2338             :   using Decoder = WasmFullDecoder<validate, EmptyInterface>;
    2339             : 
    2340             : #define DEFINE_EMPTY_CALLBACK(name, ...) \
    2341             :   void name(Decoder* decoder, ##__VA_ARGS__) {}
    2342             :   INTERFACE_FUNCTIONS(DEFINE_EMPTY_CALLBACK)
    2343             : #undef DEFINE_EMPTY_CALLBACK
    2344             : };
    2345             : 
    2346             : #undef TRACE
    2347             : #undef VALIDATE
    2348             : #undef CHECK_PROTOTYPE_OPCODE
    2349             : #undef OPCODE_ERROR
    2350             : 
    2351             : }  // namespace wasm
    2352             : }  // namespace internal
    2353             : }  // namespace v8
    2354             : 
    2355             : #endif  // V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_

Generated by: LCOV version 1.10