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