• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
6 #define V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
7 
8 // Do only include this header for implementing new Interface of the
9 // WasmFullDecoder.
10 
11 #include "src/base/platform/elapsed-timer.h"
12 #include "src/bit-vector.h"
13 #include "src/wasm/decoder.h"
14 #include "src/wasm/function-body-decoder.h"
15 #include "src/wasm/wasm-features.h"
16 #include "src/wasm/wasm-limits.h"
17 #include "src/wasm/wasm-module.h"
18 #include "src/wasm/wasm-opcodes.h"
19 
20 namespace v8 {
21 namespace internal {
22 namespace wasm {
23 
24 struct WasmGlobal;
25 struct WasmException;
26 
27 #define TRACE(...)                                    \
28   do {                                                \
29     if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
30   } while (false)
31 
32 #define TRACE_INST_FORMAT "  @%-8d #%-20s|"
33 
34 // Return the evaluation of `condition` if validate==true, DCHECK that it's
35 // true and always return true otherwise.
36 #define VALIDATE(condition)       \
37   (validate ? (condition) : [&] { \
38     DCHECK(condition);            \
39     return true;                  \
40   }())
41 
42 #define RET_ON_PROTOTYPE_OPCODE(feat)                                          \
43   DCHECK(!this->module_ || this->module_->origin == kWasmOrigin);              \
44   if (!this->enabled_.feat) {                                                  \
45     this->error("Invalid opcode (enable with --experimental-wasm-" #feat ")"); \
46   } else {                                                                     \
47     this->detected_->feat = true;                                              \
48   }
49 
50 #define CHECK_PROTOTYPE_OPCODE(feat)                                           \
51   DCHECK(!this->module_ || this->module_->origin == kWasmOrigin);              \
52   if (!this->enabled_.feat) {                                                  \
53     this->error("Invalid opcode (enable with --experimental-wasm-" #feat ")"); \
54     break;                                                                     \
55   } else {                                                                     \
56     this->detected_->feat = true;                                              \
57   }
58 
59 #define OPCODE_ERROR(opcode, message)                                 \
60   (this->errorf(this->pc_, "%s: %s", WasmOpcodes::OpcodeName(opcode), \
61                 (message)))
62 
63 #define ATOMIC_OP_LIST(V)                \
64   V(I32AtomicLoad, Uint32)               \
65   V(I64AtomicLoad, Uint64)               \
66   V(I32AtomicLoad8U, Uint8)              \
67   V(I32AtomicLoad16U, Uint16)            \
68   V(I64AtomicLoad8U, Uint8)              \
69   V(I64AtomicLoad16U, Uint16)            \
70   V(I64AtomicLoad32U, Uint32)            \
71   V(I32AtomicAdd, Uint32)                \
72   V(I32AtomicAdd8U, Uint8)               \
73   V(I32AtomicAdd16U, Uint16)             \
74   V(I64AtomicAdd, Uint64)                \
75   V(I64AtomicAdd8U, Uint8)               \
76   V(I64AtomicAdd16U, Uint16)             \
77   V(I64AtomicAdd32U, Uint32)             \
78   V(I32AtomicSub, Uint32)                \
79   V(I64AtomicSub, Uint64)                \
80   V(I32AtomicSub8U, Uint8)               \
81   V(I32AtomicSub16U, Uint16)             \
82   V(I64AtomicSub8U, Uint8)               \
83   V(I64AtomicSub16U, Uint16)             \
84   V(I64AtomicSub32U, Uint32)             \
85   V(I32AtomicAnd, Uint32)                \
86   V(I64AtomicAnd, Uint64)                \
87   V(I32AtomicAnd8U, Uint8)               \
88   V(I32AtomicAnd16U, Uint16)             \
89   V(I64AtomicAnd8U, Uint8)               \
90   V(I64AtomicAnd16U, Uint16)             \
91   V(I64AtomicAnd32U, Uint32)             \
92   V(I32AtomicOr, Uint32)                 \
93   V(I64AtomicOr, Uint64)                 \
94   V(I32AtomicOr8U, Uint8)                \
95   V(I32AtomicOr16U, Uint16)              \
96   V(I64AtomicOr8U, Uint8)                \
97   V(I64AtomicOr16U, Uint16)              \
98   V(I64AtomicOr32U, Uint32)              \
99   V(I32AtomicXor, Uint32)                \
100   V(I64AtomicXor, Uint64)                \
101   V(I32AtomicXor8U, Uint8)               \
102   V(I32AtomicXor16U, Uint16)             \
103   V(I64AtomicXor8U, Uint8)               \
104   V(I64AtomicXor16U, Uint16)             \
105   V(I64AtomicXor32U, Uint32)             \
106   V(I32AtomicExchange, Uint32)           \
107   V(I64AtomicExchange, Uint64)           \
108   V(I32AtomicExchange8U, Uint8)          \
109   V(I32AtomicExchange16U, Uint16)        \
110   V(I64AtomicExchange8U, Uint8)          \
111   V(I64AtomicExchange16U, Uint16)        \
112   V(I64AtomicExchange32U, Uint32)        \
113   V(I32AtomicCompareExchange, Uint32)    \
114   V(I64AtomicCompareExchange, Uint64)    \
115   V(I32AtomicCompareExchange8U, Uint8)   \
116   V(I32AtomicCompareExchange16U, Uint16) \
117   V(I64AtomicCompareExchange8U, Uint8)   \
118   V(I64AtomicCompareExchange16U, Uint16) \
119   V(I64AtomicCompareExchange32U, Uint32)
120 
121 #define ATOMIC_STORE_OP_LIST(V) \
122   V(I32AtomicStore, Uint32)     \
123   V(I64AtomicStore, Uint64)     \
124   V(I32AtomicStore8U, Uint8)    \
125   V(I32AtomicStore16U, Uint16)  \
126   V(I64AtomicStore8U, Uint8)    \
127   V(I64AtomicStore16U, Uint16)  \
128   V(I64AtomicStore32U, Uint32)
129 
130 template <typename T, typename Allocator>
vec2vec(std::vector<T,Allocator> & vec)131 Vector<T> vec2vec(std::vector<T, Allocator>& vec) {
132   return Vector<T>(vec.data(), vec.size());
133 }
134 
135 // Helpers for decoding different kinds of immediates which follow bytecodes.
136 template <Decoder::ValidateFlag validate>
137 struct LocalIndexImmediate {
138   uint32_t index;
139   ValueType type = kWasmStmt;
140   unsigned length;
141 
LocalIndexImmediateLocalIndexImmediate142   inline LocalIndexImmediate(Decoder* decoder, const byte* pc) {
143     index = decoder->read_u32v<validate>(pc + 1, &length, "local index");
144   }
145 };
146 
147 template <Decoder::ValidateFlag validate>
148 struct ExceptionIndexImmediate {
149   uint32_t index;
150   const WasmException* exception = nullptr;
151   unsigned length;
152 
ExceptionIndexImmediateExceptionIndexImmediate153   inline ExceptionIndexImmediate(Decoder* decoder, const byte* pc) {
154     index = decoder->read_u32v<validate>(pc + 1, &length, "exception index");
155   }
156 };
157 
158 template <Decoder::ValidateFlag validate>
159 struct ImmI32Immediate {
160   int32_t value;
161   unsigned length;
ImmI32ImmediateImmI32Immediate162   inline ImmI32Immediate(Decoder* decoder, const byte* pc) {
163     value = decoder->read_i32v<validate>(pc + 1, &length, "immi32");
164   }
165 };
166 
167 template <Decoder::ValidateFlag validate>
168 struct ImmI64Immediate {
169   int64_t value;
170   unsigned length;
ImmI64ImmediateImmI64Immediate171   inline ImmI64Immediate(Decoder* decoder, const byte* pc) {
172     value = decoder->read_i64v<validate>(pc + 1, &length, "immi64");
173   }
174 };
175 
176 template <Decoder::ValidateFlag validate>
177 struct ImmF32Immediate {
178   float value;
179   unsigned length = 4;
ImmF32ImmediateImmF32Immediate180   inline ImmF32Immediate(Decoder* decoder, const byte* pc) {
181     // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
182     uint32_t tmp = decoder->read_u32<validate>(pc + 1, "immf32");
183     memcpy(&value, &tmp, sizeof(value));
184   }
185 };
186 
187 template <Decoder::ValidateFlag validate>
188 struct ImmF64Immediate {
189   double value;
190   unsigned length = 8;
ImmF64ImmediateImmF64Immediate191   inline ImmF64Immediate(Decoder* decoder, const byte* pc) {
192     // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
193     uint64_t tmp = decoder->read_u64<validate>(pc + 1, "immf64");
194     memcpy(&value, &tmp, sizeof(value));
195   }
196 };
197 
198 template <Decoder::ValidateFlag validate>
199 struct GlobalIndexImmediate {
200   uint32_t index;
201   ValueType type = kWasmStmt;
202   const WasmGlobal* global = nullptr;
203   unsigned length;
204 
GlobalIndexImmediateGlobalIndexImmediate205   inline GlobalIndexImmediate(Decoder* decoder, const byte* pc) {
206     index = decoder->read_u32v<validate>(pc + 1, &length, "global index");
207   }
208 };
209 
210 template <Decoder::ValidateFlag validate>
211 struct BlockTypeImmediate {
212   unsigned length = 1;
213   ValueType type = kWasmStmt;
214   uint32_t sig_index = 0;
215   FunctionSig* sig = nullptr;
216 
BlockTypeImmediateBlockTypeImmediate217   inline BlockTypeImmediate(const WasmFeatures& enabled, Decoder* decoder,
218                             const byte* pc) {
219     uint8_t val = decoder->read_u8<validate>(pc + 1, "block type");
220     if (!decode_local_type(val, &type)) {
221       // Handle multi-value blocks.
222       if (!VALIDATE(enabled.mv)) {
223         decoder->error(pc + 1, "invalid block type");
224         return;
225       }
226       if (!VALIDATE(decoder->ok())) return;
227       int32_t index =
228           decoder->read_i32v<validate>(pc + 1, &length, "block arity");
229       if (!VALIDATE(length > 0 && index >= 0)) {
230         decoder->error(pc + 1, "invalid block type index");
231         return;
232       }
233       sig_index = static_cast<uint32_t>(index);
234     }
235   }
236 
237   // Decode a byte representing a local type. Return {false} if the encoded
238   // byte was invalid or the start of a type index.
decode_local_typeBlockTypeImmediate239   inline bool decode_local_type(uint8_t val, ValueType* result) {
240     switch (static_cast<ValueTypeCode>(val)) {
241       case kLocalVoid:
242         *result = kWasmStmt;
243         return true;
244       case kLocalI32:
245         *result = kWasmI32;
246         return true;
247       case kLocalI64:
248         *result = kWasmI64;
249         return true;
250       case kLocalF32:
251         *result = kWasmF32;
252         return true;
253       case kLocalF64:
254         *result = kWasmF64;
255         return true;
256       case kLocalS128:
257         *result = kWasmS128;
258         return true;
259       case kLocalAnyFunc:
260         *result = kWasmAnyFunc;
261         return true;
262       case kLocalAnyRef:
263         *result = kWasmAnyRef;
264         return true;
265       default:
266         *result = kWasmVar;
267         return false;
268     }
269   }
270 
in_arityBlockTypeImmediate271   uint32_t in_arity() const {
272     if (type != kWasmVar) return 0;
273     return static_cast<uint32_t>(sig->parameter_count());
274   }
out_arityBlockTypeImmediate275   uint32_t out_arity() const {
276     if (type == kWasmStmt) return 0;
277     if (type != kWasmVar) return 1;
278     return static_cast<uint32_t>(sig->return_count());
279   }
in_typeBlockTypeImmediate280   ValueType in_type(uint32_t index) {
281     DCHECK_EQ(kWasmVar, type);
282     return sig->GetParam(index);
283   }
out_typeBlockTypeImmediate284   ValueType out_type(uint32_t index) {
285     if (type == kWasmVar) return sig->GetReturn(index);
286     DCHECK_NE(kWasmStmt, type);
287     DCHECK_EQ(0, index);
288     return type;
289   }
290 };
291 
292 template <Decoder::ValidateFlag validate>
293 struct BreakDepthImmediate {
294   uint32_t depth;
295   unsigned length;
BreakDepthImmediateBreakDepthImmediate296   inline BreakDepthImmediate(Decoder* decoder, const byte* pc) {
297     depth = decoder->read_u32v<validate>(pc + 1, &length, "break depth");
298   }
299 };
300 
301 template <Decoder::ValidateFlag validate>
302 struct CallIndirectImmediate {
303   uint32_t table_index;
304   uint32_t sig_index;
305   FunctionSig* sig = nullptr;
306   unsigned length = 0;
CallIndirectImmediateCallIndirectImmediate307   inline CallIndirectImmediate(Decoder* decoder, const byte* pc) {
308     unsigned len = 0;
309     sig_index = decoder->read_u32v<validate>(pc + 1, &len, "signature index");
310     if (!VALIDATE(decoder->ok())) return;
311     table_index = decoder->read_u8<validate>(pc + 1 + len, "table index");
312     if (!VALIDATE(table_index == 0)) {
313       decoder->errorf(pc + 1 + len, "expected table index 0, found %u",
314                       table_index);
315     }
316     length = 1 + len;
317   }
318 };
319 
320 template <Decoder::ValidateFlag validate>
321 struct CallFunctionImmediate {
322   uint32_t index;
323   FunctionSig* sig = nullptr;
324   unsigned length;
CallFunctionImmediateCallFunctionImmediate325   inline CallFunctionImmediate(Decoder* decoder, const byte* pc) {
326     index = decoder->read_u32v<validate>(pc + 1, &length, "function index");
327   }
328 };
329 
330 template <Decoder::ValidateFlag validate>
331 struct MemoryIndexImmediate {
332   uint32_t index;
333   unsigned length = 1;
MemoryIndexImmediateMemoryIndexImmediate334   inline MemoryIndexImmediate(Decoder* decoder, const byte* pc) {
335     index = decoder->read_u8<validate>(pc + 1, "memory index");
336     if (!VALIDATE(index == 0)) {
337       decoder->errorf(pc + 1, "expected memory index 0, found %u", index);
338     }
339   }
340 };
341 
342 template <Decoder::ValidateFlag validate>
343 struct BranchTableImmediate {
344   uint32_t table_count;
345   const byte* start;
346   const byte* table;
BranchTableImmediateBranchTableImmediate347   inline BranchTableImmediate(Decoder* decoder, const byte* pc) {
348     DCHECK_EQ(kExprBrTable, decoder->read_u8<validate>(pc, "opcode"));
349     start = pc + 1;
350     unsigned len = 0;
351     table_count = decoder->read_u32v<validate>(pc + 1, &len, "table count");
352     table = pc + 1 + len;
353   }
354 };
355 
356 // A helper to iterate over a branch table.
357 template <Decoder::ValidateFlag validate>
358 class BranchTableIterator {
359  public:
cur_index()360   unsigned cur_index() { return index_; }
has_next()361   bool has_next() { return VALIDATE(decoder_->ok()) && index_ <= table_count_; }
next()362   uint32_t next() {
363     DCHECK(has_next());
364     index_++;
365     unsigned length;
366     uint32_t result =
367         decoder_->read_u32v<validate>(pc_, &length, "branch table entry");
368     pc_ += length;
369     return result;
370   }
371   // length, including the length of the {BranchTableImmediate}, but not the
372   // opcode.
length()373   unsigned length() {
374     while (has_next()) next();
375     return static_cast<unsigned>(pc_ - start_);
376   }
pc()377   const byte* pc() { return pc_; }
378 
BranchTableIterator(Decoder * decoder,const BranchTableImmediate<validate> & imm)379   BranchTableIterator(Decoder* decoder,
380                       const BranchTableImmediate<validate>& imm)
381       : decoder_(decoder),
382         start_(imm.start),
383         pc_(imm.table),
384         table_count_(imm.table_count) {}
385 
386  private:
387   Decoder* decoder_;
388   const byte* start_;
389   const byte* pc_;
390   uint32_t index_ = 0;    // the current index.
391   uint32_t table_count_;  // the count of entries, not including default.
392 };
393 
394 template <Decoder::ValidateFlag validate>
395 struct MemoryAccessImmediate {
396   uint32_t alignment;
397   uint32_t offset;
398   unsigned length = 0;
MemoryAccessImmediateMemoryAccessImmediate399   inline MemoryAccessImmediate(Decoder* decoder, const byte* pc,
400                                uint32_t max_alignment) {
401     unsigned alignment_length;
402     alignment =
403         decoder->read_u32v<validate>(pc + 1, &alignment_length, "alignment");
404     if (!VALIDATE(alignment <= max_alignment)) {
405       decoder->errorf(pc + 1,
406                       "invalid alignment; expected maximum alignment is %u, "
407                       "actual alignment is %u",
408                       max_alignment, alignment);
409     }
410     if (!VALIDATE(decoder->ok())) return;
411     unsigned offset_length;
412     offset = decoder->read_u32v<validate>(pc + 1 + alignment_length,
413                                           &offset_length, "offset");
414     length = alignment_length + offset_length;
415   }
416 };
417 
418 // Immediate for SIMD lane operations.
419 template <Decoder::ValidateFlag validate>
420 struct SimdLaneImmediate {
421   uint8_t lane;
422   unsigned length = 1;
423 
SimdLaneImmediateSimdLaneImmediate424   inline SimdLaneImmediate(Decoder* decoder, const byte* pc) {
425     lane = decoder->read_u8<validate>(pc + 2, "lane");
426   }
427 };
428 
429 // Immediate for SIMD shift operations.
430 template <Decoder::ValidateFlag validate>
431 struct SimdShiftImmediate {
432   uint8_t shift;
433   unsigned length = 1;
434 
SimdShiftImmediateSimdShiftImmediate435   inline SimdShiftImmediate(Decoder* decoder, const byte* pc) {
436     shift = decoder->read_u8<validate>(pc + 2, "shift");
437   }
438 };
439 
440 // Immediate for SIMD S8x16 shuffle operations.
441 template <Decoder::ValidateFlag validate>
442 struct Simd8x16ShuffleImmediate {
443   uint8_t shuffle[kSimd128Size] = {0};
444 
Simd8x16ShuffleImmediateSimd8x16ShuffleImmediate445   inline Simd8x16ShuffleImmediate(Decoder* decoder, const byte* pc) {
446     for (uint32_t i = 0; i < kSimd128Size; ++i) {
447       shuffle[i] = decoder->read_u8<validate>(pc + 2 + i, "shuffle");
448       if (!VALIDATE(decoder->ok())) return;
449     }
450   }
451 };
452 
453 // An entry on the value stack.
454 struct ValueBase {
455   const byte* pc;
456   ValueType type;
457 
458   // Named constructors.
UnreachableValueBase459   static ValueBase Unreachable(const byte* pc) { return {pc, kWasmVar}; }
460 
NewValueBase461   static ValueBase New(const byte* pc, ValueType type) { return {pc, type}; }
462 };
463 
464 template <typename Value>
465 struct Merge {
466   uint32_t arity;
467   union {
468     Value* array;
469     Value first;
470   } vals;  // Either multiple values or a single value.
471 
472   // Tracks whether this merge was ever reached. Uses precise reachability, like
473   // Reachability::kReachable.
474   bool reached;
475 
reachedMerge476   Merge(bool reached = false) : reached(reached) {}
477 
478   Value& operator[](uint32_t i) {
479     DCHECK_GT(arity, i);
480     return arity == 1 ? vals.first : vals.array[i];
481   }
482 };
483 
484 enum ControlKind : uint8_t {
485   kControlIf,
486   kControlIfElse,
487   kControlBlock,
488   kControlLoop,
489   kControlTry,
490   kControlTryCatch
491 };
492 
493 enum Reachability : uint8_t {
494   // reachable code.
495   kReachable,
496   // reachable code in unreachable block (implies normal validation).
497   kSpecOnlyReachable,
498   // code unreachable in its own block (implies polymorphic validation).
499   kUnreachable
500 };
501 
502 // An entry on the control stack (i.e. if, block, loop, or try).
503 template <typename Value>
504 struct ControlBase {
505   ControlKind kind;
506   uint32_t stack_depth;  // stack height at the beginning of the construct.
507   const byte* pc;
508   Reachability reachability = kReachable;
509 
510   // Values merged into the start or end of this control construct.
511   Merge<Value> start_merge;
512   Merge<Value> end_merge;
513 
514   ControlBase() = default;
ControlBaseControlBase515   ControlBase(ControlKind kind, uint32_t stack_depth, const byte* pc)
516       : kind(kind), stack_depth(stack_depth), pc(pc) {}
517 
518   // Check whether the current block is reachable.
reachableControlBase519   bool reachable() const { return reachability == kReachable; }
520 
521   // Check whether the rest of the block is unreachable.
522   // Note that this is different from {!reachable()}, as there is also the
523   // "indirect unreachable state", for which both {reachable()} and
524   // {unreachable()} return false.
unreachableControlBase525   bool unreachable() const { return reachability == kUnreachable; }
526 
527   // Return the reachability of new control structs started in this block.
innerReachabilityControlBase528   Reachability innerReachability() const {
529     return reachability == kReachable ? kReachable : kSpecOnlyReachable;
530   }
531 
is_ifControlBase532   bool is_if() const { return is_onearmed_if() || is_if_else(); }
is_onearmed_ifControlBase533   bool is_onearmed_if() const { return kind == kControlIf; }
is_if_elseControlBase534   bool is_if_else() const { return kind == kControlIfElse; }
is_blockControlBase535   bool is_block() const { return kind == kControlBlock; }
is_loopControlBase536   bool is_loop() const { return kind == kControlLoop; }
is_tryControlBase537   bool is_try() const { return is_incomplete_try() || is_try_catch(); }
is_incomplete_tryControlBase538   bool is_incomplete_try() const { return kind == kControlTry; }
is_try_catchControlBase539   bool is_try_catch() const { return kind == kControlTryCatch; }
540 
br_mergeControlBase541   inline Merge<Value>* br_merge() {
542     return is_loop() ? &this->start_merge : &this->end_merge;
543   }
544 
545   // Named constructors.
BlockControlBase546   static ControlBase Block(const byte* pc, uint32_t stack_depth) {
547     return {kControlBlock, stack_depth, pc};
548   }
549 
IfControlBase550   static ControlBase If(const byte* pc, uint32_t stack_depth) {
551     return {kControlIf, stack_depth, pc};
552   }
553 
LoopControlBase554   static ControlBase Loop(const byte* pc, uint32_t stack_depth) {
555     return {kControlLoop, stack_depth, pc};
556   }
557 
TryControlBase558   static ControlBase Try(const byte* pc, uint32_t stack_depth) {
559     return {kControlTry, stack_depth, pc};
560   }
561 };
562 
563 #define CONCRETE_NAMED_CONSTRUCTOR(concrete_type, abstract_type, name) \
564   template <typename... Args>                                          \
565   static concrete_type name(Args&&... args) {                          \
566     concrete_type val;                                                 \
567     static_cast<abstract_type&>(val) =                                 \
568         abstract_type::name(std::forward<Args>(args)...);              \
569     return val;                                                        \
570   }
571 
572 // Provide the default named constructors, which default-initialize the
573 // ConcreteType and the initialize the fields of ValueBase correctly.
574 // Use like this:
575 // struct Value : public ValueWithNamedConstructors<Value> { int new_field; };
576 template <typename ConcreteType>
577 struct ValueWithNamedConstructors : public ValueBase {
578   // Named constructors.
579   CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ValueBase, Unreachable)
580   CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ValueBase, New)
581 };
582 
583 // Provide the default named constructors, which default-initialize the
584 // ConcreteType and the initialize the fields of ControlBase correctly.
585 // Use like this:
586 // struct Control : public ControlWithNamedConstructors<Control, Value> {
587 //   int my_uninitialized_field;
588 //   char* other_field = nullptr;
589 // };
590 template <typename ConcreteType, typename Value>
591 struct ControlWithNamedConstructors : public ControlBase<Value> {
592   // Named constructors.
593   CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Block)
594   CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, If)
595   CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Loop)
596   CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Try)
597 };
598 
599 // This is the list of callback functions that an interface for the
600 // WasmFullDecoder should implement.
601 // F(Name, args...)
602 #define INTERFACE_FUNCTIONS(F)                                                \
603   /* General: */                                                              \
604   F(StartFunction)                                                            \
605   F(StartFunctionBody, Control* block)                                        \
606   F(FinishFunction)                                                           \
607   F(OnFirstError)                                                             \
608   F(NextInstruction, WasmOpcode)                                              \
609   /* Control: */                                                              \
610   F(Block, Control* block)                                                    \
611   F(Loop, Control* block)                                                     \
612   F(Try, Control* block)                                                      \
613   F(If, const Value& cond, Control* if_block)                                 \
614   F(FallThruTo, Control* c)                                                   \
615   F(PopControl, Control* block)                                               \
616   F(EndControl, Control* block)                                               \
617   /* Instructions: */                                                         \
618   F(UnOp, WasmOpcode opcode, FunctionSig*, const Value& value, Value* result) \
619   F(BinOp, WasmOpcode opcode, FunctionSig*, const Value& lhs,                 \
620     const Value& rhs, Value* result)                                          \
621   F(I32Const, Value* result, int32_t value)                                   \
622   F(I64Const, Value* result, int64_t value)                                   \
623   F(F32Const, Value* result, float value)                                     \
624   F(F64Const, Value* result, double value)                                    \
625   F(RefNull, Value* result)                                                   \
626   F(Drop, const Value& value)                                                 \
627   F(DoReturn, Vector<Value> values, bool implicit)                            \
628   F(GetLocal, Value* result, const LocalIndexImmediate<validate>& imm)        \
629   F(SetLocal, const Value& value, const LocalIndexImmediate<validate>& imm)   \
630   F(TeeLocal, const Value& value, Value* result,                              \
631     const LocalIndexImmediate<validate>& imm)                                 \
632   F(GetGlobal, Value* result, const GlobalIndexImmediate<validate>& imm)      \
633   F(SetGlobal, const Value& value, const GlobalIndexImmediate<validate>& imm) \
634   F(Unreachable)                                                              \
635   F(Select, const Value& cond, const Value& fval, const Value& tval,          \
636     Value* result)                                                            \
637   F(Br, Control* target)                                                      \
638   F(BrIf, const Value& cond, Control* target)                                 \
639   F(BrTable, const BranchTableImmediate<validate>& imm, const Value& key)     \
640   F(Else, Control* if_block)                                                  \
641   F(LoadMem, LoadType type, const MemoryAccessImmediate<validate>& imm,       \
642     const Value& index, Value* result)                                        \
643   F(StoreMem, StoreType type, const MemoryAccessImmediate<validate>& imm,     \
644     const Value& index, const Value& value)                                   \
645   F(CurrentMemoryPages, Value* result)                                        \
646   F(GrowMemory, const Value& value, Value* result)                            \
647   F(CallDirect, const CallFunctionImmediate<validate>& imm,                   \
648     const Value args[], Value returns[])                                      \
649   F(CallIndirect, const Value& index,                                         \
650     const CallIndirectImmediate<validate>& imm, const Value args[],           \
651     Value returns[])                                                          \
652   F(SimdOp, WasmOpcode opcode, Vector<Value> args, Value* result)             \
653   F(SimdLaneOp, WasmOpcode opcode, const SimdLaneImmediate<validate>& imm,    \
654     const Vector<Value> inputs, Value* result)                                \
655   F(SimdShiftOp, WasmOpcode opcode, const SimdShiftImmediate<validate>& imm,  \
656     const Value& input, Value* result)                                        \
657   F(Simd8x16ShuffleOp, const Simd8x16ShuffleImmediate<validate>& imm,         \
658     const Value& input0, const Value& input1, Value* result)                  \
659   F(Throw, const ExceptionIndexImmediate<validate>&, Control* block,          \
660     const Vector<Value>& args)                                                \
661   F(CatchException, const ExceptionIndexImmediate<validate>& imm,             \
662     Control* block, Vector<Value> caught_values)                              \
663   F(AtomicOp, WasmOpcode opcode, Vector<Value> args,                          \
664     const MemoryAccessImmediate<validate>& imm, Value* result)
665 
666 // Generic Wasm bytecode decoder with utilities for decoding immediates,
667 // lengths, etc.
668 template <Decoder::ValidateFlag validate>
669 class WasmDecoder : public Decoder {
670  public:
671   WasmDecoder(const WasmModule* module, const WasmFeatures& enabled,
672               WasmFeatures* detected, FunctionSig* sig, const byte* start,
673               const byte* end, uint32_t buffer_offset = 0)
Decoder(start,end,buffer_offset)674       : Decoder(start, end, buffer_offset),
675         module_(module),
676         enabled_(enabled),
677         detected_(detected),
678         sig_(sig),
679         local_types_(nullptr) {}
680   const WasmModule* module_;
681   const WasmFeatures enabled_;
682   WasmFeatures* detected_;
683   FunctionSig* sig_;
684 
685   ZoneVector<ValueType>* local_types_;
686 
total_locals()687   uint32_t total_locals() const {
688     return local_types_ == nullptr
689                ? 0
690                : static_cast<uint32_t>(local_types_->size());
691   }
692 
DecodeLocals(const WasmFeatures & enabled,Decoder * decoder,const FunctionSig * sig,ZoneVector<ValueType> * type_list)693   static bool DecodeLocals(const WasmFeatures& enabled, Decoder* decoder,
694                            const FunctionSig* sig,
695                            ZoneVector<ValueType>* type_list) {
696     DCHECK_NOT_NULL(type_list);
697     DCHECK_EQ(0, type_list->size());
698     // Initialize from signature.
699     if (sig != nullptr) {
700       type_list->assign(sig->parameters().begin(), sig->parameters().end());
701     }
702     // Decode local declarations, if any.
703     uint32_t entries = decoder->consume_u32v("local decls count");
704     if (decoder->failed()) return false;
705 
706     TRACE("local decls count: %u\n", entries);
707     while (entries-- > 0 && VALIDATE(decoder->ok()) && decoder->more()) {
708       uint32_t count = decoder->consume_u32v("local count");
709       if (decoder->failed()) return false;
710 
711       DCHECK_LE(type_list->size(), kV8MaxWasmFunctionLocals);
712       if (count > kV8MaxWasmFunctionLocals - type_list->size()) {
713         decoder->error(decoder->pc() - 1, "local count too large");
714         return false;
715       }
716       byte code = decoder->consume_u8("local type");
717       if (decoder->failed()) return false;
718 
719       ValueType type;
720       switch (code) {
721         case kLocalI32:
722           type = kWasmI32;
723           break;
724         case kLocalI64:
725           type = kWasmI64;
726           break;
727         case kLocalF32:
728           type = kWasmF32;
729           break;
730         case kLocalF64:
731           type = kWasmF64;
732           break;
733         case kLocalAnyRef:
734           if (enabled.anyref) {
735             type = kWasmAnyRef;
736             break;
737           }
738           decoder->error(decoder->pc() - 1, "invalid local type");
739           return false;
740         case kLocalS128:
741           if (enabled.simd) {
742             type = kWasmS128;
743             break;
744           }
745           V8_FALLTHROUGH;
746         default:
747           decoder->error(decoder->pc() - 1, "invalid local type");
748           return false;
749       }
750       type_list->insert(type_list->end(), count, type);
751     }
752     DCHECK(decoder->ok());
753     return true;
754   }
755 
AnalyzeLoopAssignment(Decoder * decoder,const byte * pc,uint32_t locals_count,Zone * zone)756   static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc,
757                                           uint32_t locals_count, Zone* zone) {
758     if (pc >= decoder->end()) return nullptr;
759     if (*pc != kExprLoop) return nullptr;
760 
761     // The number of locals_count is augmented by 2 so that 'locals_count - 2'
762     // can be used to track mem_size, and 'locals_count - 1' to track mem_start.
763     BitVector* assigned = new (zone) BitVector(locals_count, zone);
764     int depth = 0;
765     // Iteratively process all AST nodes nested inside the loop.
766     while (pc < decoder->end() && VALIDATE(decoder->ok())) {
767       WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
768       unsigned length = 1;
769       switch (opcode) {
770         case kExprLoop:
771         case kExprIf:
772         case kExprBlock:
773         case kExprTry:
774           length = OpcodeLength(decoder, pc);
775           depth++;
776           break;
777         case kExprSetLocal:  // fallthru
778         case kExprTeeLocal: {
779           LocalIndexImmediate<Decoder::kValidate> imm(decoder, pc);
780           if (assigned->length() > 0 &&
781               imm.index < static_cast<uint32_t>(assigned->length())) {
782             // Unverified code might have an out-of-bounds index.
783             assigned->Add(imm.index);
784           }
785           length = 1 + imm.length;
786           break;
787         }
788         case kExprGrowMemory:
789         case kExprCallFunction:
790         case kExprCallIndirect:
791           // Add instance cache nodes to the assigned set.
792           // TODO(titzer): make this more clear.
793           assigned->Add(locals_count - 1);
794           length = OpcodeLength(decoder, pc);
795           break;
796         case kExprEnd:
797           depth--;
798           break;
799         default:
800           length = OpcodeLength(decoder, pc);
801           break;
802       }
803       if (depth <= 0) break;
804       pc += length;
805     }
806     return VALIDATE(decoder->ok()) ? assigned : nullptr;
807   }
808 
Validate(const byte * pc,LocalIndexImmediate<Decoder::kValidate> & imm)809   inline bool Validate(const byte* pc,
810                        LocalIndexImmediate<Decoder::kValidate>& imm) {
811     if (!VALIDATE(imm.index < total_locals())) {
812       errorf(pc + 1, "invalid local index: %u", imm.index);
813       return false;
814     }
815     imm.type = local_types_ ? local_types_->at(imm.index) : kWasmStmt;
816     return true;
817   }
818 
Validate(const byte * pc,ExceptionIndexImmediate<validate> & imm)819   inline bool Validate(const byte* pc, ExceptionIndexImmediate<validate>& imm) {
820     if (!VALIDATE(module_ != nullptr &&
821                   imm.index < module_->exceptions.size())) {
822       errorf(pc + 1, "Invalid exception index: %u", imm.index);
823       return false;
824     }
825     imm.exception = &module_->exceptions[imm.index];
826     return true;
827   }
828 
Validate(const byte * pc,GlobalIndexImmediate<validate> & imm)829   inline bool Validate(const byte* pc, GlobalIndexImmediate<validate>& imm) {
830     if (!VALIDATE(module_ != nullptr && imm.index < module_->globals.size())) {
831       errorf(pc + 1, "invalid global index: %u", imm.index);
832       return false;
833     }
834     imm.global = &module_->globals[imm.index];
835     imm.type = imm.global->type;
836     return true;
837   }
838 
Complete(const byte * pc,CallFunctionImmediate<validate> & imm)839   inline bool Complete(const byte* pc, CallFunctionImmediate<validate>& imm) {
840     if (!VALIDATE(module_ != nullptr &&
841                   imm.index < module_->functions.size())) {
842       return false;
843     }
844     imm.sig = module_->functions[imm.index].sig;
845     return true;
846   }
847 
Validate(const byte * pc,CallFunctionImmediate<validate> & imm)848   inline bool Validate(const byte* pc, CallFunctionImmediate<validate>& imm) {
849     if (Complete(pc, imm)) {
850       return true;
851     }
852     errorf(pc + 1, "invalid function index: %u", imm.index);
853     return false;
854   }
855 
Complete(const byte * pc,CallIndirectImmediate<validate> & imm)856   inline bool Complete(const byte* pc, CallIndirectImmediate<validate>& imm) {
857     if (!VALIDATE(module_ != nullptr &&
858                   imm.sig_index < module_->signatures.size())) {
859       return false;
860     }
861     imm.sig = module_->signatures[imm.sig_index];
862     return true;
863   }
864 
Validate(const byte * pc,CallIndirectImmediate<validate> & imm)865   inline bool Validate(const byte* pc, CallIndirectImmediate<validate>& imm) {
866     if (!VALIDATE(module_ != nullptr && !module_->tables.empty())) {
867       error("function table has to exist to execute call_indirect");
868       return false;
869     }
870     if (!Complete(pc, imm)) {
871       errorf(pc + 1, "invalid signature index: #%u", imm.sig_index);
872       return false;
873     }
874     return true;
875   }
876 
Validate(const byte * pc,BreakDepthImmediate<validate> & imm,size_t control_depth)877   inline bool Validate(const byte* pc, BreakDepthImmediate<validate>& imm,
878                        size_t control_depth) {
879     if (!VALIDATE(imm.depth < control_depth)) {
880       errorf(pc + 1, "invalid break depth: %u", imm.depth);
881       return false;
882     }
883     return true;
884   }
885 
Validate(const byte * pc,BranchTableImmediate<validate> & imm,size_t block_depth)886   bool Validate(const byte* pc, BranchTableImmediate<validate>& imm,
887                 size_t block_depth) {
888     if (!VALIDATE(imm.table_count < kV8MaxWasmFunctionSize)) {
889       errorf(pc + 1, "invalid table count (> max function size): %u",
890              imm.table_count);
891       return false;
892     }
893     return checkAvailable(imm.table_count);
894   }
895 
Validate(const byte * pc,WasmOpcode opcode,SimdLaneImmediate<validate> & imm)896   inline bool Validate(const byte* pc, WasmOpcode opcode,
897                        SimdLaneImmediate<validate>& imm) {
898     uint8_t num_lanes = 0;
899     switch (opcode) {
900       case kExprF32x4ExtractLane:
901       case kExprF32x4ReplaceLane:
902       case kExprI32x4ExtractLane:
903       case kExprI32x4ReplaceLane:
904         num_lanes = 4;
905         break;
906       case kExprI16x8ExtractLane:
907       case kExprI16x8ReplaceLane:
908         num_lanes = 8;
909         break;
910       case kExprI8x16ExtractLane:
911       case kExprI8x16ReplaceLane:
912         num_lanes = 16;
913         break;
914       default:
915         UNREACHABLE();
916         break;
917     }
918     if (!VALIDATE(imm.lane >= 0 && imm.lane < num_lanes)) {
919       error(pc_ + 2, "invalid lane index");
920       return false;
921     } else {
922       return true;
923     }
924   }
925 
Validate(const byte * pc,WasmOpcode opcode,SimdShiftImmediate<validate> & imm)926   inline bool Validate(const byte* pc, WasmOpcode opcode,
927                        SimdShiftImmediate<validate>& imm) {
928     uint8_t max_shift = 0;
929     switch (opcode) {
930       case kExprI32x4Shl:
931       case kExprI32x4ShrS:
932       case kExprI32x4ShrU:
933         max_shift = 32;
934         break;
935       case kExprI16x8Shl:
936       case kExprI16x8ShrS:
937       case kExprI16x8ShrU:
938         max_shift = 16;
939         break;
940       case kExprI8x16Shl:
941       case kExprI8x16ShrS:
942       case kExprI8x16ShrU:
943         max_shift = 8;
944         break;
945       default:
946         UNREACHABLE();
947         break;
948     }
949     if (!VALIDATE(imm.shift >= 0 && imm.shift < max_shift)) {
950       error(pc_ + 2, "invalid shift amount");
951       return false;
952     } else {
953       return true;
954     }
955   }
956 
Validate(const byte * pc,Simd8x16ShuffleImmediate<validate> & imm)957   inline bool Validate(const byte* pc,
958                        Simd8x16ShuffleImmediate<validate>& imm) {
959     uint8_t max_lane = 0;
960     for (uint32_t i = 0; i < kSimd128Size; ++i) {
961       max_lane = std::max(max_lane, imm.shuffle[i]);
962     }
963     // Shuffle indices must be in [0..31] for a 16 lane shuffle.
964     if (!VALIDATE(max_lane <= 2 * kSimd128Size)) {
965       error(pc_ + 2, "invalid shuffle mask");
966       return false;
967     }
968     return true;
969   }
970 
Complete(BlockTypeImmediate<validate> & imm)971   inline bool Complete(BlockTypeImmediate<validate>& imm) {
972     if (imm.type != kWasmVar) return true;
973     if (!VALIDATE((module_ && imm.sig_index < module_->signatures.size()))) {
974       return false;
975     }
976     imm.sig = module_->signatures[imm.sig_index];
977     return true;
978   }
979 
Validate(BlockTypeImmediate<validate> & imm)980   inline bool Validate(BlockTypeImmediate<validate>& imm) {
981     if (!Complete(imm)) {
982       errorf(pc_, "block type index %u out of bounds (%zu signatures)",
983              imm.sig_index, module_ ? module_->signatures.size() : 0);
984       return false;
985     }
986     return true;
987   }
988 
OpcodeLength(Decoder * decoder,const byte * pc)989   static unsigned OpcodeLength(Decoder* decoder, const byte* pc) {
990     WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
991     switch (opcode) {
992 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
993       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
994       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
995 #undef DECLARE_OPCODE_CASE
996       {
997         MemoryAccessImmediate<validate> imm(decoder, pc, UINT32_MAX);
998         return 1 + imm.length;
999       }
1000       case kExprBr:
1001       case kExprBrIf: {
1002         BreakDepthImmediate<validate> imm(decoder, pc);
1003         return 1 + imm.length;
1004       }
1005       case kExprSetGlobal:
1006       case kExprGetGlobal: {
1007         GlobalIndexImmediate<validate> imm(decoder, pc);
1008         return 1 + imm.length;
1009       }
1010 
1011       case kExprCallFunction: {
1012         CallFunctionImmediate<validate> imm(decoder, pc);
1013         return 1 + imm.length;
1014       }
1015       case kExprCallIndirect: {
1016         CallIndirectImmediate<validate> imm(decoder, pc);
1017         return 1 + imm.length;
1018       }
1019 
1020       case kExprTry:
1021       case kExprIf:  // fall through
1022       case kExprLoop:
1023       case kExprBlock: {
1024         BlockTypeImmediate<validate> imm(kAllWasmFeatures, decoder, pc);
1025         return 1 + imm.length;
1026       }
1027 
1028       case kExprThrow:
1029       case kExprCatch: {
1030         ExceptionIndexImmediate<validate> imm(decoder, pc);
1031         return 1 + imm.length;
1032       }
1033 
1034       case kExprSetLocal:
1035       case kExprTeeLocal:
1036       case kExprGetLocal: {
1037         LocalIndexImmediate<Decoder::kValidate> imm(decoder, pc);
1038         return 1 + imm.length;
1039       }
1040       case kExprBrTable: {
1041         BranchTableImmediate<validate> imm(decoder, pc);
1042         BranchTableIterator<validate> iterator(decoder, imm);
1043         return 1 + iterator.length();
1044       }
1045       case kExprI32Const: {
1046         ImmI32Immediate<validate> imm(decoder, pc);
1047         return 1 + imm.length;
1048       }
1049       case kExprI64Const: {
1050         ImmI64Immediate<validate> imm(decoder, pc);
1051         return 1 + imm.length;
1052       }
1053       case kExprRefNull: {
1054         return 1;
1055       }
1056       case kExprGrowMemory:
1057       case kExprMemorySize: {
1058         MemoryIndexImmediate<validate> imm(decoder, pc);
1059         return 1 + imm.length;
1060       }
1061       case kExprF32Const:
1062         return 5;
1063       case kExprF64Const:
1064         return 9;
1065       case kNumericPrefix:
1066         return 2;
1067       case kSimdPrefix: {
1068         byte simd_index = decoder->read_u8<validate>(pc + 1, "simd_index");
1069         WasmOpcode opcode =
1070             static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
1071         switch (opcode) {
1072 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1073           FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
1074 #undef DECLARE_OPCODE_CASE
1075           return 2;
1076 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1077           FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
1078 #undef DECLARE_OPCODE_CASE
1079           return 3;
1080 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1081           FOREACH_SIMD_MEM_OPCODE(DECLARE_OPCODE_CASE)
1082 #undef DECLARE_OPCODE_CASE
1083           {
1084             MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
1085             return 2 + imm.length;
1086           }
1087           // Shuffles require a byte per lane, or 16 immediate bytes.
1088           case kExprS8x16Shuffle:
1089             return 2 + kSimd128Size;
1090           default:
1091             decoder->error(pc, "invalid SIMD opcode");
1092             return 2;
1093         }
1094       }
1095       case kAtomicPrefix: {
1096         byte atomic_index = decoder->read_u8<validate>(pc + 1, "atomic_index");
1097         WasmOpcode opcode =
1098             static_cast<WasmOpcode>(kAtomicPrefix << 8 | atomic_index);
1099         switch (opcode) {
1100 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1101           FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE)
1102 #undef DECLARE_OPCODE_CASE
1103           {
1104             MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
1105             return 2 + imm.length;
1106           }
1107           default:
1108             decoder->error(pc, "invalid Atomics opcode");
1109             return 2;
1110         }
1111       }
1112       default:
1113         return 1;
1114     }
1115   }
1116 
StackEffect(const byte * pc)1117   std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) {
1118     WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
1119     // Handle "simple" opcodes with a fixed signature first.
1120     FunctionSig* sig = WasmOpcodes::Signature(opcode);
1121     if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode);
1122     if (sig) return {sig->parameter_count(), sig->return_count()};
1123 
1124 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1125     // clang-format off
1126     switch (opcode) {
1127       case kExprSelect:
1128         return {3, 1};
1129       FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
1130         return {2, 0};
1131       FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
1132       case kExprTeeLocal:
1133       case kExprGrowMemory:
1134         return {1, 1};
1135       case kExprSetLocal:
1136       case kExprSetGlobal:
1137       case kExprDrop:
1138       case kExprBrIf:
1139       case kExprBrTable:
1140       case kExprIf:
1141         return {1, 0};
1142       case kExprGetLocal:
1143       case kExprGetGlobal:
1144       case kExprI32Const:
1145       case kExprI64Const:
1146       case kExprF32Const:
1147       case kExprF64Const:
1148       case kExprRefNull:
1149       case kExprMemorySize:
1150         return {0, 1};
1151       case kExprCallFunction: {
1152         CallFunctionImmediate<validate> imm(this, pc);
1153         CHECK(Complete(pc, imm));
1154         return {imm.sig->parameter_count(), imm.sig->return_count()};
1155       }
1156       case kExprCallIndirect: {
1157         CallIndirectImmediate<validate> imm(this, pc);
1158         CHECK(Complete(pc, imm));
1159         // Indirect calls pop an additional argument for the table index.
1160         return {imm.sig->parameter_count() + 1,
1161                 imm.sig->return_count()};
1162       }
1163       case kExprBr:
1164       case kExprBlock:
1165       case kExprLoop:
1166       case kExprEnd:
1167       case kExprElse:
1168       case kExprNop:
1169       case kExprReturn:
1170       case kExprUnreachable:
1171         return {0, 0};
1172       case kNumericPrefix:
1173       case kAtomicPrefix:
1174       case kSimdPrefix: {
1175         opcode = static_cast<WasmOpcode>(opcode << 8 | *(pc + 1));
1176         switch (opcode) {
1177           FOREACH_SIMD_1_OPERAND_1_PARAM_OPCODE(DECLARE_OPCODE_CASE)
1178             return {1, 1};
1179           FOREACH_SIMD_1_OPERAND_2_PARAM_OPCODE(DECLARE_OPCODE_CASE)
1180           FOREACH_SIMD_MASK_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
1181             return {2, 1};
1182           default: {
1183             sig = WasmOpcodes::Signature(opcode);
1184             if (sig) {
1185               return {sig->parameter_count(), sig->return_count()};
1186             }
1187           }
1188         }
1189         V8_FALLTHROUGH;
1190       }
1191       default:
1192         V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x (%s)", opcode,
1193                  WasmOpcodes::OpcodeName(opcode));
1194         return {0, 0};
1195     }
1196 #undef DECLARE_OPCODE_CASE
1197     // clang-format on
1198   }
1199 };
1200 
1201 #define CALL_INTERFACE(name, ...) interface_.name(this, ##__VA_ARGS__)
1202 #define CALL_INTERFACE_IF_REACHABLE(name, ...)                 \
1203   do {                                                         \
1204     DCHECK(!control_.empty());                                 \
1205     if (VALIDATE(this->ok()) && control_.back().reachable()) { \
1206       interface_.name(this, ##__VA_ARGS__);                    \
1207     }                                                          \
1208   } while (false)
1209 #define CALL_INTERFACE_IF_PARENT_REACHABLE(name, ...)           \
1210   do {                                                          \
1211     DCHECK(!control_.empty());                                  \
1212     if (VALIDATE(this->ok()) &&                                 \
1213         (control_.size() == 1 || control_at(1)->reachable())) { \
1214       interface_.name(this, ##__VA_ARGS__);                     \
1215     }                                                           \
1216   } while (false)
1217 
1218 template <Decoder::ValidateFlag validate, typename Interface>
1219 class WasmFullDecoder : public WasmDecoder<validate> {
1220   using Value = typename Interface::Value;
1221   using Control = typename Interface::Control;
1222   using MergeValues = Merge<Value>;
1223 
1224   // All Value types should be trivially copyable for performance. We push, pop,
1225   // and store them in local variables.
1226   ASSERT_TRIVIALLY_COPYABLE(Value);
1227 
1228  public:
1229   template <typename... InterfaceArgs>
WasmFullDecoder(Zone * zone,const WasmModule * module,const WasmFeatures & enabled,WasmFeatures * detected,const FunctionBody & body,InterfaceArgs &&...interface_args)1230   WasmFullDecoder(Zone* zone, const WasmModule* module,
1231                   const WasmFeatures& enabled, WasmFeatures* detected,
1232                   const FunctionBody& body, InterfaceArgs&&... interface_args)
1233       : WasmDecoder<validate>(module, enabled, detected, body.sig, body.start,
1234                               body.end, body.offset),
1235         zone_(zone),
1236         interface_(std::forward<InterfaceArgs>(interface_args)...),
1237         local_type_vec_(zone),
1238         stack_(zone),
1239         control_(zone),
1240         args_(zone),
1241         last_end_found_(false) {
1242     this->local_types_ = &local_type_vec_;
1243   }
1244 
interface()1245   Interface& interface() { return interface_; }
1246 
Decode()1247   bool Decode() {
1248     DCHECK(stack_.empty());
1249     DCHECK(control_.empty());
1250 
1251     base::ElapsedTimer decode_timer;
1252     if (FLAG_trace_wasm_decode_time) {
1253       decode_timer.Start();
1254     }
1255 
1256     if (this->end_ < this->pc_) {
1257       this->error("function body end < start");
1258       return false;
1259     }
1260 
1261     DCHECK_EQ(0, this->local_types_->size());
1262     WasmDecoder<validate>::DecodeLocals(this->enabled_, this, this->sig_,
1263                                         this->local_types_);
1264     CALL_INTERFACE(StartFunction);
1265     DecodeFunctionBody();
1266     if (!this->failed()) CALL_INTERFACE(FinishFunction);
1267 
1268     if (this->failed()) return this->TraceFailed();
1269 
1270     if (!control_.empty()) {
1271       // Generate a better error message whether the unterminated control
1272       // structure is the function body block or an innner structure.
1273       if (control_.size() > 1) {
1274         this->error(control_.back().pc, "unterminated control structure");
1275       } else {
1276         this->error("function body must end with \"end\" opcode");
1277       }
1278       return TraceFailed();
1279     }
1280 
1281     if (!last_end_found_) {
1282       this->error("function body must end with \"end\" opcode");
1283       return false;
1284     }
1285 
1286     if (FLAG_trace_wasm_decode_time) {
1287       double ms = decode_timer.Elapsed().InMillisecondsF();
1288       PrintF("wasm-decode %s (%0.3f ms)\n\n",
1289              VALIDATE(this->ok()) ? "ok" : "failed", ms);
1290     } else {
1291       TRACE("wasm-decode %s\n\n", VALIDATE(this->ok()) ? "ok" : "failed");
1292     }
1293 
1294     return true;
1295   }
1296 
TraceFailed()1297   bool TraceFailed() {
1298     TRACE("wasm-error module+%-6d func+%d: %s\n\n", this->error_offset_,
1299           this->GetBufferRelativeOffset(this->error_offset_),
1300           this->error_msg_.c_str());
1301     return false;
1302   }
1303 
SafeOpcodeNameAt(const byte * pc)1304   const char* SafeOpcodeNameAt(const byte* pc) {
1305     if (pc >= this->end_) return "<end>";
1306     return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(*pc));
1307   }
1308 
zone()1309   inline Zone* zone() const { return zone_; }
1310 
NumLocals()1311   inline uint32_t NumLocals() {
1312     return static_cast<uint32_t>(local_type_vec_.size());
1313   }
1314 
GetLocalType(uint32_t index)1315   inline ValueType GetLocalType(uint32_t index) {
1316     return local_type_vec_[index];
1317   }
1318 
position()1319   inline WasmCodePosition position() {
1320     int offset = static_cast<int>(this->pc_ - this->start_);
1321     DCHECK_EQ(this->pc_ - this->start_, offset);  // overflows cannot happen
1322     return offset;
1323   }
1324 
control_depth()1325   inline uint32_t control_depth() const {
1326     return static_cast<uint32_t>(control_.size());
1327   }
1328 
control_at(uint32_t depth)1329   inline Control* control_at(uint32_t depth) {
1330     DCHECK_GT(control_.size(), depth);
1331     return &control_.back() - depth;
1332   }
1333 
stack_size()1334   inline uint32_t stack_size() const {
1335     DCHECK_GE(kMaxUInt32, stack_.size());
1336     return static_cast<uint32_t>(stack_.size());
1337   }
1338 
stack_value(uint32_t depth)1339   inline Value* stack_value(uint32_t depth) {
1340     DCHECK_GT(stack_.size(), depth);
1341     return &stack_[stack_.size() - depth - 1];
1342   }
1343 
GetMergeValueFromStack(Control * c,Merge<Value> * merge,uint32_t i)1344   inline Value& GetMergeValueFromStack(
1345       Control* c, Merge<Value>* merge, uint32_t i) {
1346     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
1347     DCHECK_GT(merge->arity, i);
1348     DCHECK_GE(stack_.size(), c->stack_depth + merge->arity);
1349     return stack_[stack_.size() - merge->arity + i];
1350   }
1351 
1352  private:
1353   static constexpr size_t kErrorMsgSize = 128;
1354 
1355   Zone* zone_;
1356 
1357   Interface interface_;
1358 
1359   ZoneVector<ValueType> local_type_vec_;  // types of local variables.
1360   ZoneVector<Value> stack_;               // stack of values.
1361   ZoneVector<Control> control_;           // stack of blocks, loops, and ifs.
1362   ZoneVector<Value> args_;                // parameters of current block or call
1363   bool last_end_found_;
1364 
CheckHasMemory()1365   bool CheckHasMemory() {
1366     if (!VALIDATE(this->module_->has_memory)) {
1367       this->error(this->pc_ - 1, "memory instruction with no memory");
1368       return false;
1369     }
1370     return true;
1371   }
1372 
CheckHasSharedMemory()1373   bool CheckHasSharedMemory() {
1374     if (!VALIDATE(this->module_->has_shared_memory)) {
1375       this->error(this->pc_ - 1, "Atomic opcodes used without shared memory");
1376       return false;
1377     }
1378     return true;
1379   }
1380 
1381   class TraceLine {
1382    public:
1383     static constexpr int kMaxLen = 512;
~TraceLine()1384     ~TraceLine() {
1385       if (!FLAG_trace_wasm_decoder) return;
1386       PrintF("%.*s\n", len_, buffer_);
1387     }
1388 
1389     // Appends a formatted string.
1390     PRINTF_FORMAT(2, 3)
Append(const char * format,...)1391     void Append(const char* format, ...) {
1392       if (!FLAG_trace_wasm_decoder) return;
1393       va_list va_args;
1394       va_start(va_args, format);
1395       size_t remaining_len = kMaxLen - len_;
1396       Vector<char> remaining_msg_space(buffer_ + len_, remaining_len);
1397       int len = VSNPrintF(remaining_msg_space, format, va_args);
1398       va_end(va_args);
1399       len_ += len < 0 ? remaining_len : len;
1400     }
1401 
1402    private:
1403     char buffer_[kMaxLen];
1404     int len_ = 0;
1405   };
1406 
1407   // Decodes the body of a function.
DecodeFunctionBody()1408   void DecodeFunctionBody() {
1409     TRACE("wasm-decode %p...%p (module+%u, %d bytes)\n",
1410           reinterpret_cast<const void*>(this->start()),
1411           reinterpret_cast<const void*>(this->end()), this->pc_offset(),
1412           static_cast<int>(this->end() - this->start()));
1413 
1414     // Set up initial function block.
1415     {
1416       auto* c = PushBlock();
1417       InitMerge(&c->start_merge, 0, [](uint32_t) -> Value { UNREACHABLE(); });
1418       InitMerge(&c->end_merge,
1419                 static_cast<uint32_t>(this->sig_->return_count()),
1420                 [&] (uint32_t i) {
1421                     return Value::New(this->pc_, this->sig_->GetReturn(i)); });
1422       CALL_INTERFACE(StartFunctionBody, c);
1423     }
1424 
1425     while (this->pc_ < this->end_) {  // decoding loop.
1426       unsigned len = 1;
1427       WasmOpcode opcode = static_cast<WasmOpcode>(*this->pc_);
1428 
1429       CALL_INTERFACE_IF_REACHABLE(NextInstruction, opcode);
1430 
1431 #if DEBUG
1432       TraceLine trace_msg;
1433 #define TRACE_PART(...) trace_msg.Append(__VA_ARGS__)
1434       if (!WasmOpcodes::IsPrefixOpcode(opcode)) {
1435         TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
1436                    WasmOpcodes::OpcodeName(opcode));
1437       }
1438 #else
1439 #define TRACE_PART(...)
1440 #endif
1441 
1442       FunctionSig* sig = const_cast<FunctionSig*>(kSimpleOpcodeSigs[opcode]);
1443       if (sig) {
1444         BuildSimpleOperator(opcode, sig);
1445       } else {
1446         // Complex bytecode.
1447         switch (opcode) {
1448           case kExprNop:
1449             break;
1450           case kExprBlock: {
1451             BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
1452             if (!this->Validate(imm)) break;
1453             PopArgs(imm.sig);
1454             auto* block = PushBlock();
1455             SetBlockType(block, imm);
1456             CALL_INTERFACE_IF_REACHABLE(Block, block);
1457             PushMergeValues(block, &block->start_merge);
1458             len = 1 + imm.length;
1459             break;
1460           }
1461           case kExprRethrow: {
1462             // TODO(kschimpf): Implement.
1463             CHECK_PROTOTYPE_OPCODE(eh);
1464             OPCODE_ERROR(opcode, "not implemented yet");
1465             break;
1466           }
1467           case kExprThrow: {
1468             CHECK_PROTOTYPE_OPCODE(eh);
1469             ExceptionIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
1470             len = 1 + imm.length;
1471             if (!this->Validate(this->pc_, imm)) break;
1472             PopArgs(imm.exception->ToFunctionSig());
1473             CALL_INTERFACE_IF_REACHABLE(Throw, imm, &control_.back(),
1474                                         vec2vec(args_));
1475             EndControl();
1476             break;
1477           }
1478           case kExprTry: {
1479             CHECK_PROTOTYPE_OPCODE(eh);
1480             BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
1481             if (!this->Validate(imm)) break;
1482             PopArgs(imm.sig);
1483             auto* try_block = PushTry();
1484             SetBlockType(try_block, imm);
1485             len = 1 + imm.length;
1486             CALL_INTERFACE_IF_REACHABLE(Try, try_block);
1487             PushMergeValues(try_block, &try_block->start_merge);
1488             break;
1489           }
1490           case kExprCatch: {
1491             // TODO(kschimpf): Fix to use type signature of exception.
1492             CHECK_PROTOTYPE_OPCODE(eh);
1493             ExceptionIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
1494             len = 1 + imm.length;
1495 
1496             if (!this->Validate(this->pc_, imm)) break;
1497 
1498             if (!VALIDATE(!control_.empty())) {
1499               this->error("catch does not match any try");
1500               break;
1501             }
1502 
1503             Control* c = &control_.back();
1504             if (!VALIDATE(c->is_try())) {
1505               this->error("catch does not match any try");
1506               break;
1507             }
1508 
1509             if (!VALIDATE(c->is_incomplete_try())) {
1510               OPCODE_ERROR(opcode, "multiple catch blocks not implemented");
1511               break;
1512             }
1513             c->kind = kControlTryCatch;
1514             FallThruTo(c);
1515             stack_.resize(c->stack_depth);
1516             const WasmExceptionSig* sig = imm.exception->sig;
1517             for (size_t i = 0, e = sig->parameter_count(); i < e; ++i) {
1518               Push(sig->GetParam(i));
1519             }
1520             Vector<Value> values(stack_.data() + c->stack_depth,
1521                                  sig->parameter_count());
1522             CALL_INTERFACE_IF_PARENT_REACHABLE(CatchException, imm, c, values);
1523             c->reachability = control_at(1)->innerReachability();
1524             break;
1525           }
1526           case kExprCatchAll: {
1527             // TODO(kschimpf): Implement.
1528             CHECK_PROTOTYPE_OPCODE(eh);
1529             OPCODE_ERROR(opcode, "not implemented yet");
1530             break;
1531           }
1532           case kExprLoop: {
1533             BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
1534             if (!this->Validate(imm)) break;
1535             PopArgs(imm.sig);
1536             auto* block = PushLoop();
1537             SetBlockType(&control_.back(), imm);
1538             len = 1 + imm.length;
1539             CALL_INTERFACE_IF_REACHABLE(Loop, block);
1540             PushMergeValues(block, &block->start_merge);
1541             break;
1542           }
1543           case kExprIf: {
1544             BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
1545             if (!this->Validate(imm)) break;
1546             auto cond = Pop(0, kWasmI32);
1547             PopArgs(imm.sig);
1548             if (!VALIDATE(this->ok())) break;
1549             auto* if_block = PushIf();
1550             SetBlockType(if_block, imm);
1551             CALL_INTERFACE_IF_REACHABLE(If, cond, if_block);
1552             len = 1 + imm.length;
1553             PushMergeValues(if_block, &if_block->start_merge);
1554             break;
1555           }
1556           case kExprElse: {
1557             if (!VALIDATE(!control_.empty())) {
1558               this->error("else does not match any if");
1559               break;
1560             }
1561             Control* c = &control_.back();
1562             if (!VALIDATE(c->is_if())) {
1563               this->error(this->pc_, "else does not match an if");
1564               break;
1565             }
1566             if (c->is_if_else()) {
1567               this->error(this->pc_, "else already present for if");
1568               break;
1569             }
1570             FallThruTo(c);
1571             c->kind = kControlIfElse;
1572             CALL_INTERFACE_IF_PARENT_REACHABLE(Else, c);
1573             PushMergeValues(c, &c->start_merge);
1574             c->reachability = control_at(1)->innerReachability();
1575             break;
1576           }
1577           case kExprEnd: {
1578             if (!VALIDATE(!control_.empty())) {
1579               this->error("end does not match any if, try, or block");
1580               return;
1581             }
1582             Control* c = &control_.back();
1583             if (!VALIDATE(!c->is_incomplete_try())) {
1584               this->error(this->pc_, "missing catch in try");
1585               break;
1586             }
1587             if (c->is_onearmed_if()) {
1588               // Emulate empty else arm.
1589               FallThruTo(c);
1590               if (this->failed()) break;
1591               CALL_INTERFACE_IF_PARENT_REACHABLE(Else, c);
1592               PushMergeValues(c, &c->start_merge);
1593               c->reachability = control_at(1)->innerReachability();
1594             }
1595 
1596             FallThruTo(c);
1597             // A loop just leaves the values on the stack.
1598             if (!c->is_loop()) PushMergeValues(c, &c->end_merge);
1599 
1600             if (control_.size() == 1) {
1601               // If at the last (implicit) control, check we are at end.
1602               if (!VALIDATE(this->pc_ + 1 == this->end_)) {
1603                 this->error(this->pc_ + 1, "trailing code after function end");
1604                 break;
1605               }
1606               last_end_found_ = true;
1607               // The result of the block is the return value.
1608               TRACE_PART("\n" TRACE_INST_FORMAT, startrel(this->pc_),
1609                          "(implicit) return");
1610               DoReturn(c, true);
1611             }
1612 
1613             PopControl(c);
1614             break;
1615           }
1616           case kExprSelect: {
1617             auto cond = Pop(2, kWasmI32);
1618             auto fval = Pop();
1619             auto tval = Pop(0, fval.type);
1620             auto* result = Push(tval.type == kWasmVar ? fval.type : tval.type);
1621             CALL_INTERFACE_IF_REACHABLE(Select, cond, fval, tval, result);
1622             break;
1623           }
1624           case kExprBr: {
1625             BreakDepthImmediate<validate> imm(this, this->pc_);
1626             if (!this->Validate(this->pc_, imm, control_.size())) break;
1627             Control* c = control_at(imm.depth);
1628             if (!TypeCheckBreak(c)) break;
1629             if (control_.back().reachable()) {
1630               CALL_INTERFACE(Br, c);
1631               c->br_merge()->reached = true;
1632             }
1633             len = 1 + imm.length;
1634             EndControl();
1635             break;
1636           }
1637           case kExprBrIf: {
1638             BreakDepthImmediate<validate> imm(this, this->pc_);
1639             auto cond = Pop(0, kWasmI32);
1640             if (this->failed()) break;
1641             if (!this->Validate(this->pc_, imm, control_.size())) break;
1642             Control* c = control_at(imm.depth);
1643             if (!TypeCheckBreak(c)) break;
1644             if (control_.back().reachable()) {
1645               CALL_INTERFACE(BrIf, cond, c);
1646               c->br_merge()->reached = true;
1647             }
1648             len = 1 + imm.length;
1649             break;
1650           }
1651           case kExprBrTable: {
1652             BranchTableImmediate<validate> imm(this, this->pc_);
1653             BranchTableIterator<validate> iterator(this, imm);
1654             auto key = Pop(0, kWasmI32);
1655             if (this->failed()) break;
1656             if (!this->Validate(this->pc_, imm, control_.size())) break;
1657             uint32_t br_arity = 0;
1658             std::vector<bool> br_targets(control_.size());
1659             while (iterator.has_next()) {
1660               const uint32_t i = iterator.cur_index();
1661               const byte* pos = iterator.pc();
1662               uint32_t target = iterator.next();
1663               if (!VALIDATE(target < control_.size())) {
1664                 this->errorf(pos,
1665                              "improper branch in br_table target %u (depth %u)",
1666                              i, target);
1667                 break;
1668               }
1669               // Avoid redundant break target checks.
1670               if (br_targets[target]) continue;
1671               br_targets[target] = true;
1672               // Check that label types match up.
1673               Control* c = control_at(target);
1674               uint32_t arity = c->br_merge()->arity;
1675               if (i == 0) {
1676                 br_arity = arity;
1677               } else if (!VALIDATE(br_arity == arity)) {
1678                 this->errorf(pos,
1679                              "inconsistent arity in br_table target %u"
1680                              " (previous was %u, this one %u)",
1681                              i, br_arity, arity);
1682               }
1683               if (!TypeCheckBreak(c)) break;
1684             }
1685             if (this->failed()) break;
1686 
1687             if (control_.back().reachable()) {
1688               CALL_INTERFACE(BrTable, imm, key);
1689 
1690               for (uint32_t depth = control_depth(); depth-- > 0;) {
1691                 if (!br_targets[depth]) continue;
1692                 control_at(depth)->br_merge()->reached = true;
1693               }
1694             }
1695 
1696             len = 1 + iterator.length();
1697             EndControl();
1698             break;
1699           }
1700           case kExprReturn: {
1701             DoReturn(&control_.back(), false);
1702             break;
1703           }
1704           case kExprUnreachable: {
1705             CALL_INTERFACE_IF_REACHABLE(Unreachable);
1706             EndControl();
1707             break;
1708           }
1709           case kExprI32Const: {
1710             ImmI32Immediate<validate> imm(this, this->pc_);
1711             auto* value = Push(kWasmI32);
1712             CALL_INTERFACE_IF_REACHABLE(I32Const, value, imm.value);
1713             len = 1 + imm.length;
1714             break;
1715           }
1716           case kExprI64Const: {
1717             ImmI64Immediate<validate> imm(this, this->pc_);
1718             auto* value = Push(kWasmI64);
1719             CALL_INTERFACE_IF_REACHABLE(I64Const, value, imm.value);
1720             len = 1 + imm.length;
1721             break;
1722           }
1723           case kExprF32Const: {
1724             ImmF32Immediate<validate> imm(this, this->pc_);
1725             auto* value = Push(kWasmF32);
1726             CALL_INTERFACE_IF_REACHABLE(F32Const, value, imm.value);
1727             len = 1 + imm.length;
1728             break;
1729           }
1730           case kExprF64Const: {
1731             ImmF64Immediate<validate> imm(this, this->pc_);
1732             auto* value = Push(kWasmF64);
1733             CALL_INTERFACE_IF_REACHABLE(F64Const, value, imm.value);
1734             len = 1 + imm.length;
1735             break;
1736           }
1737           case kExprRefNull: {
1738             CHECK_PROTOTYPE_OPCODE(anyref);
1739             auto* value = Push(kWasmAnyRef);
1740             CALL_INTERFACE_IF_REACHABLE(RefNull, value);
1741             len = 1;
1742             break;
1743           }
1744           case kExprGetLocal: {
1745             LocalIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
1746             if (!this->Validate(this->pc_, imm)) break;
1747             auto* value = Push(imm.type);
1748             CALL_INTERFACE_IF_REACHABLE(GetLocal, value, imm);
1749             len = 1 + imm.length;
1750             break;
1751           }
1752           case kExprSetLocal: {
1753             LocalIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
1754             if (!this->Validate(this->pc_, imm)) break;
1755             auto value = Pop(0, local_type_vec_[imm.index]);
1756             CALL_INTERFACE_IF_REACHABLE(SetLocal, value, imm);
1757             len = 1 + imm.length;
1758             break;
1759           }
1760           case kExprTeeLocal: {
1761             LocalIndexImmediate<Decoder::kValidate> imm(this, this->pc_);
1762             if (!this->Validate(this->pc_, imm)) break;
1763             auto value = Pop(0, local_type_vec_[imm.index]);
1764             auto* result = Push(value.type);
1765             CALL_INTERFACE_IF_REACHABLE(TeeLocal, value, result, imm);
1766             len = 1 + imm.length;
1767             break;
1768           }
1769           case kExprDrop: {
1770             auto value = Pop();
1771             CALL_INTERFACE_IF_REACHABLE(Drop, value);
1772             break;
1773           }
1774           case kExprGetGlobal: {
1775             GlobalIndexImmediate<validate> imm(this, this->pc_);
1776             len = 1 + imm.length;
1777             if (!this->Validate(this->pc_, imm)) break;
1778             auto* result = Push(imm.type);
1779             CALL_INTERFACE_IF_REACHABLE(GetGlobal, result, imm);
1780             break;
1781           }
1782           case kExprSetGlobal: {
1783             GlobalIndexImmediate<validate> imm(this, this->pc_);
1784             len = 1 + imm.length;
1785             if (!this->Validate(this->pc_, imm)) break;
1786             if (!VALIDATE(imm.global->mutability)) {
1787               this->errorf(this->pc_, "immutable global #%u cannot be assigned",
1788                            imm.index);
1789               break;
1790             }
1791             auto value = Pop(0, imm.type);
1792             CALL_INTERFACE_IF_REACHABLE(SetGlobal, value, imm);
1793             break;
1794           }
1795           case kExprI32LoadMem8S:
1796             len = 1 + DecodeLoadMem(LoadType::kI32Load8S);
1797             break;
1798           case kExprI32LoadMem8U:
1799             len = 1 + DecodeLoadMem(LoadType::kI32Load8U);
1800             break;
1801           case kExprI32LoadMem16S:
1802             len = 1 + DecodeLoadMem(LoadType::kI32Load16S);
1803             break;
1804           case kExprI32LoadMem16U:
1805             len = 1 + DecodeLoadMem(LoadType::kI32Load16U);
1806             break;
1807           case kExprI32LoadMem:
1808             len = 1 + DecodeLoadMem(LoadType::kI32Load);
1809             break;
1810           case kExprI64LoadMem8S:
1811             len = 1 + DecodeLoadMem(LoadType::kI64Load8S);
1812             break;
1813           case kExprI64LoadMem8U:
1814             len = 1 + DecodeLoadMem(LoadType::kI64Load8U);
1815             break;
1816           case kExprI64LoadMem16S:
1817             len = 1 + DecodeLoadMem(LoadType::kI64Load16S);
1818             break;
1819           case kExprI64LoadMem16U:
1820             len = 1 + DecodeLoadMem(LoadType::kI64Load16U);
1821             break;
1822           case kExprI64LoadMem32S:
1823             len = 1 + DecodeLoadMem(LoadType::kI64Load32S);
1824             break;
1825           case kExprI64LoadMem32U:
1826             len = 1 + DecodeLoadMem(LoadType::kI64Load32U);
1827             break;
1828           case kExprI64LoadMem:
1829             len = 1 + DecodeLoadMem(LoadType::kI64Load);
1830             break;
1831           case kExprF32LoadMem:
1832             len = 1 + DecodeLoadMem(LoadType::kF32Load);
1833             break;
1834           case kExprF64LoadMem:
1835             len = 1 + DecodeLoadMem(LoadType::kF64Load);
1836             break;
1837           case kExprI32StoreMem8:
1838             len = 1 + DecodeStoreMem(StoreType::kI32Store8);
1839             break;
1840           case kExprI32StoreMem16:
1841             len = 1 + DecodeStoreMem(StoreType::kI32Store16);
1842             break;
1843           case kExprI32StoreMem:
1844             len = 1 + DecodeStoreMem(StoreType::kI32Store);
1845             break;
1846           case kExprI64StoreMem8:
1847             len = 1 + DecodeStoreMem(StoreType::kI64Store8);
1848             break;
1849           case kExprI64StoreMem16:
1850             len = 1 + DecodeStoreMem(StoreType::kI64Store16);
1851             break;
1852           case kExprI64StoreMem32:
1853             len = 1 + DecodeStoreMem(StoreType::kI64Store32);
1854             break;
1855           case kExprI64StoreMem:
1856             len = 1 + DecodeStoreMem(StoreType::kI64Store);
1857             break;
1858           case kExprF32StoreMem:
1859             len = 1 + DecodeStoreMem(StoreType::kF32Store);
1860             break;
1861           case kExprF64StoreMem:
1862             len = 1 + DecodeStoreMem(StoreType::kF64Store);
1863             break;
1864           case kExprGrowMemory: {
1865             if (!CheckHasMemory()) break;
1866             MemoryIndexImmediate<validate> imm(this, this->pc_);
1867             len = 1 + imm.length;
1868             DCHECK_NOT_NULL(this->module_);
1869             if (!VALIDATE(this->module_->origin == kWasmOrigin)) {
1870               this->error("grow_memory is not supported for asmjs modules");
1871               break;
1872             }
1873             auto value = Pop(0, kWasmI32);
1874             auto* result = Push(kWasmI32);
1875             CALL_INTERFACE_IF_REACHABLE(GrowMemory, value, result);
1876             break;
1877           }
1878           case kExprMemorySize: {
1879             if (!CheckHasMemory()) break;
1880             MemoryIndexImmediate<validate> imm(this, this->pc_);
1881             auto* result = Push(kWasmI32);
1882             len = 1 + imm.length;
1883             CALL_INTERFACE_IF_REACHABLE(CurrentMemoryPages, result);
1884             break;
1885           }
1886           case kExprCallFunction: {
1887             CallFunctionImmediate<validate> imm(this, this->pc_);
1888             len = 1 + imm.length;
1889             if (!this->Validate(this->pc_, imm)) break;
1890             // TODO(clemensh): Better memory management.
1891             PopArgs(imm.sig);
1892             auto* returns = PushReturns(imm.sig);
1893             CALL_INTERFACE_IF_REACHABLE(CallDirect, imm, args_.data(), returns);
1894             break;
1895           }
1896           case kExprCallIndirect: {
1897             CallIndirectImmediate<validate> imm(this, this->pc_);
1898             len = 1 + imm.length;
1899             if (!this->Validate(this->pc_, imm)) break;
1900             auto index = Pop(0, kWasmI32);
1901             PopArgs(imm.sig);
1902             auto* returns = PushReturns(imm.sig);
1903             CALL_INTERFACE_IF_REACHABLE(CallIndirect, index, imm, args_.data(),
1904                                         returns);
1905             break;
1906           }
1907           case kNumericPrefix: {
1908             CHECK_PROTOTYPE_OPCODE(sat_f2i_conversions);
1909             ++len;
1910             byte numeric_index = this->template read_u8<validate>(
1911                 this->pc_ + 1, "numeric index");
1912             opcode = static_cast<WasmOpcode>(opcode << 8 | numeric_index);
1913             TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
1914                        WasmOpcodes::OpcodeName(opcode));
1915             sig = WasmOpcodes::Signature(opcode);
1916             if (sig == nullptr) {
1917               this->errorf(this->pc_, "Unrecognized numeric opcode: %x\n",
1918                            opcode);
1919               return;
1920             }
1921             BuildSimpleOperator(opcode, sig);
1922             break;
1923           }
1924           case kSimdPrefix: {
1925             CHECK_PROTOTYPE_OPCODE(simd);
1926             len++;
1927             byte simd_index =
1928                 this->template read_u8<validate>(this->pc_ + 1, "simd index");
1929             opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
1930             TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
1931                        WasmOpcodes::OpcodeName(opcode));
1932             len += DecodeSimdOpcode(opcode);
1933             break;
1934           }
1935           case kAtomicPrefix: {
1936             CHECK_PROTOTYPE_OPCODE(threads);
1937             if (!CheckHasSharedMemory()) break;
1938             len++;
1939             byte atomic_index =
1940                 this->template read_u8<validate>(this->pc_ + 1, "atomic index");
1941             opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_index);
1942             TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
1943                        WasmOpcodes::OpcodeName(opcode));
1944             len += DecodeAtomicOpcode(opcode);
1945             break;
1946           }
1947 // Note that prototype opcodes are not handled in the fastpath
1948 // above this switch, to avoid checking a feature flag.
1949 #define SIMPLE_PROTOTYPE_CASE(name, opc, sig) \
1950   case kExpr##name: /* fallthrough */
1951             FOREACH_SIMPLE_PROTOTYPE_OPCODE(SIMPLE_PROTOTYPE_CASE)
1952 #undef SIMPLE_PROTOTYPE_CASE
1953             BuildSimplePrototypeOperator(opcode);
1954             break;
1955           default: {
1956             // Deal with special asmjs opcodes.
1957             if (this->module_ != nullptr &&
1958                 this->module_->origin == kAsmJsOrigin) {
1959               sig = WasmOpcodes::AsmjsSignature(opcode);
1960               if (sig) {
1961                 BuildSimpleOperator(opcode, sig);
1962               }
1963             } else {
1964               this->error("Invalid opcode");
1965               return;
1966             }
1967           }
1968         }
1969       }
1970 
1971 #if DEBUG
1972       if (FLAG_trace_wasm_decoder) {
1973         TRACE_PART(" ");
1974         for (Control& c : control_) {
1975           switch (c.kind) {
1976             case kControlIf:
1977               TRACE_PART("I");
1978               break;
1979             case kControlBlock:
1980               TRACE_PART("B");
1981               break;
1982             case kControlLoop:
1983               TRACE_PART("L");
1984               break;
1985             case kControlTry:
1986               TRACE_PART("T");
1987               break;
1988             default:
1989               break;
1990           }
1991           if (c.start_merge.arity) TRACE_PART("%u-", c.start_merge.arity);
1992           TRACE_PART("%u", c.end_merge.arity);
1993           if (!c.reachable()) TRACE_PART("%c", c.unreachable() ? '*' : '#');
1994         }
1995         TRACE_PART(" | ");
1996         for (size_t i = 0; i < stack_.size(); ++i) {
1997           auto& val = stack_[i];
1998           WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
1999           if (WasmOpcodes::IsPrefixOpcode(opcode)) {
2000             opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1));
2001           }
2002           TRACE_PART(" %c@%d:%s", ValueTypes::ShortNameOf(val.type),
2003                      static_cast<int>(val.pc - this->start_),
2004                      WasmOpcodes::OpcodeName(opcode));
2005           // If the decoder failed, don't try to decode the immediates, as this
2006           // can trigger a DCHECK failure.
2007           if (this->failed()) continue;
2008           switch (opcode) {
2009             case kExprI32Const: {
2010               ImmI32Immediate<Decoder::kNoValidate> imm(this, val.pc);
2011               TRACE_PART("[%d]", imm.value);
2012               break;
2013             }
2014             case kExprGetLocal:
2015             case kExprSetLocal:
2016             case kExprTeeLocal: {
2017               LocalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
2018               TRACE_PART("[%u]", imm.index);
2019               break;
2020             }
2021             case kExprGetGlobal:
2022             case kExprSetGlobal: {
2023               GlobalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
2024               TRACE_PART("[%u]", imm.index);
2025               break;
2026             }
2027             default:
2028               break;
2029           }
2030         }
2031       }
2032 #endif
2033       this->pc_ += len;
2034     }  // end decode loop
2035     if (!VALIDATE(this->pc_ == this->end_) && this->ok()) {
2036       this->error("Beyond end of code");
2037     }
2038   }
2039 
EndControl()2040   void EndControl() {
2041     DCHECK(!control_.empty());
2042     auto* current = &control_.back();
2043     stack_.resize(current->stack_depth);
2044     CALL_INTERFACE_IF_REACHABLE(EndControl, current);
2045     current->reachability = kUnreachable;
2046   }
2047 
2048   template<typename func>
InitMerge(Merge<Value> * merge,uint32_t arity,func get_val)2049   void InitMerge(Merge<Value>* merge, uint32_t arity, func get_val) {
2050     merge->arity = arity;
2051     if (arity == 1) {
2052       merge->vals.first = get_val(0);
2053     } else if (arity > 1) {
2054       merge->vals.array = zone_->NewArray<Value>(arity);
2055       for (unsigned i = 0; i < arity; i++) {
2056         merge->vals.array[i] = get_val(i);
2057       }
2058     }
2059   }
2060 
SetBlockType(Control * c,BlockTypeImmediate<validate> & imm)2061   void SetBlockType(Control* c, BlockTypeImmediate<validate>& imm) {
2062     DCHECK_EQ(imm.in_arity(), this->args_.size());
2063     const byte* pc = this->pc_;
2064     Value* args = this->args_.data();
2065     InitMerge(&c->end_merge, imm.out_arity(), [pc, &imm](uint32_t i) {
2066       return Value::New(pc, imm.out_type(i));
2067     });
2068     InitMerge(&c->start_merge, imm.in_arity(),
2069               [args](uint32_t i) { return args[i]; });
2070   }
2071 
2072   // Pops arguments as required by signature into {args_}.
PopArgs(FunctionSig * sig)2073   V8_INLINE void PopArgs(FunctionSig* sig) {
2074     int count = sig ? static_cast<int>(sig->parameter_count()) : 0;
2075     args_.resize(count);
2076     for (int i = count - 1; i >= 0; --i) {
2077       args_[i] = Pop(i, sig->GetParam(i));
2078     }
2079   }
2080 
GetReturnType(FunctionSig * sig)2081   ValueType GetReturnType(FunctionSig* sig) {
2082     DCHECK_GE(1, sig->return_count());
2083     return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn();
2084   }
2085 
PushControl(Control && new_control)2086   Control* PushControl(Control&& new_control) {
2087     Reachability reachability =
2088         control_.empty() ? kReachable : control_.back().innerReachability();
2089     control_.emplace_back(std::move(new_control));
2090     Control* c = &control_.back();
2091     c->reachability = reachability;
2092     c->start_merge.reached = c->reachable();
2093     return c;
2094   }
2095 
PushBlock()2096   Control* PushBlock() {
2097     return PushControl(Control::Block(this->pc_, stack_size()));
2098   }
PushLoop()2099   Control* PushLoop() {
2100     return PushControl(Control::Loop(this->pc_, stack_size()));
2101   }
PushIf()2102   Control* PushIf() {
2103     return PushControl(Control::If(this->pc_, stack_size()));
2104   }
PushTry()2105   Control* PushTry() {
2106     // current_catch_ = static_cast<int32_t>(control_.size() - 1);
2107     return PushControl(Control::Try(this->pc_, stack_size()));
2108   }
2109 
PopControl(Control * c)2110   void PopControl(Control* c) {
2111     DCHECK_EQ(c, &control_.back());
2112     CALL_INTERFACE_IF_PARENT_REACHABLE(PopControl, c);
2113     bool reached = c->end_merge.reached;
2114     control_.pop_back();
2115     // If the parent block was reachable before, but the popped control does not
2116     // return to here, this block becomes indirectly unreachable.
2117     if (!control_.empty() && !reached && control_.back().reachable()) {
2118       control_.back().reachability = kSpecOnlyReachable;
2119     }
2120   }
2121 
2122   int DecodeLoadMem(LoadType type, int prefix_len = 0) {
2123     if (!CheckHasMemory()) return 0;
2124     MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
2125                                         type.size_log_2());
2126     auto index = Pop(0, kWasmI32);
2127     auto* result = Push(type.value_type());
2128     CALL_INTERFACE_IF_REACHABLE(LoadMem, type, imm, index, result);
2129     return imm.length;
2130   }
2131 
2132   int DecodeStoreMem(StoreType store, int prefix_len = 0) {
2133     if (!CheckHasMemory()) return 0;
2134     MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
2135                                         store.size_log_2());
2136     auto value = Pop(1, store.value_type());
2137     auto index = Pop(0, kWasmI32);
2138     CALL_INTERFACE_IF_REACHABLE(StoreMem, store, imm, index, value);
2139     return imm.length;
2140   }
2141 
SimdExtractLane(WasmOpcode opcode,ValueType type)2142   unsigned SimdExtractLane(WasmOpcode opcode, ValueType type) {
2143     SimdLaneImmediate<validate> imm(this, this->pc_);
2144     if (this->Validate(this->pc_, opcode, imm)) {
2145       Value inputs[] = {Pop(0, kWasmS128)};
2146       auto* result = Push(type);
2147       CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
2148                                   result);
2149     }
2150     return imm.length;
2151   }
2152 
SimdReplaceLane(WasmOpcode opcode,ValueType type)2153   unsigned SimdReplaceLane(WasmOpcode opcode, ValueType type) {
2154     SimdLaneImmediate<validate> imm(this, this->pc_);
2155     if (this->Validate(this->pc_, opcode, imm)) {
2156       Value inputs[2];
2157       inputs[1] = Pop(1, type);
2158       inputs[0] = Pop(0, kWasmS128);
2159       auto* result = Push(kWasmS128);
2160       CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
2161                                   result);
2162     }
2163     return imm.length;
2164   }
2165 
SimdShiftOp(WasmOpcode opcode)2166   unsigned SimdShiftOp(WasmOpcode opcode) {
2167     SimdShiftImmediate<validate> imm(this, this->pc_);
2168     if (this->Validate(this->pc_, opcode, imm)) {
2169       auto input = Pop(0, kWasmS128);
2170       auto* result = Push(kWasmS128);
2171       CALL_INTERFACE_IF_REACHABLE(SimdShiftOp, opcode, imm, input, result);
2172     }
2173     return imm.length;
2174   }
2175 
Simd8x16ShuffleOp()2176   unsigned Simd8x16ShuffleOp() {
2177     Simd8x16ShuffleImmediate<validate> imm(this, this->pc_);
2178     if (this->Validate(this->pc_, imm)) {
2179       auto input1 = Pop(1, kWasmS128);
2180       auto input0 = Pop(0, kWasmS128);
2181       auto* result = Push(kWasmS128);
2182       CALL_INTERFACE_IF_REACHABLE(Simd8x16ShuffleOp, imm, input0, input1,
2183                                   result);
2184     }
2185     return 16;
2186   }
2187 
DecodeSimdOpcode(WasmOpcode opcode)2188   unsigned DecodeSimdOpcode(WasmOpcode opcode) {
2189     unsigned len = 0;
2190     switch (opcode) {
2191       case kExprF32x4ExtractLane: {
2192         len = SimdExtractLane(opcode, kWasmF32);
2193         break;
2194       }
2195       case kExprI32x4ExtractLane:
2196       case kExprI16x8ExtractLane:
2197       case kExprI8x16ExtractLane: {
2198         len = SimdExtractLane(opcode, kWasmI32);
2199         break;
2200       }
2201       case kExprF32x4ReplaceLane: {
2202         len = SimdReplaceLane(opcode, kWasmF32);
2203         break;
2204       }
2205       case kExprI32x4ReplaceLane:
2206       case kExprI16x8ReplaceLane:
2207       case kExprI8x16ReplaceLane: {
2208         len = SimdReplaceLane(opcode, kWasmI32);
2209         break;
2210       }
2211       case kExprI32x4Shl:
2212       case kExprI32x4ShrS:
2213       case kExprI32x4ShrU:
2214       case kExprI16x8Shl:
2215       case kExprI16x8ShrS:
2216       case kExprI16x8ShrU:
2217       case kExprI8x16Shl:
2218       case kExprI8x16ShrS:
2219       case kExprI8x16ShrU: {
2220         len = SimdShiftOp(opcode);
2221         break;
2222       }
2223       case kExprS8x16Shuffle: {
2224         len = Simd8x16ShuffleOp();
2225         break;
2226       }
2227       case kExprS128LoadMem:
2228         len = DecodeLoadMem(LoadType::kS128Load, 1);
2229         break;
2230       case kExprS128StoreMem:
2231         len = DecodeStoreMem(StoreType::kS128Store, 1);
2232         break;
2233       default: {
2234         FunctionSig* sig = WasmOpcodes::Signature(opcode);
2235         if (!VALIDATE(sig != nullptr)) {
2236           this->error("invalid simd opcode");
2237           break;
2238         }
2239         PopArgs(sig);
2240         auto* results =
2241             sig->return_count() == 0 ? nullptr : Push(GetReturnType(sig));
2242         CALL_INTERFACE_IF_REACHABLE(SimdOp, opcode, vec2vec(args_), results);
2243       }
2244     }
2245     return len;
2246   }
2247 
DecodeAtomicOpcode(WasmOpcode opcode)2248   unsigned DecodeAtomicOpcode(WasmOpcode opcode) {
2249     unsigned len = 0;
2250     ValueType ret_type;
2251     FunctionSig* sig = WasmOpcodes::Signature(opcode);
2252     if (sig != nullptr) {
2253       MachineType memtype;
2254       switch (opcode) {
2255 #define CASE_ATOMIC_STORE_OP(Name, Type) \
2256   case kExpr##Name: {                    \
2257     memtype = MachineType::Type();       \
2258     ret_type = kWasmStmt;                \
2259     break;                               \
2260   }
2261         ATOMIC_STORE_OP_LIST(CASE_ATOMIC_STORE_OP)
2262 #undef CASE_ATOMIC_OP
2263 #define CASE_ATOMIC_OP(Name, Type) \
2264   case kExpr##Name: {              \
2265     memtype = MachineType::Type(); \
2266     ret_type = GetReturnType(sig); \
2267     break;                         \
2268   }
2269         ATOMIC_OP_LIST(CASE_ATOMIC_OP)
2270 #undef CASE_ATOMIC_OP
2271         default:
2272           this->error("invalid atomic opcode");
2273           return 0;
2274       }
2275       MemoryAccessImmediate<validate> imm(
2276           this, this->pc_ + 1, ElementSizeLog2Of(memtype.representation()));
2277       len += imm.length;
2278       PopArgs(sig);
2279       auto result = ret_type == kWasmStmt ? nullptr : Push(GetReturnType(sig));
2280       CALL_INTERFACE_IF_REACHABLE(AtomicOp, opcode, vec2vec(args_), imm,
2281                                   result);
2282     } else {
2283       this->error("invalid atomic opcode");
2284     }
2285     return len;
2286   }
2287 
DoReturn(Control * c,bool implicit)2288   void DoReturn(Control* c, bool implicit) {
2289     int return_count = static_cast<int>(this->sig_->return_count());
2290     args_.resize(return_count);
2291 
2292     // Pop return values off the stack in reverse order.
2293     for (int i = return_count - 1; i >= 0; --i) {
2294       args_[i] = Pop(i, this->sig_->GetReturn(i));
2295     }
2296 
2297     // Simulate that an implicit return morally comes after the current block.
2298     if (implicit && c->end_merge.reached) c->reachability = kReachable;
2299     CALL_INTERFACE_IF_REACHABLE(DoReturn, vec2vec(args_), implicit);
2300 
2301     EndControl();
2302   }
2303 
Push(ValueType type)2304   inline Value* Push(ValueType type) {
2305     DCHECK_NE(kWasmStmt, type);
2306     stack_.push_back(Value::New(this->pc_, type));
2307     return &stack_.back();
2308   }
2309 
PushMergeValues(Control * c,Merge<Value> * merge)2310   void PushMergeValues(Control* c, Merge<Value>* merge) {
2311     DCHECK_EQ(c, &control_.back());
2312     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
2313     stack_.resize(c->stack_depth);
2314     if (merge->arity == 1) {
2315       stack_.push_back(merge->vals.first);
2316     } else {
2317       for (unsigned i = 0; i < merge->arity; i++) {
2318         stack_.push_back(merge->vals.array[i]);
2319       }
2320     }
2321     DCHECK_EQ(c->stack_depth + merge->arity, stack_.size());
2322   }
2323 
PushReturns(FunctionSig * sig)2324   Value* PushReturns(FunctionSig* sig) {
2325     size_t return_count = sig->return_count();
2326     if (return_count == 0) return nullptr;
2327     size_t old_size = stack_.size();
2328     for (size_t i = 0; i < return_count; ++i) {
2329       Push(sig->GetReturn(i));
2330     }
2331     return stack_.data() + old_size;
2332   }
2333 
Pop(int index,ValueType expected)2334   Value Pop(int index, ValueType expected) {
2335     auto val = Pop();
2336     if (!VALIDATE(val.type == expected || val.type == kWasmVar ||
2337                   expected == kWasmVar)) {
2338       this->errorf(val.pc, "%s[%d] expected type %s, found %s of type %s",
2339                    SafeOpcodeNameAt(this->pc_), index,
2340                    ValueTypes::TypeName(expected), SafeOpcodeNameAt(val.pc),
2341                    ValueTypes::TypeName(val.type));
2342     }
2343     return val;
2344   }
2345 
Pop()2346   Value Pop() {
2347     DCHECK(!control_.empty());
2348     uint32_t limit = control_.back().stack_depth;
2349     if (stack_.size() <= limit) {
2350       // Popping past the current control start in reachable code.
2351       if (!VALIDATE(control_.back().unreachable())) {
2352         this->errorf(this->pc_, "%s found empty stack",
2353                      SafeOpcodeNameAt(this->pc_));
2354       }
2355       return Value::Unreachable(this->pc_);
2356     }
2357     auto val = stack_.back();
2358     stack_.pop_back();
2359     return val;
2360   }
2361 
startrel(const byte * ptr)2362   int startrel(const byte* ptr) { return static_cast<int>(ptr - this->start_); }
2363 
FallThruTo(Control * c)2364   void FallThruTo(Control* c) {
2365     DCHECK_EQ(c, &control_.back());
2366     if (!TypeCheckFallThru(c)) return;
2367     if (!c->reachable()) return;
2368 
2369     if (!c->is_loop()) CALL_INTERFACE(FallThruTo, c);
2370     c->end_merge.reached = true;
2371   }
2372 
TypeCheckMergeValues(Control * c,Merge<Value> * merge)2373   bool TypeCheckMergeValues(Control* c, Merge<Value>* merge) {
2374     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
2375     DCHECK_GE(stack_.size(), c->stack_depth + merge->arity);
2376     // Typecheck the topmost {merge->arity} values on the stack.
2377     for (uint32_t i = 0; i < merge->arity; ++i) {
2378       auto& val = GetMergeValueFromStack(c, merge, i);
2379       auto& old = (*merge)[i];
2380       if (val.type != old.type) {
2381         // If {val.type} is polymorphic, which results from unreachable, make
2382         // it more specific by using the merge value's expected type.
2383         // If it is not polymorphic, this is a type error.
2384         if (!VALIDATE(val.type == kWasmVar)) {
2385           this->errorf(
2386               this->pc_, "type error in merge[%u] (expected %s, got %s)", i,
2387               ValueTypes::TypeName(old.type), ValueTypes::TypeName(val.type));
2388           return false;
2389         }
2390         val.type = old.type;
2391       }
2392     }
2393 
2394     return true;
2395   }
2396 
TypeCheckFallThru(Control * c)2397   bool TypeCheckFallThru(Control* c) {
2398     DCHECK_EQ(c, &control_.back());
2399     if (!validate) return true;
2400     uint32_t expected = c->end_merge.arity;
2401     DCHECK_GE(stack_.size(), c->stack_depth);
2402     uint32_t actual = static_cast<uint32_t>(stack_.size()) - c->stack_depth;
2403     // Fallthrus must match the arity of the control exactly.
2404     if (!InsertUnreachablesIfNecessary(expected, actual) || actual > expected) {
2405       this->errorf(
2406           this->pc_,
2407           "expected %u elements on the stack for fallthru to @%d, found %u",
2408           expected, startrel(c->pc), actual);
2409       return false;
2410     }
2411 
2412     return TypeCheckMergeValues(c, &c->end_merge);
2413   }
2414 
TypeCheckBreak(Control * c)2415   bool TypeCheckBreak(Control* c) {
2416     // Breaks must have at least the number of values expected; can have more.
2417     uint32_t expected = c->br_merge()->arity;
2418     DCHECK_GE(stack_.size(), control_.back().stack_depth);
2419     uint32_t actual =
2420         static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth;
2421     if (!InsertUnreachablesIfNecessary(expected, actual)) {
2422       this->errorf(this->pc_,
2423                    "expected %u elements on the stack for br to @%d, found %u",
2424                    expected, startrel(c->pc), actual);
2425       return false;
2426     }
2427     return TypeCheckMergeValues(c, c->br_merge());
2428   }
2429 
InsertUnreachablesIfNecessary(uint32_t expected,uint32_t actual)2430   inline bool InsertUnreachablesIfNecessary(uint32_t expected,
2431                                             uint32_t actual) {
2432     if (V8_LIKELY(actual >= expected)) {
2433       return true;  // enough actual values are there.
2434     }
2435     if (!VALIDATE(control_.back().unreachable())) {
2436       // There aren't enough values on the stack.
2437       return false;
2438     }
2439     // A slow path. When the actual number of values on the stack is less
2440     // than the expected number of values and the current control is
2441     // unreachable, insert unreachable values below the actual values.
2442     // This simplifies {TypeCheckMergeValues}.
2443     auto pos = stack_.begin() + (stack_.size() - actual);
2444     stack_.insert(pos, (expected - actual), Value::Unreachable(this->pc_));
2445     return true;
2446   }
2447 
onFirstError()2448   virtual void onFirstError() {
2449     this->end_ = this->pc_;  // Terminate decoding loop.
2450     TRACE(" !%s\n", this->error_msg_.c_str());
2451     CALL_INTERFACE(OnFirstError);
2452   }
2453 
BuildSimplePrototypeOperator(WasmOpcode opcode)2454   void BuildSimplePrototypeOperator(WasmOpcode opcode) {
2455     if (WasmOpcodes::IsSignExtensionOpcode(opcode)) {
2456       RET_ON_PROTOTYPE_OPCODE(se);
2457     }
2458     if (WasmOpcodes::IsAnyRefOpcode(opcode)) {
2459       RET_ON_PROTOTYPE_OPCODE(anyref);
2460     }
2461     FunctionSig* sig = WasmOpcodes::Signature(opcode);
2462     BuildSimpleOperator(opcode, sig);
2463   }
2464 
BuildSimpleOperator(WasmOpcode opcode,FunctionSig * sig)2465   inline void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
2466     switch (sig->parameter_count()) {
2467       case 1: {
2468         auto val = Pop(0, sig->GetParam(0));
2469         auto* ret =
2470             sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
2471         CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, sig, val, ret);
2472         break;
2473       }
2474       case 2: {
2475         auto rval = Pop(1, sig->GetParam(1));
2476         auto lval = Pop(0, sig->GetParam(0));
2477         auto* ret =
2478             sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
2479         CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, sig, lval, rval, ret);
2480         break;
2481       }
2482       default:
2483         UNREACHABLE();
2484     }
2485   }
2486 };
2487 
2488 #undef CALL_INTERFACE
2489 #undef CALL_INTERFACE_IF_REACHABLE
2490 #undef CALL_INTERFACE_IF_PARENT_REACHABLE
2491 
2492 class EmptyInterface {
2493  public:
2494   static constexpr Decoder::ValidateFlag validate = Decoder::kValidate;
2495   using Value = ValueBase;
2496   using Control = ControlBase<Value>;
2497   using FullDecoder = WasmFullDecoder<validate, EmptyInterface>;
2498 
2499 #define DEFINE_EMPTY_CALLBACK(name, ...) \
2500   void name(FullDecoder* decoder, ##__VA_ARGS__) {}
2501   INTERFACE_FUNCTIONS(DEFINE_EMPTY_CALLBACK)
2502 #undef DEFINE_EMPTY_CALLBACK
2503 };
2504 
2505 #undef TRACE
2506 #undef TRACE_INST_FORMAT
2507 #undef VALIDATE
2508 #undef CHECK_PROTOTYPE_OPCODE
2509 #undef OPCODE_ERROR
2510 
2511 }  // namespace wasm
2512 }  // namespace internal
2513 }  // namespace v8
2514 
2515 #endif  // V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
2516