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