LCOV - code coverage report
Current view: top level - src/wasm - function-body-decoder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 818 961 85.1 %
Date: 2017-04-26 Functions: 55 65 84.6 %

          Line data    Source code
       1             : // Copyright 2015 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             : #include "src/signature.h"
       6             : 
       7             : #include "src/base/platform/elapsed-timer.h"
       8             : #include "src/bit-vector.h"
       9             : #include "src/flags.h"
      10             : #include "src/handles.h"
      11             : #include "src/objects-inl.h"
      12             : #include "src/zone/zone-containers.h"
      13             : 
      14             : #include "src/wasm/decoder.h"
      15             : #include "src/wasm/function-body-decoder-impl.h"
      16             : #include "src/wasm/function-body-decoder.h"
      17             : #include "src/wasm/wasm-limits.h"
      18             : #include "src/wasm/wasm-module.h"
      19             : #include "src/wasm/wasm-opcodes.h"
      20             : 
      21             : #include "src/ostreams.h"
      22             : 
      23             : #include "src/compiler/wasm-compiler.h"
      24             : 
      25             : namespace v8 {
      26             : namespace internal {
      27             : namespace wasm {
      28             : 
      29             : #if DEBUG
      30             : #define TRACE(...)                                    \
      31             :   do {                                                \
      32             :     if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
      33             :   } while (false)
      34             : #else
      35             : #define TRACE(...)
      36             : #endif
      37             : 
      38             : #define CHECK_PROTOTYPE_OPCODE(flag)                   \
      39             :   if (module_ != nullptr && module_->is_asm_js()) {    \
      40             :     error("Opcode not supported for asmjs modules");   \
      41             :   }                                                    \
      42             :   if (!FLAG_##flag) {                                  \
      43             :     error("Invalid opcode (enable with --" #flag ")"); \
      44             :     break;                                             \
      45             :   }
      46             : 
      47             : // An SsaEnv environment carries the current local variable renaming
      48             : // as well as the current effect and control dependency in the TF graph.
      49             : // It maintains a control state that tracks whether the environment
      50             : // is reachable, has reached a control end, or has been merged.
      51             : struct SsaEnv {
      52             :   enum State { kControlEnd, kUnreachable, kReached, kMerged };
      53             : 
      54             :   State state;
      55             :   TFNode* control;
      56             :   TFNode* effect;
      57             :   TFNode** locals;
      58             : 
      59     3400550 :   bool go() { return state >= kReached; }
      60             :   void Kill(State new_state = kControlEnd) {
      61      806003 :     state = new_state;
      62      806003 :     locals = nullptr;
      63      806003 :     control = nullptr;
      64      806003 :     effect = nullptr;
      65             :   }
      66             :   void SetNotMerged() {
      67       20858 :     if (state == kMerged) state = kReached;
      68             :   }
      69             : };
      70             : 
      71             : // An entry on the value stack.
      72             : struct Value {
      73             :   const byte* pc;
      74             :   TFNode* node;
      75             :   ValueType type;
      76             : };
      77             : 
      78             : struct TryInfo : public ZoneObject {
      79             :   SsaEnv* catch_env;
      80             :   TFNode* exception;
      81             : 
      82         124 :   explicit TryInfo(SsaEnv* c) : catch_env(c), exception(nullptr) {}
      83             : };
      84             : 
      85             : struct MergeValues {
      86             :   uint32_t arity;
      87             :   union {
      88             :     Value* array;
      89             :     Value first;
      90             :   } vals;  // Either multiple values or a single value.
      91             : 
      92             :   Value& operator[](size_t i) {
      93             :     DCHECK_GT(arity, i);
      94       85588 :     return arity == 1 ? vals.first : vals.array[i];
      95             :   }
      96             : };
      97             : 
      98             : static Value* NO_VALUE = nullptr;
      99             : 
     100             : enum ControlKind { kControlIf, kControlBlock, kControlLoop, kControlTry };
     101             : 
     102             : // An entry on the control stack (i.e. if, block, loop).
     103             : struct Control {
     104             :   const byte* pc;
     105             :   ControlKind kind;
     106             :   size_t stack_depth;      // stack height at the beginning of the construct.
     107             :   SsaEnv* end_env;         // end environment for the construct.
     108             :   SsaEnv* false_env;       // false environment (only for if).
     109             :   TryInfo* try_info;       // Information used for compiling try statements.
     110             :   int32_t previous_catch;  // The previous Control (on the stack) with a catch.
     111             :   bool unreachable;        // The current block has been ended.
     112             : 
     113             :   // Values merged into the end of this control construct.
     114             :   MergeValues merge;
     115             : 
     116             :   inline bool is_if() const { return kind == kControlIf; }
     117             :   inline bool is_block() const { return kind == kControlBlock; }
     118             :   inline bool is_loop() const { return kind == kControlLoop; }
     119             :   inline bool is_try() const { return kind == kControlTry; }
     120             : 
     121             :   // Named constructors.
     122             :   static Control Block(const byte* pc, size_t stack_depth, SsaEnv* end_env,
     123             :                        int32_t previous_catch) {
     124             :     return {pc,      kControlBlock,  stack_depth, end_env,        nullptr,
     125      224850 :             nullptr, previous_catch, false,       {0, {NO_VALUE}}};
     126             :   }
     127             : 
     128             :   static Control If(const byte* pc, size_t stack_depth, SsaEnv* end_env,
     129             :                     SsaEnv* false_env, int32_t previous_catch) {
     130             :     return {pc,      kControlIf,     stack_depth, end_env,        false_env,
     131       71911 :             nullptr, previous_catch, false,       {0, {NO_VALUE}}};
     132             :   }
     133             : 
     134             :   static Control Loop(const byte* pc, size_t stack_depth, SsaEnv* end_env,
     135             :                       int32_t previous_catch) {
     136             :     return {pc,      kControlLoop,   stack_depth, end_env,        nullptr,
     137       11623 :             nullptr, previous_catch, false,       {0, {NO_VALUE}}};
     138             :   }
     139             : 
     140             :   static Control Try(const byte* pc, size_t stack_depth, SsaEnv* end_env,
     141             :                      Zone* zone, SsaEnv* catch_env, int32_t previous_catch) {
     142             :     DCHECK_NOT_NULL(catch_env);
     143             :     TryInfo* try_info = new (zone) TryInfo(catch_env);
     144             :     return {pc,       kControlTry,    stack_depth, end_env,        nullptr,
     145         124 :             try_info, previous_catch, false,       {0, {NO_VALUE}}};
     146             :   }
     147             : };
     148             : 
     149             : // Macros that build nodes only if there is a graph and the current SSA
     150             : // environment is reachable from start. This avoids problems with malformed
     151             : // TF graphs when decoding inputs that have unreachable code.
     152             : #define BUILD(func, ...) \
     153             :   (build() ? CheckForException(builder_->func(__VA_ARGS__)) : nullptr)
     154             : #define BUILD0(func) (build() ? CheckForException(builder_->func()) : nullptr)
     155             : 
     156             : // Generic Wasm bytecode decoder with utilities for decoding operands,
     157             : // lengths, etc.
     158      323113 : class WasmDecoder : public Decoder {
     159             :  public:
     160             :   WasmDecoder(const WasmModule* module, FunctionSig* sig, const byte* start,
     161             :               const byte* end)
     162             :       : Decoder(start, end),
     163             :         module_(module),
     164             :         sig_(sig),
     165      323178 :         local_types_(nullptr) {}
     166             :   const WasmModule* module_;
     167             :   FunctionSig* sig_;
     168             : 
     169             :   ZoneVector<ValueType>* local_types_;
     170             : 
     171             :   size_t total_locals() const {
     172      627341 :     return local_types_ == nullptr ? 0 : local_types_->size();
     173             :   }
     174             : 
     175      116968 :   static bool DecodeLocals(Decoder* decoder, const FunctionSig* sig,
     176             :                            ZoneVector<ValueType>* type_list) {
     177             :     DCHECK_NOT_NULL(type_list);
     178             :     DCHECK_EQ(0, type_list->size());
     179             :     // Initialize from signature.
     180      108187 :     if (sig != nullptr) {
     181       95353 :       type_list->assign(sig->parameters().begin(), sig->parameters().end());
     182             :     }
     183             :     // Decode local declarations, if any.
     184             :     uint32_t entries = decoder->consume_u32v("local decls count");
     185      108210 :     if (decoder->failed()) return false;
     186             : 
     187             :     TRACE("local decls count: %u\n", entries);
     188      134409 :     while (entries-- > 0 && decoder->ok() && decoder->more()) {
     189             :       uint32_t count = decoder->consume_u32v("local count");
     190        8783 :       if (decoder->failed()) return false;
     191             : 
     192       17492 :       if ((count + type_list->size()) > kV8MaxWasmFunctionLocals) {
     193           3 :         decoder->error(decoder->pc() - 1, "local count too large");
     194           3 :         return false;
     195             :       }
     196             :       byte code = decoder->consume_u8("local type");
     197        8743 :       if (decoder->failed()) return false;
     198             : 
     199             :       ValueType type;
     200        8742 :       switch (code) {
     201             :         case kLocalI32:
     202        5911 :           type = kWasmI32;
     203        5911 :           break;
     204             :         case kLocalI64:
     205         295 :           type = kWasmI64;
     206         295 :           break;
     207             :         case kLocalF32:
     208         459 :           type = kWasmF32;
     209         459 :           break;
     210             :         case kLocalF64:
     211        1705 :           type = kWasmF64;
     212        1705 :           break;
     213             :         case kLocalS128:
     214         343 :           type = kWasmS128;
     215         343 :           break;
     216             :         case kLocalS1x4:
     217           0 :           type = kWasmS1x4;
     218           0 :           break;
     219             :         case kLocalS1x8:
     220           0 :           type = kWasmS1x8;
     221           0 :           break;
     222             :         case kLocalS1x16:
     223           0 :           type = kWasmS1x16;
     224           0 :           break;
     225             :         default:
     226          29 :           decoder->error(decoder->pc() - 1, "invalid local type");
     227          29 :           return false;
     228             :       }
     229        8713 :       type_list->insert(type_list->end(), count, type);
     230             :     }
     231             :     DCHECK(decoder->ok());
     232             :     return true;
     233             :   }
     234             : 
     235     1867757 :   static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc,
     236             :                                           int locals_count, Zone* zone) {
     237        8845 :     if (pc >= decoder->end()) return nullptr;
     238        8844 :     if (*pc != kExprLoop) return nullptr;
     239             : 
     240      282393 :     BitVector* assigned = new (zone) BitVector(locals_count, zone);
     241             :     int depth = 0;
     242             :     // Iteratively process all AST nodes nested inside the loop.
     243     3726662 :     while (pc < decoder->end() && decoder->ok()) {
     244     1858906 :       WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
     245             :       unsigned length = 1;
     246             :       switch (opcode) {
     247             :         case kExprLoop:
     248             :         case kExprIf:
     249             :         case kExprBlock:
     250             :         case kExprTry:
     251      164840 :           length = OpcodeLength(decoder, pc);
     252      164840 :           depth++;
     253      164840 :           break;
     254             :         case kExprSetLocal:  // fallthru
     255             :         case kExprTeeLocal: {
     256             :           LocalIndexOperand<true> operand(decoder, pc);
     257      273549 :           if (assigned->length() > 0 &&
     258      136774 :               operand.index < static_cast<uint32_t>(assigned->length())) {
     259             :             // Unverified code might have an out-of-bounds index.
     260      136774 :             assigned->Add(operand.index);
     261             :           }
     262      136775 :           length = 1 + operand.length;
     263             :           break;
     264             :         }
     265             :         case kExprEnd:
     266      164834 :           depth--;
     267      164834 :           break;
     268             :         default:
     269     1392457 :           length = OpcodeLength(decoder, pc);
     270     1392457 :           break;
     271             :       }
     272     1858906 :       if (depth <= 0) break;
     273     1850068 :       pc += length;
     274             :     }
     275        8844 :     return decoder->ok() ? assigned : nullptr;
     276             :   }
     277             : 
     278     1237148 :   inline bool Validate(const byte* pc, LocalIndexOperand<true>& operand) {
     279     1237148 :     if (operand.index < total_locals()) {
     280      618545 :       if (local_types_) {
     281      618545 :         operand.type = local_types_->at(operand.index);
     282             :       } else {
     283           0 :         operand.type = kWasmStmt;
     284             :       }
     285             :       return true;
     286             :     }
     287          29 :     errorf(pc + 1, "invalid local index: %u", operand.index);
     288          29 :     return false;
     289             :   }
     290             : 
     291       18832 :   inline bool Validate(const byte* pc, GlobalIndexOperand<true>& operand) {
     292       56496 :     if (module_ != nullptr && operand.index < module_->globals.size()) {
     293       37664 :       operand.global = &module_->globals[operand.index];
     294       18832 :       operand.type = operand.global->type;
     295       18832 :       return true;
     296             :     }
     297           0 :     errorf(pc + 1, "invalid global index: %u", operand.index);
     298           0 :     return false;
     299             :   }
     300             : 
     301             :   inline bool Complete(const byte* pc, CallFunctionOperand<true>& operand) {
     302      109635 :     if (module_ != nullptr && operand.index < module_->functions.size()) {
     303       73094 :       operand.sig = module_->functions[operand.index].sig;
     304             :       return true;
     305             :     }
     306             :     return false;
     307             :   }
     308             : 
     309       33771 :   inline bool Validate(const byte* pc, CallFunctionOperand<true>& operand) {
     310       33771 :     if (Complete(pc, operand)) {
     311             :       return true;
     312             :     }
     313           0 :     errorf(pc + 1, "invalid function index: %u", operand.index);
     314           0 :     return false;
     315             :   }
     316             : 
     317             :   inline bool Complete(const byte* pc, CallIndirectOperand<true>& operand) {
     318        7371 :     if (module_ != nullptr && operand.index < module_->signatures.size()) {
     319        4898 :       operand.sig = module_->signatures[operand.index];
     320             :       return true;
     321             :     }
     322             :     return false;
     323             :   }
     324             : 
     325        2384 :   inline bool Validate(const byte* pc, CallIndirectOperand<true>& operand) {
     326        4768 :     if (module_ == nullptr || module_->function_tables.empty()) {
     327           3 :       error("function table has to exist to execute call_indirect");
     328           3 :       return false;
     329             :     }
     330        2381 :     if (Complete(pc, operand)) {
     331             :       return true;
     332             :     }
     333          12 :     errorf(pc + 1, "invalid signature index: #%u", operand.index);
     334          12 :     return false;
     335             :   }
     336             : 
     337       42973 :   inline bool Validate(const byte* pc, BreakDepthOperand<true>& operand,
     338             :                        ZoneVector<Control>& control) {
     339       85946 :     if (operand.depth < control.size()) {
     340       85024 :       operand.target = &control[control.size() - operand.depth - 1];
     341             :       return true;
     342             :     }
     343         461 :     errorf(pc + 1, "invalid break depth: %u", operand.depth);
     344             :     return false;
     345             :   }
     346             : 
     347             :   bool Validate(const byte* pc, BranchTableOperand<true>& operand,
     348             :                 size_t block_depth) {
     349             :     // TODO(titzer): add extra redundant validation for br_table here?
     350             :     return true;
     351             :   }
     352             : 
     353        5390 :   inline bool Validate(const byte* pc, WasmOpcode opcode,
     354             :                        SimdLaneOperand<true>& operand) {
     355             :     uint8_t num_lanes = 0;
     356        5390 :     switch (opcode) {
     357             :       case kExprF32x4ExtractLane:
     358             :       case kExprF32x4ReplaceLane:
     359             :       case kExprI32x4ExtractLane:
     360             :       case kExprI32x4ReplaceLane:
     361             :         num_lanes = 4;
     362             :         break;
     363             :       case kExprI16x8ExtractLane:
     364             :       case kExprI16x8ReplaceLane:
     365             :         num_lanes = 8;
     366             :         break;
     367             :       case kExprI8x16ExtractLane:
     368             :       case kExprI8x16ReplaceLane:
     369             :         num_lanes = 16;
     370             :         break;
     371             :       default:
     372           0 :         UNREACHABLE();
     373             :         break;
     374             :     }
     375        5390 :     if (operand.lane < 0 || operand.lane >= num_lanes) {
     376           0 :       error(pc_ + 2, "invalid lane index");
     377             :       return false;
     378             :     } else {
     379             :       return true;
     380             :     }
     381             :   }
     382             : 
     383          42 :   inline bool Validate(const byte* pc, WasmOpcode opcode,
     384             :                        SimdShiftOperand<true>& operand) {
     385             :     uint8_t max_shift = 0;
     386          42 :     switch (opcode) {
     387             :       case kExprI32x4Shl:
     388             :       case kExprI32x4ShrS:
     389             :       case kExprI32x4ShrU:
     390             :         max_shift = 32;
     391             :         break;
     392             :       case kExprI16x8Shl:
     393             :       case kExprI16x8ShrS:
     394             :       case kExprI16x8ShrU:
     395             :         max_shift = 16;
     396             :         break;
     397             :       case kExprI8x16Shl:
     398             :       case kExprI8x16ShrS:
     399             :       case kExprI8x16ShrU:
     400             :         max_shift = 8;
     401             :         break;
     402             :       default:
     403           0 :         UNREACHABLE();
     404             :         break;
     405             :     }
     406          42 :     if (operand.shift < 0 || operand.shift >= max_shift) {
     407           0 :       error(pc_ + 2, "invalid shift amount");
     408             :       return false;
     409             :     } else {
     410             :       return true;
     411             :     }
     412             :   }
     413             : 
     414           0 :   inline bool Validate(const byte* pc, WasmOpcode opcode,
     415             :                        SimdConcatOperand<true>& operand) {
     416             :     DCHECK_EQ(wasm::kExprS8x16Concat, opcode);
     417           0 :     if (operand.bytes <= 0 || operand.bytes >= kSimd128Size) {
     418           0 :       error(pc_ + 2, "invalid byte amount");
     419             :       return false;
     420             :     } else {
     421             :       return true;
     422             :     }
     423             :   }
     424             : 
     425     1794963 :   static unsigned OpcodeLength(Decoder* decoder, const byte* pc) {
     426     1794963 :     switch (static_cast<byte>(*pc)) {
     427             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
     428             :       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
     429             :       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
     430             : #undef DECLARE_OPCODE_CASE
     431             :       {
     432       10793 :         MemoryAccessOperand<true> operand(decoder, pc, UINT32_MAX);
     433       10793 :         return 1 + operand.length;
     434             :       }
     435             :       case kExprBr:
     436             :       case kExprBrIf: {
     437             :         BreakDepthOperand<true> operand(decoder, pc);
     438       48303 :         return 1 + operand.length;
     439             :       }
     440             :       case kExprSetGlobal:
     441             :       case kExprGetGlobal: {
     442             :         GlobalIndexOperand<true> operand(decoder, pc);
     443        2811 :         return 1 + operand.length;
     444             :       }
     445             : 
     446             :       case kExprCallFunction: {
     447             :         CallFunctionOperand<true> operand(decoder, pc);
     448       20783 :         return 1 + operand.length;
     449             :       }
     450             :       case kExprCallIndirect: {
     451         731 :         CallIndirectOperand<true> operand(decoder, pc);
     452         731 :         return 1 + operand.length;
     453             :       }
     454             : 
     455             :       case kExprTry:
     456             :       case kExprIf:  // fall thru
     457             :       case kExprLoop:
     458             :       case kExprBlock: {
     459      202797 :         BlockTypeOperand<true> operand(decoder, pc);
     460      202797 :         return 1 + operand.length;
     461             :       }
     462             : 
     463             :       case kExprSetLocal:
     464             :       case kExprTeeLocal:
     465             :       case kExprGetLocal:
     466             :       case kExprCatch: {
     467             :         LocalIndexOperand<true> operand(decoder, pc);
     468      387358 :         return 1 + operand.length;
     469             :       }
     470             :       case kExprBrTable: {
     471        7580 :         BranchTableOperand<true> operand(decoder, pc);
     472             :         BranchTableIterator<true> iterator(decoder, operand);
     473        7580 :         return 1 + iterator.length();
     474             :       }
     475             :       case kExprI32Const: {
     476             :         ImmI32Operand<true> operand(decoder, pc);
     477      387143 :         return 1 + operand.length;
     478             :       }
     479             :       case kExprI64Const: {
     480             :         ImmI64Operand<true> operand(decoder, pc);
     481        4230 :         return 1 + operand.length;
     482             :       }
     483             :       case kExprGrowMemory:
     484             :       case kExprMemorySize: {
     485          52 :         MemoryIndexOperand<true> operand(decoder, pc);
     486          52 :         return 1 + operand.length;
     487             :       }
     488             :       case kExprF32Const:
     489             :         return 5;
     490             :       case kExprF64Const:
     491        4402 :         return 9;
     492             :       case kSimdPrefix: {
     493         168 :         byte simd_index = decoder->read_u8<true>(pc + 1, "simd_index");
     494             :         WasmOpcode opcode =
     495         168 :             static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
     496         168 :         switch (opcode) {
     497             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
     498             :           FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
     499             : #undef DECLARE_OPCODE_CASE
     500             :           {
     501             :             return 2;
     502             :           }
     503             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
     504             :           FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
     505             : #undef DECLARE_OPCODE_CASE
     506             :           {
     507          18 :             return 3;
     508             :           }
     509             :           default:
     510             :             decoder->error(pc, "invalid SIMD opcode");
     511           1 :             return 2;
     512             :         }
     513             :       }
     514             :       default:
     515      717475 :         return 1;
     516             :     }
     517             :   }
     518             : 
     519      239451 :   std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) {
     520      236601 :     WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
     521             :     // Handle "simple" opcodes with a fixed signature first.
     522      241831 :     FunctionSig* sig = WasmOpcodes::Signature(opcode);
     523      236601 :     if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode);
     524      241831 :     if (sig) return {sig->parameter_count(), sig->return_count()};
     525             : 
     526             : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
     527             :     // clang-format off
     528      231371 :     switch (opcode) {
     529             :       case kExprSelect:
     530          35 :         return {3, 1};
     531             :       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
     532         927 :         return {2, 0};
     533             :       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
     534             :       case kExprTeeLocal:
     535             :       case kExprGrowMemory:
     536        9762 :         return {1, 1};
     537             :       case kExprSetLocal:
     538             :       case kExprSetGlobal:
     539             :       case kExprDrop:
     540             :       case kExprBrIf:
     541             :       case kExprBrTable:
     542             :       case kExprIf:
     543       10435 :         return {1, 0};
     544             :       case kExprGetLocal:
     545             :       case kExprGetGlobal:
     546             :       case kExprI32Const:
     547             :       case kExprI64Const:
     548             :       case kExprF32Const:
     549             :       case kExprF64Const:
     550             :       case kExprMemorySize:
     551       76892 :         return {0, 1};
     552             :       case kExprCallFunction: {
     553        2770 :         CallFunctionOperand<true> operand(this, pc);
     554        2770 :         CHECK(Complete(pc, operand));
     555        5540 :         return {operand.sig->parameter_count(), operand.sig->return_count()};
     556             :       }
     557             :       case kExprCallIndirect: {
     558          80 :         CallIndirectOperand<true> operand(this, pc);
     559          80 :         CHECK(Complete(pc, operand));
     560             :         // Indirect calls pop an additional argument for the table index.
     561          80 :         return {operand.sig->parameter_count() + 1,
     562         160 :                 operand.sig->return_count()};
     563             :       }
     564             :       case kExprBr:
     565             :       case kExprBlock:
     566             :       case kExprLoop:
     567             :       case kExprEnd:
     568             :       case kExprElse:
     569             :       case kExprNop:
     570             :       case kExprReturn:
     571             :       case kExprUnreachable:
     572      130470 :         return {0, 0};
     573             :       default:
     574           0 :         V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x", opcode);
     575             :         return {0, 0};
     576             :     }
     577             : #undef DECLARE_OPCODE_CASE
     578             :     // clang-format on
     579             :   }
     580             : };
     581             : 
     582             : static const int32_t kNullCatch = -1;
     583             : 
     584             : // The full WASM decoder for bytecode. Verifies bytecode and, optionally,
     585             : // generates a TurboFan IR graph.
     586       86512 : class WasmFullDecoder : public WasmDecoder {
     587             :  public:
     588       14839 :   WasmFullDecoder(Zone* zone, const wasm::WasmModule* module,
     589             :                   const FunctionBody& body)
     590       14839 :       : WasmFullDecoder(zone, module, nullptr, body) {}
     591             : 
     592       71738 :   WasmFullDecoder(Zone* zone, TFBuilder* builder, const FunctionBody& body)
     593             :       : WasmFullDecoder(zone, builder->module_env() == nullptr
     594             :                                   ? nullptr
     595             :                                   : builder->module_env()->module,
     596      143476 :                         builder, body) {}
     597             : 
     598       86567 :   bool Decode() {
     599       86567 :     if (FLAG_wasm_code_fuzzer_gen_test) {
     600           0 :       PrintRawWasmCode(start_, end_);
     601             :     }
     602             :     base::ElapsedTimer decode_timer;
     603       86518 :     if (FLAG_trace_wasm_decode_time) {
     604             :       decode_timer.Start();
     605             :     }
     606             :     stack_.clear();
     607             :     control_.clear();
     608             : 
     609       86518 :     if (end_ < pc_) {
     610           0 :       error("function body end < start");
     611           0 :       return false;
     612             :     }
     613             : 
     614             :     DCHECK_EQ(0, local_types_->size());
     615       86518 :     WasmDecoder::DecodeLocals(this, sig_, local_types_);
     616       86617 :     InitSsaEnv();
     617       86599 :     DecodeFunctionBody();
     618             : 
     619       86607 :     if (failed()) return TraceFailed();
     620             : 
     621       75823 :     if (!control_.empty()) {
     622             :       // Generate a better error message whether the unterminated control
     623             :       // structure is the function body block or an innner structure.
     624          53 :       if (control_.size() > 1) {
     625           0 :         error(control_.back().pc, "unterminated control structure");
     626             :       } else {
     627             :         error("function body must end with \"end\" opcode.");
     628             :       }
     629             :       return TraceFailed();
     630             :     }
     631             : 
     632       75770 :     if (!last_end_found_) {
     633             :       error("function body must end with \"end\" opcode.");
     634           0 :       return false;
     635             :     }
     636             : 
     637       75770 :     if (FLAG_trace_wasm_decode_time) {
     638           0 :       double ms = decode_timer.Elapsed().InMillisecondsF();
     639           0 :       PrintF("wasm-decode %s (%0.3f ms)\n\n", ok() ? "ok" : "failed", ms);
     640             :     } else {
     641             :       TRACE("wasm-decode %s\n\n", ok() ? "ok" : "failed");
     642             :     }
     643             : 
     644             :     return true;
     645             :   }
     646             : 
     647             :   bool TraceFailed() {
     648             :     TRACE("wasm-error module+%-6d func+%d: %s\n\n", baserel(error_pc_),
     649             :           startrel(error_pc_), error_msg_.c_str());
     650             :     return false;
     651             :   }
     652             : 
     653             :  private:
     654             :   WasmFullDecoder(Zone* zone, const wasm::WasmModule* module,
     655             :                   TFBuilder* builder, const FunctionBody& body)
     656             :       : WasmDecoder(module, body.sig, body.start, body.end),
     657             :         zone_(zone),
     658             :         builder_(builder),
     659             :         base_(body.base),
     660             :         local_type_vec_(zone),
     661             :         stack_(zone),
     662             :         control_(zone),
     663             :         last_end_found_(false),
     664      259731 :         current_catch_(kNullCatch) {
     665       86577 :     local_types_ = &local_type_vec_;
     666             :   }
     667             : 
     668             :   static const size_t kErrorMsgSize = 128;
     669             : 
     670             :   Zone* zone_;
     671             :   TFBuilder* builder_;
     672             :   const byte* base_;
     673             : 
     674             :   SsaEnv* ssa_env_;
     675             : 
     676             :   ZoneVector<ValueType> local_type_vec_;  // types of local variables.
     677             :   ZoneVector<Value> stack_;               // stack of values.
     678             :   ZoneVector<Control> control_;           // stack of blocks, loops, and ifs.
     679             :   bool last_end_found_;
     680             : 
     681             :   int32_t current_catch_;
     682             : 
     683         300 :   TryInfo* current_try_info() { return control_[current_catch_].try_info; }
     684             : 
     685     4020319 :   inline bool build() { return builder_ && ssa_env_->go(); }
     686             : 
     687       86616 :   void InitSsaEnv() {
     688             :     TFNode* start = nullptr;
     689       86616 :     SsaEnv* ssa_env = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
     690       86627 :     size_t size = sizeof(TFNode*) * EnvironmentCount();
     691       86627 :     ssa_env->state = SsaEnv::kReached;
     692             :     ssa_env->locals =
     693       86627 :         size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
     694             : 
     695       86634 :     if (builder_) {
     696      265866 :       start = builder_->Start(static_cast<int>(sig_->parameter_count() + 1));
     697             :       // Initialize local variables.
     698             :       uint32_t index = 0;
     699      459950 :       while (index < sig_->parameter_count()) {
     700      122306 :         ssa_env->locals[index] = builder_->Param(index);
     701      122302 :         index++;
     702             :       }
     703      158604 :       while (index < local_type_vec_.size()) {
     704      122521 :         ValueType type = local_type_vec_[index];
     705        7524 :         TFNode* node = DefaultValue(type);
     706      109067 :         while (index < local_type_vec_.size() &&
     707       30153 :                local_type_vec_[index] == type) {
     708             :           // Do a whole run of like-typed locals at a time.
     709       28171 :           ssa_env->locals[index++] = node;
     710             :         }
     711             :       }
     712             :     }
     713       86630 :     ssa_env->control = start;
     714       86630 :     ssa_env->effect = start;
     715             :     SetEnv("initial", ssa_env);
     716       86630 :     if (builder_) {
     717             :       // The function-prologue stack check is associated with position 0, which
     718             :       // is never a position of any instruction in the function.
     719       71784 :       builder_->StackCheck(0);
     720             :     }
     721       86609 :   }
     722             : 
     723        7524 :   TFNode* DefaultValue(ValueType type) {
     724        7524 :     switch (type) {
     725             :       case kWasmI32:
     726        5424 :         return builder_->Int32Constant(0);
     727             :       case kWasmI64:
     728          91 :         return builder_->Int64Constant(0);
     729             :       case kWasmF32:
     730         220 :         return builder_->Float32Constant(0);
     731             :       case kWasmF64:
     732        1446 :         return builder_->Float64Constant(0);
     733             :       case kWasmS128:
     734         343 :         return builder_->S128Zero();
     735             :       case kWasmS1x4:
     736           0 :         return builder_->S1x4Zero();
     737             :       case kWasmS1x8:
     738           0 :         return builder_->S1x8Zero();
     739             :       case kWasmS1x16:
     740           0 :         return builder_->S1x16Zero();
     741             :       default:
     742           0 :         UNREACHABLE();
     743             :         return nullptr;
     744             :     }
     745             :   }
     746             : 
     747             :   char* indentation() {
     748             :     static const int kMaxIndent = 64;
     749             :     static char bytes[kMaxIndent + 1];
     750             :     for (int i = 0; i < kMaxIndent; ++i) bytes[i] = ' ';
     751             :     bytes[kMaxIndent] = 0;
     752             :     if (stack_.size() < kMaxIndent / 2) {
     753             :       bytes[stack_.size() * 2] = 0;
     754             :     }
     755             :     return bytes;
     756             :   }
     757             : 
     758       19587 :   bool CheckHasMemory() {
     759       19587 :     if (!module_->has_memory) {
     760          15 :       error(pc_ - 1, "memory instruction with no memory");
     761             :     }
     762       19587 :     return module_->has_memory;
     763             :   }
     764             : 
     765             :   // Decodes the body of a function.
     766     1283409 :   void DecodeFunctionBody() {
     767             :     TRACE("wasm-decode %p...%p (module+%d, %d bytes) %s\n",
     768             :           reinterpret_cast<const void*>(start_),
     769             :           reinterpret_cast<const void*>(end_), baserel(pc_),
     770             :           static_cast<int>(end_ - start_), builder_ ? "graph building" : "");
     771             : 
     772             :     {
     773             :       // Set up initial function block.
     774       86565 :       SsaEnv* break_env = ssa_env_;
     775       86565 :       SetEnv("initial env", Steal(break_env));
     776       86573 :       PushBlock(break_env);
     777      397954 :       Control* c = &control_.back();
     778      160653 :       c->merge.arity = static_cast<uint32_t>(sig_->return_count());
     779             : 
     780       86549 :       if (c->merge.arity == 1) {
     781      142504 :         c->merge.vals.first = {pc_, nullptr, sig_->GetReturn(0)};
     782       15297 :       } else if (c->merge.arity > 1) {
     783        2848 :         c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity);
     784        4276 :         for (unsigned i = 0; i < c->merge.arity; i++) {
     785        5704 :           c->merge.vals.array[i] = {pc_, nullptr, sig_->GetReturn(i)};
     786             :         }
     787             :       }
     788             :     }
     789             : 
     790     2579761 :     while (pc_ < end_) {  // decoding loop.
     791             :       unsigned len = 1;
     792     2493339 :       WasmOpcode opcode = static_cast<WasmOpcode>(*pc_);
     793             : #if DEBUG
     794             :       if (FLAG_trace_wasm_decoder && !WasmOpcodes::IsPrefixOpcode(opcode)) {
     795             :         TRACE("  @%-8d #%-20s|", startrel(pc_),
     796             :               WasmOpcodes::OpcodeName(opcode));
     797             :       }
     798             : #endif
     799             : 
     800     2493339 :       FunctionSig* sig = WasmOpcodes::Signature(opcode);
     801     2493354 :       if (sig) {
     802      411395 :         BuildSimpleOperator(opcode, sig);
     803             :       } else {
     804             :         // Complex bytecode.
     805     2081959 :         switch (opcode) {
     806             :           case kExprNop:
     807             :             break;
     808             :           case kExprBlock: {
     809             :             // The break environment is the outer environment.
     810      138277 :             BlockTypeOperand<true> operand(this, pc_);
     811      138277 :             SsaEnv* break_env = ssa_env_;
     812      138277 :             PushBlock(break_env);
     813      138277 :             SetEnv("block:start", Steal(break_env));
     814      138277 :             SetBlockType(&control_.back(), operand);
     815      138277 :             len = 1 + operand.length;
     816             :             break;
     817             :           }
     818             :           case kExprThrow: {
     819      128093 :             CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
     820         169 :             Value value = Pop(0, kWasmI32);
     821         169 :             BUILD(Throw, value.node);
     822             :             // TODO(titzer): Throw should end control, but currently we build a
     823             :             // (reachable) runtime call instead of connecting it directly to
     824             :             // end.
     825             :             //            EndControl();
     826             :             break;
     827             :           }
     828             :           case kExprTry: {
     829         368 :             CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
     830         124 :             BlockTypeOperand<true> operand(this, pc_);
     831         124 :             SsaEnv* outer_env = ssa_env_;
     832         124 :             SsaEnv* try_env = Steal(outer_env);
     833             :             SsaEnv* catch_env = UnreachableEnv();
     834         124 :             PushTry(outer_env, catch_env);
     835             :             SetEnv("try_catch:start", try_env);
     836         124 :             SetBlockType(&control_.back(), operand);
     837         124 :             len = 1 + operand.length;
     838         124 :             break;
     839             :           }
     840             :           case kExprCatch: {
     841         368 :             CHECK_PROTOTYPE_OPCODE(wasm_eh_prototype);
     842         124 :             LocalIndexOperand<true> operand(this, pc_);
     843         124 :             len = 1 + operand.length;
     844             : 
     845         124 :             if (control_.empty()) {
     846             :               error("catch does not match any try");
     847             :               break;
     848             :             }
     849             : 
     850         124 :             Control* c = &control_.back();
     851         124 :             if (!c->is_try()) {
     852             :               error("catch does not match any try");
     853             :               break;
     854             :             }
     855             : 
     856         124 :             if (c->try_info->catch_env == nullptr) {
     857           1 :               error(pc_, "catch already present for try with catch");
     858             :               break;
     859             :             }
     860             : 
     861         123 :             FallThruTo(c);
     862       19954 :             stack_.resize(c->stack_depth);
     863             : 
     864             :             DCHECK_NOT_NULL(c->try_info);
     865         123 :             SsaEnv* catch_env = c->try_info->catch_env;
     866         123 :             c->try_info->catch_env = nullptr;
     867             :             SetEnv("catch:begin", catch_env);
     868         123 :             current_catch_ = c->previous_catch;
     869             : 
     870         123 :             if (Validate(pc_, operand)) {
     871       75888 :               if (ssa_env_->locals) {
     872             :                 TFNode* exception_as_i32 =
     873         240 :                     BUILD(Catch, c->try_info->exception, position());
     874         120 :                 ssa_env_->locals[operand.index] = exception_as_i32;
     875             :               }
     876             :             }
     877             : 
     878             :             break;
     879             :           }
     880             :           case kExprLoop: {
     881       11623 :             BlockTypeOperand<true> operand(this, pc_);
     882       11623 :             SsaEnv* finish_try_env = Steal(ssa_env_);
     883             :             // The continue environment is the inner environment.
     884       11623 :             SsaEnv* loop_body_env = PrepareForLoop(pc_, finish_try_env);
     885             :             SetEnv("loop:start", loop_body_env);
     886       11623 :             ssa_env_->SetNotMerged();
     887       11623 :             PushLoop(finish_try_env);
     888       11623 :             SetBlockType(&control_.back(), operand);
     889       11623 :             len = 1 + operand.length;
     890             :             break;
     891             :           }
     892             :           case kExprIf: {
     893             :             // Condition on top of stack. Split environments for branches.
     894       71911 :             BlockTypeOperand<true> operand(this, pc_);
     895       71911 :             Value cond = Pop(0, kWasmI32);
     896       71911 :             TFNode* if_true = nullptr;
     897       71911 :             TFNode* if_false = nullptr;
     898       71911 :             BUILD(BranchNoHint, cond.node, &if_true, &if_false);
     899       71911 :             SsaEnv* end_env = ssa_env_;
     900       71911 :             SsaEnv* false_env = Split(ssa_env_);
     901       71911 :             false_env->control = if_false;
     902       71911 :             SsaEnv* true_env = Steal(ssa_env_);
     903       71911 :             true_env->control = if_true;
     904       71911 :             PushIf(end_env, false_env);
     905             :             SetEnv("if:true", true_env);
     906       71911 :             SetBlockType(&control_.back(), operand);
     907       71911 :             len = 1 + operand.length;
     908             :             break;
     909             :           }
     910             :           case kExprElse: {
     911       30867 :             if (control_.empty()) {
     912           0 :               error("else does not match any if");
     913             :               break;
     914             :             }
     915       30867 :             Control* c = &control_.back();
     916       30867 :             if (!c->is_if()) {
     917           0 :               error(pc_, "else does not match an if");
     918             :               break;
     919             :             }
     920       30867 :             if (c->false_env == nullptr) {
     921           2 :               error(pc_, "else already present for if");
     922             :               break;
     923             :             }
     924       30865 :             FallThruTo(c);
     925       30865 :             stack_.resize(c->stack_depth);
     926             :             // Switch to environment for false branch.
     927       30865 :             SetEnv("if_else:false", c->false_env);
     928       30865 :             c->false_env = nullptr;  // record that an else is already seen
     929       30865 :             break;
     930             :           }
     931             :           case kExprEnd: {
     932      295599 :             if (control_.empty()) {
     933           0 :               error("end does not match any if, try, or block");
     934             :               return;
     935             :             }
     936             :             const char* name = "block:end";
     937      295599 :             Control* c = &control_.back();
     938      295599 :             if (c->is_loop()) {
     939             :               // A loop just leaves the values on the stack.
     940       10243 :               TypeCheckFallThru(c);
     941       10243 :               if (c->unreachable) PushEndValues(c);
     942             :               PopControl();
     943       10243 :               SetEnv("loop:end", ssa_env_);
     944             :               break;
     945             :             }
     946      285356 :             if (c->is_if()) {
     947       71853 :               if (c->false_env != nullptr) {
     948             :                 // End the true branch of a one-armed if.
     949       41011 :                 Goto(c->false_env, c->end_env);
     950       60842 :                 if (!c->unreachable && stack_.size() != c->stack_depth) {
     951           1 :                   error("end of if expected empty stack");
     952           1 :                   stack_.resize(c->stack_depth);
     953             :                 }
     954       41011 :                 if (c->merge.arity > 0) {
     955           0 :                   error("non-void one-armed if");
     956             :                 }
     957             :                 name = "if:merge";
     958             :               } else {
     959             :                 // End the false branch of a two-armed if.
     960             :                 name = "if_else:merge";
     961             :               }
     962      213503 :             } else if (c->is_try()) {
     963             :               name = "try:end";
     964             : 
     965             :               // validate that catch was seen.
     966         123 :               if (c->try_info->catch_env != nullptr) {
     967           1 :                 error(pc_, "missing catch in try");
     968             :                 break;
     969             :               }
     970             :             }
     971      285355 :             FallThruTo(c);
     972      285359 :             SetEnv(name, c->end_env);
     973      285359 :             PushEndValues(c);
     974             : 
     975      285389 :             if (control_.size() == 1) {
     976             :               // If at the last (implicit) control, check we are at end.
     977       76815 :               if (pc_ + 1 != end_) {
     978        1050 :                 error(pc_ + 1, "trailing code after function end");
     979             :                 break;
     980             :               }
     981       75765 :               last_end_found_ = true;
     982      151530 :               if (ssa_env_->go()) {
     983             :                 // The result of the block is the return value.
     984             :                 TRACE("  @%-8d #xx:%-20s|", startrel(pc_), "(implicit) return");
     985       60157 :                 DoReturn();
     986             :                 TRACE("\n");
     987             :               } else {
     988       15608 :                 TypeCheckFallThru(c);
     989             :               }
     990             :             }
     991             :             PopControl();
     992             :             break;
     993             :           }
     994             :           case kExprSelect: {
     995         123 :             Value cond = Pop(2, kWasmI32);
     996         123 :             Value fval = Pop();
     997         123 :             Value tval = Pop(0, fval.type);
     998         123 :             if (build()) {
     999             :               TFNode* controls[2];
    1000          95 :               builder_->BranchNoHint(cond.node, &controls[0], &controls[1]);
    1001          95 :               TFNode* merge = builder_->Merge(2, controls);
    1002          95 :               TFNode* vals[2] = {tval.node, fval.node};
    1003          95 :               TFNode* phi = builder_->Phi(tval.type, 2, vals, merge);
    1004             :               Push(tval.type, phi);
    1005          95 :               ssa_env_->control = merge;
    1006             :             } else {
    1007          28 :               Push(tval.type == kWasmVar ? fval.type : tval.type, nullptr);
    1008             :             }
    1009             :             break;
    1010             :           }
    1011             :           case kExprBr: {
    1012       33738 :             BreakDepthOperand<true> operand(this, pc_);
    1013       33738 :             if (Validate(pc_, operand, control_)) {
    1014       33277 :               BreakTo(operand.depth);
    1015             :             }
    1016       33738 :             len = 1 + operand.length;
    1017       33738 :             EndControl();
    1018             :             break;
    1019             :           }
    1020             :           case kExprBrIf: {
    1021        9247 :             BreakDepthOperand<true> operand(this, pc_);
    1022        9247 :             Value cond = Pop(0, kWasmI32);
    1023        9247 :             if (ok() && Validate(pc_, operand, control_)) {
    1024        9235 :               SsaEnv* fenv = ssa_env_;
    1025        9235 :               SsaEnv* tenv = Split(fenv);
    1026             :               fenv->SetNotMerged();
    1027        9235 :               BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
    1028        9235 :               ssa_env_ = tenv;
    1029        9235 :               BreakTo(operand.depth);
    1030        9235 :               ssa_env_ = fenv;
    1031             :             }
    1032        9247 :             len = 1 + operand.length;
    1033             :             break;
    1034             :           }
    1035             :           case kExprBrTable: {
    1036        7848 :             BranchTableOperand<true> operand(this, pc_);
    1037             :             BranchTableIterator<true> iterator(this, operand);
    1038             :             if (Validate(pc_, operand, control_.size())) {
    1039        7848 :               Value key = Pop(0, kWasmI32);
    1040        7848 :               if (failed()) break;
    1041             : 
    1042        7847 :               SsaEnv* break_env = ssa_env_;
    1043        7847 :               if (operand.table_count > 0) {
    1044             :                 // Build branches to the various blocks based on the table.
    1045        7721 :                 TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node);
    1046             : 
    1047        7721 :                 SsaEnv* copy = Steal(break_env);
    1048        7721 :                 ssa_env_ = copy;
    1049             :                 MergeValues* merge = nullptr;
    1050      135522 :                 while (ok() && iterator.has_next()) {
    1051       56227 :                   uint32_t i = iterator.cur_index();
    1052       56227 :                   const byte* pos = iterator.pc();
    1053       56227 :                   uint32_t target = iterator.next();
    1054      112454 :                   if (target >= control_.size()) {
    1055             :                     error(pos, "improper branch in br_table");
    1056             :                     break;
    1057             :                   }
    1058       56212 :                   ssa_env_ = Split(copy);
    1059       56212 :                   ssa_env_->control = (i == operand.table_count)
    1060        7624 :                                           ? BUILD(IfDefault, sw)
    1061      120048 :                                           : BUILD(IfValue, i, sw);
    1062       56212 :                   BreakTo(target);
    1063             : 
    1064             :                   // Check that label types match up.
    1065             :                   static MergeValues loop_dummy = {0, {nullptr}};
    1066      112424 :                   Control* c = &control_[control_.size() - target - 1];
    1067       56212 :                   MergeValues* current = c->is_loop() ? &loop_dummy : &c->merge;
    1068       56212 :                   if (i == 0) {
    1069             :                     merge = current;
    1070       48491 :                   } else if (merge->arity != current->arity) {
    1071             :                     errorf(pos,
    1072             :                            "inconsistent arity in br_table target %d"
    1073             :                            " (previous was %u, this one %u)",
    1074          32 :                            i, merge->arity, current->arity);
    1075       48459 :                   } else if (control_.back().unreachable) {
    1076         144 :                     for (uint32_t j = 0; ok() && j < merge->arity; ++j) {
    1077         144 :                       if ((*merge)[j].type != (*current)[j].type) {
    1078             :                         errorf(pos,
    1079             :                                "type error in br_table target %d operand %d"
    1080             :                                " (previous expected %s, this one %s)",
    1081             :                                i, j, WasmOpcodes::TypeName((*merge)[j].type),
    1082          64 :                                WasmOpcodes::TypeName((*current)[j].type));
    1083             :                       }
    1084             :                     }
    1085             :                   }
    1086             :                 }
    1087        7721 :                 if (failed()) break;
    1088             :               } else {
    1089             :                 // Only a default target. Do the equivalent of br.
    1090         126 :                 const byte* pos = iterator.pc();
    1091         126 :                 uint32_t target = iterator.next();
    1092         252 :                 if (target >= control_.size()) {
    1093             :                   error(pos, "improper branch in br_table");
    1094             :                   break;
    1095             :                 }
    1096         116 :                 BreakTo(target);
    1097             :               }
    1098             :               // br_table ends the control flow like br.
    1099        7757 :               ssa_env_ = break_env;
    1100             :             }
    1101        7757 :             len = 1 + iterator.length();
    1102        7757 :             EndControl();
    1103        7757 :             break;
    1104             :           }
    1105             :           case kExprReturn: {
    1106       79069 :             DoReturn();
    1107       79069 :             break;
    1108             :           }
    1109             :           case kExprUnreachable: {
    1110        1706 :             BUILD(Unreachable, position());
    1111        1267 :             EndControl();
    1112        1267 :             break;
    1113             :           }
    1114             :           case kExprI32Const: {
    1115      470450 :             ImmI32Operand<true> operand(this, pc_);
    1116      470440 :             Push(kWasmI32, BUILD(Int32Constant, operand.value));
    1117      470541 :             len = 1 + operand.length;
    1118             :             break;
    1119             :           }
    1120             :           case kExprI64Const: {
    1121        6108 :             ImmI64Operand<true> operand(this, pc_);
    1122        6108 :             Push(kWasmI64, BUILD(Int64Constant, operand.value));
    1123        6108 :             len = 1 + operand.length;
    1124             :             break;
    1125             :           }
    1126             :           case kExprF32Const: {
    1127         944 :             ImmF32Operand<true> operand(this, pc_);
    1128         944 :             Push(kWasmF32, BUILD(Float32Constant, operand.value));
    1129         944 :             len = 1 + operand.length;
    1130             :             break;
    1131             :           }
    1132             :           case kExprF64Const: {
    1133       10799 :             ImmF64Operand<true> operand(this, pc_);
    1134       10799 :             Push(kWasmF64, BUILD(Float64Constant, operand.value));
    1135       10798 :             len = 1 + operand.length;
    1136             :             break;
    1137             :           }
    1138             :           case kExprGetLocal: {
    1139      469047 :             LocalIndexOperand<true> operand(this, pc_);
    1140      469063 :             if (Validate(pc_, operand)) {
    1141      469079 :               if (build()) {
    1142      451812 :                 Push(operand.type, ssa_env_->locals[operand.index]);
    1143             :               } else {
    1144       17267 :                 Push(operand.type, nullptr);
    1145             :               }
    1146             :             }
    1147      469104 :             len = 1 + operand.length;
    1148             :             break;
    1149             :           }
    1150             :           case kExprSetLocal: {
    1151      132019 :             LocalIndexOperand<true> operand(this, pc_);
    1152      132019 :             if (Validate(pc_, operand)) {
    1153      281373 :               Value val = Pop(0, local_type_vec_[operand.index]);
    1154      132013 :               if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node;
    1155             :             }
    1156      132017 :             len = 1 + operand.length;
    1157             :             break;
    1158             :           }
    1159             :           case kExprTeeLocal: {
    1160       17344 :             LocalIndexOperand<true> operand(this, pc_);
    1161       17344 :             if (Validate(pc_, operand)) {
    1162       34686 :               Value val = Pop(0, local_type_vec_[operand.index]);
    1163       17343 :               if (ssa_env_->locals) ssa_env_->locals[operand.index] = val.node;
    1164       17343 :               Push(val.type, val.node);
    1165             :             }
    1166       17344 :             len = 1 + operand.length;
    1167             :             break;
    1168             :           }
    1169             :           case kExprDrop: {
    1170       71164 :             Pop();
    1171       71164 :             break;
    1172             :           }
    1173             :           case kExprGetGlobal: {
    1174        7854 :             GlobalIndexOperand<true> operand(this, pc_);
    1175        7854 :             if (Validate(pc_, operand)) {
    1176        7854 :               Push(operand.type, BUILD(GetGlobal, operand.index));
    1177             :             }
    1178        7854 :             len = 1 + operand.length;
    1179             :             break;
    1180             :           }
    1181             :           case kExprSetGlobal: {
    1182       10978 :             GlobalIndexOperand<true> operand(this, pc_);
    1183       10978 :             if (Validate(pc_, operand)) {
    1184       10978 :               if (operand.global->mutability) {
    1185       10977 :                 Value val = Pop(0, operand.type);
    1186       10977 :                 BUILD(SetGlobal, operand.index, val.node);
    1187             :               } else {
    1188             :                 errorf(pc_, "immutable global #%u cannot be assigned",
    1189           1 :                        operand.index);
    1190             :               }
    1191             :             }
    1192       10978 :             len = 1 + operand.length;
    1193             :             break;
    1194             :           }
    1195             :           case kExprI32LoadMem8S:
    1196        4961 :             len = DecodeLoadMem(kWasmI32, MachineType::Int8());
    1197        4961 :             break;
    1198             :           case kExprI32LoadMem8U:
    1199         295 :             len = DecodeLoadMem(kWasmI32, MachineType::Uint8());
    1200         295 :             break;
    1201             :           case kExprI32LoadMem16S:
    1202          34 :             len = DecodeLoadMem(kWasmI32, MachineType::Int16());
    1203          34 :             break;
    1204             :           case kExprI32LoadMem16U:
    1205         310 :             len = DecodeLoadMem(kWasmI32, MachineType::Uint16());
    1206         310 :             break;
    1207             :           case kExprI32LoadMem:
    1208        5894 :             len = DecodeLoadMem(kWasmI32, MachineType::Int32());
    1209        5894 :             break;
    1210             :           case kExprI64LoadMem8S:
    1211          19 :             len = DecodeLoadMem(kWasmI64, MachineType::Int8());
    1212          19 :             break;
    1213             :           case kExprI64LoadMem8U:
    1214           5 :             len = DecodeLoadMem(kWasmI64, MachineType::Uint8());
    1215           5 :             break;
    1216             :           case kExprI64LoadMem16S:
    1217          19 :             len = DecodeLoadMem(kWasmI64, MachineType::Int16());
    1218          19 :             break;
    1219             :           case kExprI64LoadMem16U:
    1220           5 :             len = DecodeLoadMem(kWasmI64, MachineType::Uint16());
    1221           5 :             break;
    1222             :           case kExprI64LoadMem32S:
    1223          19 :             len = DecodeLoadMem(kWasmI64, MachineType::Int32());
    1224          19 :             break;
    1225             :           case kExprI64LoadMem32U:
    1226           5 :             len = DecodeLoadMem(kWasmI64, MachineType::Uint32());
    1227           5 :             break;
    1228             :           case kExprI64LoadMem:
    1229        1073 :             len = DecodeLoadMem(kWasmI64, MachineType::Int64());
    1230        1073 :             break;
    1231             :           case kExprF32LoadMem:
    1232        1623 :             len = DecodeLoadMem(kWasmF32, MachineType::Float32());
    1233        1623 :             break;
    1234             :           case kExprF64LoadMem:
    1235        1868 :             len = DecodeLoadMem(kWasmF64, MachineType::Float64());
    1236        1868 :             break;
    1237             :           case kExprS128LoadMem:
    1238           0 :             CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype);
    1239           0 :             len = DecodeLoadMem(kWasmS128, MachineType::Simd128());
    1240           0 :             break;
    1241             :           case kExprI32StoreMem8:
    1242         322 :             len = DecodeStoreMem(kWasmI32, MachineType::Int8());
    1243         322 :             break;
    1244             :           case kExprI32StoreMem16:
    1245         293 :             len = DecodeStoreMem(kWasmI32, MachineType::Int16());
    1246         293 :             break;
    1247             :           case kExprI32StoreMem:
    1248         784 :             len = DecodeStoreMem(kWasmI32, MachineType::Int32());
    1249         784 :             break;
    1250             :           case kExprI64StoreMem8:
    1251           0 :             len = DecodeStoreMem(kWasmI64, MachineType::Int8());
    1252           0 :             break;
    1253             :           case kExprI64StoreMem16:
    1254           0 :             len = DecodeStoreMem(kWasmI64, MachineType::Int16());
    1255           0 :             break;
    1256             :           case kExprI64StoreMem32:
    1257           0 :             len = DecodeStoreMem(kWasmI64, MachineType::Int32());
    1258           0 :             break;
    1259             :           case kExprI64StoreMem:
    1260         167 :             len = DecodeStoreMem(kWasmI64, MachineType::Int64());
    1261         167 :             break;
    1262             :           case kExprF32StoreMem:
    1263         177 :             len = DecodeStoreMem(kWasmF32, MachineType::Float32());
    1264         177 :             break;
    1265             :           case kExprF64StoreMem:
    1266         205 :             len = DecodeStoreMem(kWasmF64, MachineType::Float64());
    1267         205 :             break;
    1268             :           case kExprS128StoreMem:
    1269           0 :             CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype);
    1270           0 :             len = DecodeStoreMem(kWasmS128, MachineType::Simd128());
    1271           0 :             break;
    1272             :           case kExprGrowMemory: {
    1273         939 :             if (!CheckHasMemory()) break;
    1274         924 :             MemoryIndexOperand<true> operand(this, pc_);
    1275             :             DCHECK_NOT_NULL(module_);
    1276        1848 :             if (module_->is_wasm()) {
    1277         923 :               Value val = Pop(0, kWasmI32);
    1278         923 :               Push(kWasmI32, BUILD(GrowMemory, val.node));
    1279             :             } else {
    1280             :               error("grow_memory is not supported for asmjs modules");
    1281             :             }
    1282         924 :             len = 1 + operand.length;
    1283         924 :             break;
    1284             :           }
    1285             :           case kExprMemorySize: {
    1286         571 :             if (!CheckHasMemory()) break;
    1287         571 :             MemoryIndexOperand<true> operand(this, pc_);
    1288         571 :             Push(kWasmI32, BUILD(CurrentMemoryPages));
    1289         571 :             len = 1 + operand.length;
    1290         571 :             break;
    1291             :           }
    1292             :           case kExprCallFunction: {
    1293       33774 :             CallFunctionOperand<true> operand(this, pc_);
    1294       33773 :             if (Validate(pc_, operand)) {
    1295       33782 :               TFNode** buffer = PopArgs(operand.sig);
    1296       33784 :               TFNode** rets = nullptr;
    1297       66975 :               BUILD(CallDirect, operand.index, buffer, &rets, position());
    1298       33789 :               PushReturns(operand.sig, rets);
    1299             :             }
    1300       33784 :             len = 1 + operand.length;
    1301             :             break;
    1302             :           }
    1303             :           case kExprCallIndirect: {
    1304        2384 :             CallIndirectOperand<true> operand(this, pc_);
    1305        2384 :             if (Validate(pc_, operand)) {
    1306        2369 :               Value index = Pop(0, kWasmI32);
    1307        2369 :               TFNode** buffer = PopArgs(operand.sig);
    1308        2369 :               if (buffer) buffer[0] = index.node;
    1309        2369 :               TFNode** rets = nullptr;
    1310        4733 :               BUILD(CallIndirect, operand.index, buffer, &rets, position());
    1311        2369 :               PushReturns(operand.sig, rets);
    1312             :             }
    1313        2384 :             len = 1 + operand.length;
    1314             :             break;
    1315             :           }
    1316             :           case kSimdPrefix: {
    1317       19383 :             CHECK_PROTOTYPE_OPCODE(wasm_simd_prototype);
    1318             :             len++;
    1319        6461 :             byte simd_index = read_u8<true>(pc_ + 1, "simd index");
    1320        6461 :             opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
    1321             :             TRACE("  @%-4d #%-20s|", startrel(pc_),
    1322             :                   WasmOpcodes::OpcodeName(opcode));
    1323        6461 :             len += DecodeSimdOpcode(opcode);
    1324        6461 :             break;
    1325             :           }
    1326             :           case kAtomicPrefix: {
    1327           0 :             if (module_ == nullptr || !module_->is_asm_js()) {
    1328           0 :               error("Atomics are allowed only in AsmJs modules");
    1329             :               break;
    1330             :             }
    1331           0 :             if (!FLAG_wasm_atomics_prototype) {
    1332           0 :               error("Invalid opcode (enable with --wasm_atomics_prototype)");
    1333             :               break;
    1334             :             }
    1335             :             len = 2;
    1336           0 :             byte atomic_opcode = read_u8<true>(pc_ + 1, "atomic index");
    1337           0 :             opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_opcode);
    1338           0 :             sig = WasmOpcodes::AtomicSignature(opcode);
    1339           0 :             if (sig) {
    1340           0 :               BuildAtomicOperator(opcode);
    1341             :             }
    1342             :             break;
    1343             :           }
    1344             :           default: {
    1345             :             // Deal with special asmjs opcodes.
    1346      240248 :             if (module_ != nullptr && module_->is_asm_js()) {
    1347      119935 :               sig = WasmOpcodes::AsmjsSignature(opcode);
    1348      119935 :               if (sig) {
    1349      119935 :                 BuildSimpleOperator(opcode, sig);
    1350             :               }
    1351             :             } else {
    1352         189 :               error("Invalid opcode");
    1353             :               return;
    1354             :             }
    1355             :           }
    1356             :         }
    1357             :       }
    1358             : 
    1359             : #if DEBUG
    1360             :       if (FLAG_trace_wasm_decoder) {
    1361             :         PrintF(" ");
    1362             :         for (size_t i = 0; i < control_.size(); ++i) {
    1363             :           Control* c = &control_[i];
    1364             :           enum ControlKind {
    1365             :             kControlIf,
    1366             :             kControlBlock,
    1367             :             kControlLoop,
    1368             :             kControlTry
    1369             :           };
    1370             :           switch (c->kind) {
    1371             :             case kControlIf:
    1372             :               PrintF("I");
    1373             :               break;
    1374             :             case kControlBlock:
    1375             :               PrintF("B");
    1376             :               break;
    1377             :             case kControlLoop:
    1378             :               PrintF("L");
    1379             :               break;
    1380             :             case kControlTry:
    1381             :               PrintF("T");
    1382             :               break;
    1383             :             default:
    1384             :               break;
    1385             :           }
    1386             :           PrintF("%u", c->merge.arity);
    1387             :           if (c->unreachable) PrintF("*");
    1388             :         }
    1389             :         PrintF(" | ");
    1390             :         for (size_t i = 0; i < stack_.size(); ++i) {
    1391             :           Value& val = stack_[i];
    1392             :           WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
    1393             :           if (WasmOpcodes::IsPrefixOpcode(opcode)) {
    1394             :             opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1));
    1395             :           }
    1396             :           PrintF(" %c@%d:%s", WasmOpcodes::ShortNameOf(val.type),
    1397             :                  static_cast<int>(val.pc - start_),
    1398             :                  WasmOpcodes::OpcodeName(opcode));
    1399             :           switch (opcode) {
    1400             :             case kExprI32Const: {
    1401             :               ImmI32Operand<true> operand(this, val.pc);
    1402             :               PrintF("[%d]", operand.value);
    1403             :               break;
    1404             :             }
    1405             :             case kExprGetLocal: {
    1406             :               LocalIndexOperand<true> operand(this, val.pc);
    1407             :               PrintF("[%u]", operand.index);
    1408             :               break;
    1409             :             }
    1410             :             case kExprSetLocal:  // fallthru
    1411             :             case kExprTeeLocal: {
    1412             :               LocalIndexOperand<true> operand(this, val.pc);
    1413             :               PrintF("[%u]", operand.index);
    1414             :               break;
    1415             :             }
    1416             :             default:
    1417             :               break;
    1418             :           }
    1419             :           if (val.node == nullptr) PrintF("?");
    1420             :         }
    1421             :         PrintF("\n");
    1422             :       }
    1423             : #endif
    1424     2493212 :       pc_ += len;
    1425             :     }  // end decode loop
    1426       96949 :     if (pc_ > end_ && ok()) error("Beyond end of code");
    1427             :   }
    1428             : 
    1429      182005 :   void EndControl() {
    1430      182005 :     ssa_env_->Kill(SsaEnv::kControlEnd);
    1431      182005 :     if (!control_.empty()) {
    1432      182044 :       stack_.resize(control_.back().stack_depth);
    1433      182043 :       control_.back().unreachable = true;
    1434             :     }
    1435      182004 :   }
    1436             : 
    1437      228699 :   void SetBlockType(Control* c, BlockTypeOperand<true>& operand) {
    1438      221935 :     c->merge.arity = operand.arity;
    1439      221935 :     if (c->merge.arity == 1) {
    1440       13416 :       c->merge.vals.first = {pc_, nullptr, operand.read_entry(0)};
    1441      215227 :     } else if (c->merge.arity > 1) {
    1442          56 :       c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity);
    1443          84 :       for (unsigned i = 0; i < c->merge.arity; i++) {
    1444         112 :         c->merge.vals.array[i] = {pc_, nullptr, operand.read_entry(i)};
    1445             :       }
    1446             :     }
    1447      221935 :   }
    1448             : 
    1449      170849 :   TFNode** PopArgs(FunctionSig* sig) {
    1450       36152 :     if (build()) {
    1451       35560 :       int count = static_cast<int>(sig->parameter_count());
    1452       35560 :       TFNode** buffer = builder_->Buffer(count + 1);
    1453       35561 :       buffer[0] = nullptr;  // reserved for code object or function index.
    1454      133962 :       for (int i = count - 1; i >= 0; i--) {
    1455      196812 :         buffer[i + 1] = Pop(i, sig->GetParam(i)).node;
    1456             :       }
    1457             :       return buffer;
    1458             :     } else {
    1459         592 :       int count = static_cast<int>(sig->parameter_count());
    1460         731 :       for (int i = count - 1; i >= 0; i--) {
    1461         278 :         Pop(i, sig->GetParam(i));
    1462             :       }
    1463             :       return nullptr;
    1464             :     }
    1465             :   }
    1466             : 
    1467     1064778 :   ValueType GetReturnType(FunctionSig* sig) {
    1468      532389 :     return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn();
    1469             :   }
    1470             : 
    1471      224850 :   void PushBlock(SsaEnv* end_env) {
    1472             :     control_.emplace_back(
    1473      674550 :         Control::Block(pc_, stack_.size(), end_env, current_catch_));
    1474      224806 :   }
    1475             : 
    1476       11623 :   void PushLoop(SsaEnv* end_env) {
    1477             :     control_.emplace_back(
    1478       34869 :         Control::Loop(pc_, stack_.size(), end_env, current_catch_));
    1479       11623 :   }
    1480             : 
    1481       71911 :   void PushIf(SsaEnv* end_env, SsaEnv* false_env) {
    1482             :     control_.emplace_back(
    1483      215733 :         Control::If(pc_, stack_.size(), end_env, false_env, current_catch_));
    1484       71911 :   }
    1485             : 
    1486         124 :   void PushTry(SsaEnv* end_env, SsaEnv* catch_env) {
    1487             :     control_.emplace_back(Control::Try(pc_, stack_.size(), end_env, zone_,
    1488         372 :                                        catch_env, current_catch_));
    1489         124 :     current_catch_ = static_cast<int32_t>(control_.size() - 1);
    1490         124 :   }
    1491             : 
    1492             :   void PopControl() { control_.pop_back(); }
    1493             : 
    1494       48250 :   int DecodeLoadMem(ValueType type, MachineType mem_type) {
    1495       16130 :     if (!CheckHasMemory()) return 0;
    1496             :     MemoryAccessOperand<true> operand(
    1497       16130 :         this, pc_, ElementSizeLog2Of(mem_type.representation()));
    1498             : 
    1499       16130 :     Value index = Pop(0, kWasmI32);
    1500       32120 :     TFNode* node = BUILD(LoadMem, type, mem_type, index.node, operand.offset,
    1501             :                          operand.alignment, position());
    1502             :     Push(type, node);
    1503       16130 :     return 1 + operand.length;
    1504             :   }
    1505             : 
    1506        5779 :   int DecodeStoreMem(ValueType type, MachineType mem_type) {
    1507        1948 :     if (!CheckHasMemory()) return 0;
    1508             :     MemoryAccessOperand<true> operand(
    1509        1948 :         this, pc_, ElementSizeLog2Of(mem_type.representation()));
    1510        1947 :     Value val = Pop(1, type);
    1511        1947 :     Value index = Pop(0, kWasmI32);
    1512        1883 :     BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment,
    1513        3831 :           val.node, position());
    1514        1948 :     return 1 + operand.length;
    1515             :   }
    1516             : 
    1517       10304 :   unsigned SimdExtractLane(WasmOpcode opcode, ValueType type) {
    1518        5152 :     SimdLaneOperand<true> operand(this, pc_);
    1519        5152 :     if (Validate(pc_, opcode, operand)) {
    1520        5152 :       compiler::NodeVector inputs(1, zone_);
    1521        5152 :       inputs[0] = Pop(0, ValueType::kSimd128).node;
    1522        5152 :       TFNode* node = BUILD(SimdLaneOp, opcode, operand.lane, inputs);
    1523             :       Push(type, node);
    1524             :     }
    1525        5152 :     return operand.length;
    1526             :   }
    1527             : 
    1528         476 :   unsigned SimdReplaceLane(WasmOpcode opcode, ValueType type) {
    1529         238 :     SimdLaneOperand<true> operand(this, pc_);
    1530         238 :     if (Validate(pc_, opcode, operand)) {
    1531         238 :       compiler::NodeVector inputs(2, zone_);
    1532         238 :       inputs[1] = Pop(1, type).node;
    1533         238 :       inputs[0] = Pop(0, ValueType::kSimd128).node;
    1534         238 :       TFNode* node = BUILD(SimdLaneOp, opcode, operand.lane, inputs);
    1535             :       Push(ValueType::kSimd128, node);
    1536             :     }
    1537         238 :     return operand.length;
    1538             :   }
    1539             : 
    1540          84 :   unsigned SimdShiftOp(WasmOpcode opcode) {
    1541          42 :     SimdShiftOperand<true> operand(this, pc_);
    1542          42 :     if (Validate(pc_, opcode, operand)) {
    1543          42 :       compiler::NodeVector inputs(1, zone_);
    1544          42 :       inputs[0] = Pop(0, ValueType::kSimd128).node;
    1545          42 :       TFNode* node = BUILD(SimdShiftOp, opcode, operand.shift, inputs);
    1546             :       Push(ValueType::kSimd128, node);
    1547             :     }
    1548          42 :     return operand.length;
    1549             :   }
    1550             : 
    1551           0 :   unsigned SimdConcatOp(WasmOpcode opcode) {
    1552             :     DCHECK_EQ(wasm::kExprS8x16Concat, opcode);
    1553           0 :     SimdConcatOperand<true> operand(this, pc_);
    1554           0 :     if (Validate(pc_, opcode, operand)) {
    1555           0 :       compiler::NodeVector inputs(2, zone_);
    1556           0 :       inputs[1] = Pop(1, ValueType::kSimd128).node;
    1557           0 :       inputs[0] = Pop(0, ValueType::kSimd128).node;
    1558           0 :       TFNode* node = BUILD(SimdConcatOp, operand.bytes, inputs);
    1559             :       Push(ValueType::kSimd128, node);
    1560             :     }
    1561           0 :     return operand.length;
    1562             :   }
    1563             : 
    1564        7490 :   unsigned DecodeSimdOpcode(WasmOpcode opcode) {
    1565             :     unsigned len = 0;
    1566        6461 :     switch (opcode) {
    1567             :       case kExprF32x4ExtractLane: {
    1568           0 :         len = SimdExtractLane(opcode, ValueType::kFloat32);
    1569           0 :         break;
    1570             :       }
    1571             :       case kExprI32x4ExtractLane:
    1572             :       case kExprI16x8ExtractLane:
    1573             :       case kExprI8x16ExtractLane: {
    1574        5152 :         len = SimdExtractLane(opcode, ValueType::kWord32);
    1575        5152 :         break;
    1576             :       }
    1577             :       case kExprF32x4ReplaceLane: {
    1578           0 :         len = SimdReplaceLane(opcode, ValueType::kFloat32);
    1579           0 :         break;
    1580             :       }
    1581             :       case kExprI32x4ReplaceLane:
    1582             :       case kExprI16x8ReplaceLane:
    1583             :       case kExprI8x16ReplaceLane: {
    1584         238 :         len = SimdReplaceLane(opcode, ValueType::kWord32);
    1585         238 :         break;
    1586             :       }
    1587             :       case kExprI32x4Shl:
    1588             :       case kExprI32x4ShrS:
    1589             :       case kExprI32x4ShrU:
    1590             :       case kExprI16x8Shl:
    1591             :       case kExprI16x8ShrS:
    1592             :       case kExprI16x8ShrU:
    1593             :       case kExprI8x16Shl:
    1594             :       case kExprI8x16ShrS:
    1595             :       case kExprI8x16ShrU: {
    1596          42 :         len = SimdShiftOp(opcode);
    1597          42 :         break;
    1598             :       }
    1599             :       case kExprS8x16Concat: {
    1600           0 :         len = SimdConcatOp(opcode);
    1601           0 :         break;
    1602             :       }
    1603             :       default: {
    1604        4501 :         FunctionSig* sig = WasmOpcodes::Signature(opcode);
    1605        1029 :         if (sig != nullptr) {
    1606        1029 :           compiler::NodeVector inputs(sig->parameter_count(), zone_);
    1607        3472 :           for (size_t i = sig->parameter_count(); i > 0; i--) {
    1608        2828 :             Value val = Pop(static_cast<int>(i - 1), sig->GetParam(i - 1));
    1609        2828 :             inputs[i - 1] = val.node;
    1610             :           }
    1611        1029 :           TFNode* node = BUILD(SimdOp, opcode, inputs);
    1612             :           Push(GetReturnType(sig), node);
    1613             :         } else {
    1614           0 :           error("invalid simd opcode");
    1615             :         }
    1616             :       }
    1617             :     }
    1618        6461 :     return len;
    1619             :   }
    1620             : 
    1621           0 :   void BuildAtomicOperator(WasmOpcode opcode) { UNIMPLEMENTED(); }
    1622             : 
    1623      417506 :   void DoReturn() {
    1624      265281 :     int count = static_cast<int>(sig_->return_count());
    1625             :     TFNode** buffer = nullptr;
    1626      139133 :     if (build()) buffer = builder_->Buffer(count);
    1627             : 
    1628             :     // Pop return values off the stack in reverse order.
    1629      265388 :     for (int i = count - 1; i >= 0; i--) {
    1630      252296 :       Value val = Pop(i, sig_->GetReturn(i));
    1631      126179 :       if (buffer) buffer[i] = val.node;
    1632             :     }
    1633             : 
    1634      139240 :     BUILD(Return, count, buffer);
    1635      139240 :     EndControl();
    1636      139283 :   }
    1637             : 
    1638             :   void Push(ValueType type, TFNode* node) {
    1639     1070714 :     if (type != kWasmStmt) {
    1640     3121675 :       stack_.push_back({pc_, node, type});
    1641             :     }
    1642             :   }
    1643             : 
    1644      287113 :   void PushEndValues(Control* c) {
    1645             :     DCHECK_EQ(c, &control_.back());
    1646      287113 :     stack_.resize(c->stack_depth);
    1647      287162 :     if (c->merge.arity == 1) {
    1648       68971 :       stack_.push_back(c->merge.vals.first);
    1649             :     } else {
    1650        2899 :       for (unsigned i = 0; i < c->merge.arity; i++) {
    1651        2899 :         stack_.push_back(c->merge.vals.array[i]);
    1652             :       }
    1653             :     }
    1654             :     DCHECK_EQ(c->stack_depth + c->merge.arity, stack_.size());
    1655      287157 :   }
    1656             : 
    1657      117587 :   void PushReturns(FunctionSig* sig, TFNode** rets) {
    1658      117594 :     for (size_t i = 0; i < sig->return_count(); i++) {
    1659             :       // When verifying only, then {rets} will be null, so push null.
    1660       22644 :       Push(sig->GetReturn(i), rets ? rets[i] : nullptr);
    1661             :     }
    1662       36153 :   }
    1663             : 
    1664             :   const char* SafeOpcodeNameAt(const byte* pc) {
    1665       25745 :     if (pc >= end_) return "<end>";
    1666       21305 :     return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(*pc));
    1667             :   }
    1668             : 
    1669     1491398 :   Value Pop(int index, ValueType expected) {
    1670     1465964 :     Value val = Pop();
    1671     1466034 :     if (val.type != expected && val.type != kWasmVar && expected != kWasmVar) {
    1672             :       errorf(val.pc, "%s[%d] expected type %s, found %s of type %s",
    1673             :              SafeOpcodeNameAt(pc_), index, WasmOpcodes::TypeName(expected),
    1674       38151 :              SafeOpcodeNameAt(val.pc), WasmOpcodes::TypeName(val.type));
    1675             :     }
    1676     1466034 :     return val;
    1677             :   }
    1678             : 
    1679     1537579 :   Value Pop() {
    1680     1537268 :     size_t limit = control_.empty() ? 0 : control_.back().stack_depth;
    1681     3074536 :     if (stack_.size() <= limit) {
    1682             :       // Popping past the current control start in reachable code.
    1683         821 :       Value val = {pc_, nullptr, kWasmVar};
    1684         821 :       if (!control_.back().unreachable) {
    1685         311 :         errorf(pc_, "%s found empty stack", SafeOpcodeNameAt(pc_));
    1686             :       }
    1687         821 :       return val;
    1688             :     }
    1689     1536447 :     Value val = stack_.back();
    1690             :     stack_.pop_back();
    1691     1536447 :     return val;
    1692             :   }
    1693             : 
    1694             :   int baserel(const byte* ptr) {
    1695             :     return base_ ? static_cast<int>(ptr - base_) : 0;
    1696             :   }
    1697             : 
    1698         234 :   int startrel(const byte* ptr) { return static_cast<int>(ptr - start_); }
    1699             : 
    1700       98906 :   void BreakTo(unsigned depth) {
    1701      296520 :     Control* c = &control_[control_.size() - depth - 1];
    1702       98840 :     if (c->is_loop()) {
    1703             :       // This is the inner loop block, which does not have a value.
    1704        9797 :       Goto(ssa_env_, c->end_env);
    1705             :     } else {
    1706             :       // Merge the value(s) into the end of the block.
    1707       89043 :       size_t expected = control_.back().stack_depth + c->merge.arity;
    1708      178086 :       if (stack_.size() < expected && !control_.back().unreachable) {
    1709             :         errorf(
    1710             :             pc_,
    1711             :             "expected at least %u values on the stack for br to @%d, found %d",
    1712             :             c->merge.arity, startrel(c->pc),
    1713         132 :             static_cast<int>(stack_.size() - c->stack_depth));
    1714       98906 :         return;
    1715             :       }
    1716       88977 :       MergeValuesInto(c);
    1717             :     }
    1718             :   }
    1719             : 
    1720      316498 :   void FallThruTo(Control* c) {
    1721             :     DCHECK_EQ(c, &control_.back());
    1722             :     // Merge the value(s) into the end of the block.
    1723      316333 :     size_t expected = c->stack_depth + c->merge.arity;
    1724      948999 :     if (stack_.size() == expected ||
    1725        6635 :         (stack_.size() < expected && c->unreachable)) {
    1726      316168 :       MergeValuesInto(c);
    1727      316195 :       c->unreachable = false;
    1728      632555 :       return;
    1729             :     }
    1730             :     errorf(pc_, "expected %u elements on the stack for fallthru to @%d",
    1731         330 :            c->merge.arity, startrel(c->pc));
    1732             :   }
    1733             : 
    1734             :   inline Value& GetMergeValueFromStack(Control* c, size_t i) {
    1735      157042 :     return stack_[stack_.size() - c->merge.arity + i];
    1736             :   }
    1737             : 
    1738       25854 :   void TypeCheckFallThru(Control* c) {
    1739             :     DCHECK_EQ(c, &control_.back());
    1740             :     // Fallthru must match arity exactly.
    1741       25851 :     int arity = static_cast<int>(c->merge.arity);
    1742       77553 :     if (c->stack_depth + arity < stack_.size() ||
    1743           3 :         (c->stack_depth + arity != stack_.size() && !c->unreachable)) {
    1744             :       errorf(pc_, "expected %d elements on the stack for fallthru to @%d",
    1745           6 :              arity, startrel(c->pc));
    1746           3 :       return;
    1747             :     }
    1748             :     // Typecheck the values left on the stack.
    1749       25848 :     size_t avail = stack_.size() - c->stack_depth;
    1750       39662 :     for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail;
    1751             :          i < c->merge.arity; i++) {
    1752             :       Value& val = GetMergeValueFromStack(c, i);
    1753             :       Value& old = c->merge[i];
    1754       13814 :       if (val.type != old.type) {
    1755             :         errorf(pc_, "type error in merge[%zu] (expected %s, got %s)", i,
    1756             :                WasmOpcodes::TypeName(old.type),
    1757           0 :                WasmOpcodes::TypeName(val.type));
    1758           0 :         return;
    1759             :       }
    1760             :     }
    1761             :   }
    1762             : 
    1763      405145 :   void MergeValuesInto(Control* c) {
    1764      405145 :     SsaEnv* target = c->end_env;
    1765      405145 :     bool first = target->state == SsaEnv::kUnreachable;
    1766      405145 :     bool reachable = ssa_env_->go();
    1767      405145 :     Goto(ssa_env_, target);
    1768             : 
    1769      810444 :     size_t avail = stack_.size() - control_.back().stack_depth;
    1770      951704 :     for (size_t i = avail >= c->merge.arity ? 0 : c->merge.arity - avail;
    1771      475852 :          i < c->merge.arity; i++) {
    1772             :       Value& val = GetMergeValueFromStack(c, i);
    1773             :       Value& old = c->merge[i];
    1774       71614 :       if (val.type != old.type && val.type != kWasmVar) {
    1775             :         errorf(pc_, "type error in merge[%zu] (expected %s, got %s)", i,
    1776             :                WasmOpcodes::TypeName(old.type),
    1777        1015 :                WasmOpcodes::TypeName(val.type));
    1778      406198 :         return;
    1779             :       }
    1780       70599 :       if (builder_ && reachable) {
    1781             :         DCHECK_NOT_NULL(val.node);
    1782             :         old.node =
    1783             :             first ? val.node : CreateOrMergeIntoPhi(old.type, target->control,
    1784       59637 :                                                     old.node, val.node);
    1785             :       }
    1786             :     }
    1787             :   }
    1788             : 
    1789             :   void SetEnv(const char* reason, SsaEnv* env) {
    1790             : #if DEBUG
    1791             :     if (FLAG_trace_wasm_decoder) {
    1792             :       char state = 'X';
    1793             :       if (env) {
    1794             :         switch (env->state) {
    1795             :           case SsaEnv::kReached:
    1796             :             state = 'R';
    1797             :             break;
    1798             :           case SsaEnv::kUnreachable:
    1799             :             state = 'U';
    1800             :             break;
    1801             :           case SsaEnv::kMerged:
    1802             :             state = 'M';
    1803             :             break;
    1804             :           case SsaEnv::kControlEnd:
    1805             :             state = 'E';
    1806             :             break;
    1807             :         }
    1808             :       }
    1809             :       PrintF("{set_env = %p, state = %c, reason = %s", static_cast<void*>(env),
    1810             :              state, reason);
    1811             :       if (env && env->control) {
    1812             :         PrintF(", control = ");
    1813             :         compiler::WasmGraphBuilder::PrintDebugName(env->control);
    1814             :       }
    1815             :       PrintF("}\n");
    1816             :     }
    1817             : #endif
    1818      711635 :     ssa_env_ = env;
    1819      721878 :     if (builder_) {
    1820      676094 :       builder_->set_control_ptr(&env->control);
    1821      676094 :       builder_->set_effect_ptr(&env->effect);
    1822             :     }
    1823             :   }
    1824             : 
    1825     1340071 :   TFNode* CheckForException(TFNode* node) {
    1826     1340071 :     if (node == nullptr) {
    1827             :       return nullptr;
    1828             :     }
    1829             : 
    1830     1339654 :     const bool inside_try_scope = current_catch_ != kNullCatch;
    1831             : 
    1832     1339654 :     if (!inside_try_scope) {
    1833             :       return node;
    1834             :     }
    1835             : 
    1836         644 :     TFNode* if_success = nullptr;
    1837         644 :     TFNode* if_exception = nullptr;
    1838         644 :     if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
    1839             :       return node;
    1840             :     }
    1841             : 
    1842         150 :     SsaEnv* success_env = Steal(ssa_env_);
    1843         150 :     success_env->control = if_success;
    1844             : 
    1845         150 :     SsaEnv* exception_env = Split(success_env);
    1846         150 :     exception_env->control = if_exception;
    1847             :     TryInfo* try_info = current_try_info();
    1848         150 :     Goto(exception_env, try_info->catch_env);
    1849         150 :     TFNode* exception = try_info->exception;
    1850         150 :     if (exception == nullptr) {
    1851             :       DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
    1852         120 :       try_info->exception = if_exception;
    1853             :     } else {
    1854             :       DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
    1855             :       try_info->exception =
    1856             :           CreateOrMergeIntoPhi(kWasmI32, try_info->catch_env->control,
    1857          30 :                                try_info->exception, if_exception);
    1858             :     }
    1859             : 
    1860             :     SetEnv("if_success", success_env);
    1861         150 :     return node;
    1862             :   }
    1863             : 
    1864      456077 :   void Goto(SsaEnv* from, SsaEnv* to) {
    1865             :     DCHECK_NOT_NULL(to);
    1866      456077 :     if (!from->go()) return;
    1867      307801 :     switch (to->state) {
    1868             :       case SsaEnv::kUnreachable: {  // Overwrite destination.
    1869      233144 :         to->state = SsaEnv::kReached;
    1870      233144 :         to->locals = from->locals;
    1871      233144 :         to->control = from->control;
    1872      233144 :         to->effect = from->effect;
    1873      233144 :         break;
    1874             :       }
    1875             :       case SsaEnv::kReached: {  // Create a new merge.
    1876       50611 :         to->state = SsaEnv::kMerged;
    1877       50611 :         if (!builder_) break;
    1878             :         // Merge control.
    1879       50271 :         TFNode* controls[] = {to->control, from->control};
    1880       50271 :         TFNode* merge = builder_->Merge(2, controls);
    1881       50271 :         to->control = merge;
    1882             :         // Merge effects.
    1883       50271 :         if (from->effect != to->effect) {
    1884       24717 :           TFNode* effects[] = {to->effect, from->effect, merge};
    1885       24717 :           to->effect = builder_->EffectPhi(2, effects, merge);
    1886             :         }
    1887             :         // Merge SSA values.
    1888      926422 :         for (int i = EnvironmentCount() - 1; i >= 0; i--) {
    1889      876151 :           TFNode* a = to->locals[i];
    1890      876151 :           TFNode* b = from->locals[i];
    1891      876151 :           if (a != b) {
    1892       72937 :             TFNode* vals[] = {a, b};
    1893      153674 :             to->locals[i] = builder_->Phi(local_type_vec_[i], 2, vals, merge);
    1894             :           }
    1895             :         }
    1896             :         break;
    1897             :       }
    1898             :       case SsaEnv::kMerged: {
    1899       24046 :         if (!builder_) break;
    1900       24041 :         TFNode* merge = to->control;
    1901             :         // Extend the existing merge.
    1902       24041 :         builder_->AppendToMerge(merge, from->control);
    1903             :         // Merge effects.
    1904       24041 :         if (builder_->IsPhiWithMerge(to->effect, merge)) {
    1905       14769 :           builder_->AppendToPhi(to->effect, from->effect);
    1906        9272 :         } else if (to->effect != from->effect) {
    1907         294 :           uint32_t count = builder_->InputCount(merge);
    1908         294 :           TFNode** effects = builder_->Buffer(count);
    1909        1119 :           for (uint32_t j = 0; j < count - 1; j++) {
    1910         825 :             effects[j] = to->effect;
    1911             :           }
    1912         294 :           effects[count - 1] = from->effect;
    1913         294 :           to->effect = builder_->EffectPhi(count, effects, merge);
    1914             :         }
    1915             :         // Merge locals.
    1916      463908 :         for (int i = EnvironmentCount() - 1; i >= 0; i--) {
    1917      439867 :           TFNode* tnode = to->locals[i];
    1918      439867 :           TFNode* fnode = from->locals[i];
    1919      439867 :           if (builder_->IsPhiWithMerge(tnode, merge)) {
    1920       93522 :             builder_->AppendToPhi(tnode, fnode);
    1921      346345 :           } else if (tnode != fnode) {
    1922        7800 :             uint32_t count = builder_->InputCount(merge);
    1923        7800 :             TFNode** vals = builder_->Buffer(count);
    1924       32920 :             for (uint32_t j = 0; j < count - 1; j++) {
    1925       25120 :               vals[j] = tnode;
    1926             :             }
    1927        7800 :             vals[count - 1] = fnode;
    1928        7800 :             to->locals[i] =
    1929        7800 :                 builder_->Phi(local_type_vec_[i], count, vals, merge);
    1930             :           }
    1931             :         }
    1932             :         break;
    1933             :       }
    1934             :       default:
    1935           0 :         UNREACHABLE();
    1936             :     }
    1937             :     return from->Kill();
    1938             :   }
    1939             : 
    1940        6221 :   TFNode* CreateOrMergeIntoPhi(ValueType type, TFNode* merge, TFNode* tnode,
    1941             :                                TFNode* fnode) {
    1942             :     DCHECK_NOT_NULL(builder_);
    1943        6221 :     if (builder_->IsPhiWithMerge(tnode, merge)) {
    1944          70 :       builder_->AppendToPhi(tnode, fnode);
    1945        6151 :     } else if (tnode != fnode) {
    1946        6105 :       uint32_t count = builder_->InputCount(merge);
    1947        6105 :       TFNode** vals = builder_->Buffer(count);
    1948        6105 :       for (uint32_t j = 0; j < count - 1; j++) vals[j] = tnode;
    1949        6105 :       vals[count - 1] = fnode;
    1950        6105 :       return builder_->Phi(type, count, vals, merge);
    1951             :     }
    1952         116 :     return tnode;
    1953             :   }
    1954             : 
    1955       29157 :   SsaEnv* PrepareForLoop(const byte* pc, SsaEnv* env) {
    1956       11623 :     if (!builder_) return Split(env);
    1957        8767 :     if (!env->go()) return Split(env);
    1958        8767 :     env->state = SsaEnv::kMerged;
    1959             : 
    1960        8767 :     env->control = builder_->Loop(env->control);
    1961        8767 :     env->effect = builder_->EffectPhi(1, &env->effect, env->control);
    1962        8767 :     builder_->Terminate(env->effect, env->control);
    1963      205986 :     BitVector* assigned = AnalyzeLoopAssignment(
    1964       17534 :         this, pc, static_cast<int>(total_locals()), zone_);
    1965        8767 :     if (failed()) return env;
    1966        8767 :     if (assigned != nullptr) {
    1967             :       // Only introduce phis for variables assigned in this loop.
    1968      214753 :       for (int i = EnvironmentCount() - 1; i >= 0; i--) {
    1969      205986 :         if (!assigned->Contains(i)) continue;
    1970             :         env->locals[i] =
    1971       86668 :             builder_->Phi(local_type_vec_[i], 1, &env->locals[i], env->control);
    1972             :       }
    1973        8767 :       SsaEnv* loop_body_env = Split(env);
    1974             :       builder_->StackCheck(position(), &(loop_body_env->effect),
    1975       17534 :                            &(loop_body_env->control));
    1976        8767 :       return loop_body_env;
    1977             :     }
    1978             : 
    1979             :     // Conservatively introduce phis for all local variables.
    1980           0 :     for (int i = EnvironmentCount() - 1; i >= 0; i--) {
    1981             :       env->locals[i] =
    1982           0 :           builder_->Phi(local_type_vec_[i], 1, &env->locals[i], env->control);
    1983             :     }
    1984             : 
    1985           0 :     SsaEnv* loop_body_env = Split(env);
    1986             :     builder_->StackCheck(position(), &(loop_body_env->effect),
    1987           0 :                          &(loop_body_env->control));
    1988           0 :     return loop_body_env;
    1989             :   }
    1990             : 
    1991             :   // Create a complete copy of the {from}.
    1992      298262 :   SsaEnv* Split(SsaEnv* from) {
    1993             :     DCHECK_NOT_NULL(from);
    1994      149131 :     SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
    1995      149131 :     size_t size = sizeof(TFNode*) * EnvironmentCount();
    1996      149131 :     result->control = from->control;
    1997      149131 :     result->effect = from->effect;
    1998             : 
    1999      149131 :     if (from->go()) {
    2000      148942 :       result->state = SsaEnv::kReached;
    2001             :       result->locals =
    2002      148942 :           size > 0 ? reinterpret_cast<TFNode**>(zone_->New(size)) : nullptr;
    2003      148942 :       memcpy(result->locals, from->locals, size);
    2004             :     } else {
    2005         189 :       result->state = SsaEnv::kUnreachable;
    2006         189 :       result->locals = nullptr;
    2007             :     }
    2008             : 
    2009      149131 :     return result;
    2010             :   }
    2011             : 
    2012             :   // Create a copy of {from} that steals its state and leaves {from}
    2013             :   // unreachable.
    2014      316556 :   SsaEnv* Steal(SsaEnv* from) {
    2015             :     DCHECK_NOT_NULL(from);
    2016      316556 :     if (!from->go()) return UnreachableEnv();
    2017      316208 :     SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
    2018      316197 :     result->state = SsaEnv::kReached;
    2019      316197 :     result->locals = from->locals;
    2020      316197 :     result->control = from->control;
    2021      316197 :     result->effect = from->effect;
    2022             :     from->Kill(SsaEnv::kUnreachable);
    2023      316197 :     return result;
    2024             :   }
    2025             : 
    2026             :   // Create an unreachable environment.
    2027             :   SsaEnv* UnreachableEnv() {
    2028         298 :     SsaEnv* result = reinterpret_cast<SsaEnv*>(zone_->New(sizeof(SsaEnv)));
    2029         298 :     result->state = SsaEnv::kUnreachable;
    2030         298 :     result->control = nullptr;
    2031         298 :     result->effect = nullptr;
    2032         298 :     result->locals = nullptr;
    2033             :     return result;
    2034             :   }
    2035             : 
    2036             :   int EnvironmentCount() {
    2037      619441 :     if (builder_) return static_cast<int>(local_type_vec_.size());
    2038             :     return 0;  // if we aren't building a graph, don't bother with SSA renaming.
    2039             :   }
    2040             : 
    2041       10782 :   virtual void onFirstError() {
    2042       10782 :     end_ = pc_;          // Terminate decoding loop.
    2043       10782 :     builder_ = nullptr;  // Don't build any more nodes.
    2044             :     TRACE(" !%s\n", error_msg_.c_str());
    2045       10782 :   }
    2046             : 
    2047             :   inline wasm::WasmCodePosition position() {
    2048      584416 :     int offset = static_cast<int>(pc_ - start_);
    2049             :     DCHECK_EQ(pc_ - start_, offset);  // overflows cannot happen
    2050             :     return offset;
    2051             :   }
    2052             : 
    2053     2545453 :   inline void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
    2054             :     TFNode* node;
    2055      531307 :     switch (sig->parameter_count()) {
    2056             :       case 1: {
    2057      101554 :         Value val = Pop(0, sig->GetParam(0));
    2058      201884 :         node = BUILD(Unop, opcode, val.node, position());
    2059             :         break;
    2060             :       }
    2061             :       case 2: {
    2062      429753 :         Value rval = Pop(1, sig->GetParam(1));
    2063      429811 :         Value lval = Pop(0, sig->GetParam(0));
    2064      851144 :         node = BUILD(Binop, opcode, lval.node, rval.node, position());
    2065             :         break;
    2066             :       }
    2067             :       default:
    2068           0 :         UNREACHABLE();
    2069             :         node = nullptr;
    2070             :         break;
    2071             :     }
    2072             :     Push(GetReturnType(sig), node);
    2073      531362 :   }
    2074             : };
    2075             : 
    2076       21585 : bool DecodeLocalDecls(BodyLocalDecls* decls, const byte* start,
    2077             :                       const byte* end) {
    2078             :   Decoder decoder(start, end);
    2079       21585 :   if (WasmDecoder::DecodeLocals(&decoder, nullptr, &decls->type_list)) {
    2080             :     DCHECK(decoder.ok());
    2081       43110 :     decls->encoded_size = decoder.pc_offset();
    2082       21555 :     return true;
    2083             :   }
    2084             :   return false;
    2085             : }
    2086             : 
    2087       21496 : BytecodeIterator::BytecodeIterator(const byte* start, const byte* end,
    2088             :                                    BodyLocalDecls* decls)
    2089       21496 :     : Decoder(start, end) {
    2090       21496 :   if (decls != nullptr) {
    2091       21493 :     if (DecodeLocalDecls(decls, start, end)) {
    2092       21464 :       pc_ += decls->encoded_size;
    2093       21464 :       if (pc_ > end_) pc_ = end_;
    2094             :     }
    2095             :   }
    2096       21496 : }
    2097             : 
    2098       14839 : DecodeResult VerifyWasmCode(AccountingAllocator* allocator,
    2099             :                             const wasm::WasmModule* module,
    2100             :                             FunctionBody& body) {
    2101       14839 :   Zone zone(allocator, ZONE_NAME);
    2102       14839 :   WasmFullDecoder decoder(&zone, module, body);
    2103       14839 :   decoder.Decode();
    2104       29678 :   return decoder.toResult<DecodeStruct*>(nullptr);
    2105             : }
    2106             : 
    2107       71769 : DecodeResult BuildTFGraph(AccountingAllocator* allocator, TFBuilder* builder,
    2108             :                           FunctionBody& body) {
    2109       71769 :   Zone zone(allocator, ZONE_NAME);
    2110       71754 :   WasmFullDecoder decoder(&zone, builder, body);
    2111       71716 :   decoder.Decode();
    2112      143358 :   return decoder.toResult<DecodeStruct*>(nullptr);
    2113             : }
    2114             : 
    2115      237666 : unsigned OpcodeLength(const byte* pc, const byte* end) {
    2116             :   Decoder decoder(pc, end);
    2117      475332 :   return WasmDecoder::OpcodeLength(&decoder, pc);
    2118             : }
    2119             : 
    2120      236601 : std::pair<uint32_t, uint32_t> StackEffect(const WasmModule* module,
    2121             :                                           FunctionSig* sig, const byte* pc,
    2122             :                                           const byte* end) {
    2123             :   WasmDecoder decoder(module, sig, pc, end);
    2124      473202 :   return decoder.StackEffect(pc);
    2125             : }
    2126             : 
    2127           0 : void PrintRawWasmCode(const byte* start, const byte* end) {
    2128           0 :   AccountingAllocator allocator;
    2129           0 :   PrintRawWasmCode(&allocator, FunctionBodyForTesting(start, end), nullptr);
    2130           0 : }
    2131             : 
    2132             : namespace {
    2133           0 : const char* RawOpcodeName(WasmOpcode opcode) {
    2134           0 :   switch (opcode) {
    2135             : #define DECLARE_NAME_CASE(name, opcode, sig) \
    2136             :   case kExpr##name:                          \
    2137             :     return "kExpr" #name;
    2138           0 :     FOREACH_OPCODE(DECLARE_NAME_CASE)
    2139             : #undef DECLARE_NAME_CASE
    2140             :     default:
    2141             :       break;
    2142             :   }
    2143           0 :   return "Unknown";
    2144             : }
    2145             : }  // namespace
    2146             : 
    2147           0 : bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
    2148             :                       const wasm::WasmModule* module) {
    2149           0 :   OFStream os(stdout);
    2150           0 :   Zone zone(allocator, ZONE_NAME);
    2151           0 :   WasmFullDecoder decoder(&zone, module, body);
    2152             :   int line_nr = 0;
    2153             : 
    2154             :   // Print the function signature.
    2155           0 :   if (body.sig) {
    2156           0 :     os << "// signature: " << *body.sig << std::endl;
    2157             :     ++line_nr;
    2158             :   }
    2159             : 
    2160             :   // Print the local declarations.
    2161             :   BodyLocalDecls decls(&zone);
    2162           0 :   BytecodeIterator i(body.start, body.end, &decls);
    2163           0 :   if (body.start != i.pc() && !FLAG_wasm_code_fuzzer_gen_test) {
    2164           0 :     os << "// locals: ";
    2165           0 :     if (!decls.type_list.empty()) {
    2166           0 :       ValueType type = decls.type_list[0];
    2167             :       uint32_t count = 0;
    2168           0 :       for (size_t pos = 0; pos < decls.type_list.size(); ++pos) {
    2169           0 :         if (decls.type_list[pos] == type) {
    2170           0 :           ++count;
    2171             :         } else {
    2172           0 :           os << " " << count << " " << WasmOpcodes::TypeName(type);
    2173           0 :           type = decls.type_list[pos];
    2174             :           count = 1;
    2175             :         }
    2176             :       }
    2177             :     }
    2178             :     os << std::endl;
    2179             :     ++line_nr;
    2180             : 
    2181           0 :     for (const byte* locals = body.start; locals < i.pc(); locals++) {
    2182           0 :       os << (locals == body.start ? "0x" : " 0x") << AsHex(*locals, 2) << ",";
    2183             :     }
    2184             :     os << std::endl;
    2185             :     ++line_nr;
    2186             :   }
    2187             : 
    2188           0 :   os << "// body: " << std::endl;
    2189             :   ++line_nr;
    2190             :   unsigned control_depth = 0;
    2191           0 :   for (; i.has_next(); i.next()) {
    2192           0 :     unsigned length = WasmDecoder::OpcodeLength(&decoder, i.pc());
    2193             : 
    2194           0 :     WasmOpcode opcode = i.current();
    2195           0 :     if (opcode == kExprElse) control_depth--;
    2196             : 
    2197           0 :     int num_whitespaces = control_depth < 32 ? 2 * control_depth : 64;
    2198             : 
    2199             :     // 64 whitespaces
    2200             :     const char* padding =
    2201             :         "                                                                ";
    2202           0 :     os.write(padding, num_whitespaces);
    2203             : 
    2204           0 :     os << RawOpcodeName(opcode) << ",";
    2205             : 
    2206           0 :     for (size_t j = 1; j < length; ++j) {
    2207           0 :       os << " 0x" << AsHex(i.pc()[j], 2) << ",";
    2208             :     }
    2209             : 
    2210           0 :     switch (opcode) {
    2211             :       case kExprElse:
    2212           0 :         os << "   // @" << i.pc_offset();
    2213           0 :         control_depth++;
    2214           0 :         break;
    2215             :       case kExprLoop:
    2216             :       case kExprIf:
    2217             :       case kExprBlock:
    2218             :       case kExprTry: {
    2219           0 :         BlockTypeOperand<true> operand(&i, i.pc());
    2220           0 :         os << "   // @" << i.pc_offset();
    2221           0 :         for (unsigned i = 0; i < operand.arity; i++) {
    2222           0 :           os << " " << WasmOpcodes::TypeName(operand.read_entry(i));
    2223             :         }
    2224           0 :         control_depth++;
    2225             :         break;
    2226             :       }
    2227             :       case kExprEnd:
    2228           0 :         os << "   // @" << i.pc_offset();
    2229           0 :         control_depth--;
    2230           0 :         break;
    2231             :       case kExprBr: {
    2232           0 :         BreakDepthOperand<true> operand(&i, i.pc());
    2233           0 :         os << "   // depth=" << operand.depth;
    2234             :         break;
    2235             :       }
    2236             :       case kExprBrIf: {
    2237           0 :         BreakDepthOperand<true> operand(&i, i.pc());
    2238           0 :         os << "   // depth=" << operand.depth;
    2239             :         break;
    2240             :       }
    2241             :       case kExprBrTable: {
    2242           0 :         BranchTableOperand<true> operand(&i, i.pc());
    2243           0 :         os << " // entries=" << operand.table_count;
    2244             :         break;
    2245             :       }
    2246             :       case kExprCallIndirect: {
    2247           0 :         CallIndirectOperand<true> operand(&i, i.pc());
    2248           0 :         os << "   // sig #" << operand.index;
    2249           0 :         if (decoder.Complete(i.pc(), operand)) {
    2250           0 :           os << ": " << *operand.sig;
    2251             :         }
    2252             :         break;
    2253             :       }
    2254             :       case kExprCallFunction: {
    2255           0 :         CallFunctionOperand<true> operand(&i, i.pc());
    2256           0 :         os << " // function #" << operand.index;
    2257           0 :         if (decoder.Complete(i.pc(), operand)) {
    2258           0 :           os << ": " << *operand.sig;
    2259             :         }
    2260             :         break;
    2261             :       }
    2262             :       default:
    2263             :         break;
    2264             :     }
    2265             :     os << std::endl;
    2266             :     ++line_nr;
    2267             :   }
    2268             : 
    2269           0 :   return decoder.ok();
    2270             : }
    2271             : 
    2272          78 : BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
    2273             :                                            const byte* start, const byte* end) {
    2274             :   Decoder decoder(start, end);
    2275             :   return WasmDecoder::AnalyzeLoopAssignment(&decoder, start,
    2276         156 :                                             static_cast<int>(num_locals), zone);
    2277             : }
    2278             : 
    2279             : }  // namespace wasm
    2280             : }  // namespace internal
    2281             : }  // namespace v8

Generated by: LCOV version 1.10