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