Line data Source code
1 : // Copyright 2017 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
6 : #define V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
7 :
8 : // Do only include this header for implementing new Interface of the
9 : // WasmFullDecoder.
10 :
11 : #include "src/bit-vector.h"
12 : #include "src/wasm/decoder.h"
13 : #include "src/wasm/function-body-decoder.h"
14 : #include "src/wasm/wasm-limits.h"
15 : #include "src/wasm/wasm-module.h"
16 : #include "src/wasm/wasm-opcodes.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 : namespace wasm {
21 :
22 : struct WasmGlobal;
23 : struct WasmException;
24 :
25 : #if DEBUG
26 : #define TRACE(...) \
27 : do { \
28 : if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
29 : } while (false)
30 : #else
31 : #define TRACE(...)
32 : #endif
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 CHECK_PROTOTYPE_OPCODE(flag) \
43 : DCHECK(!this->module_ || !this->module_->is_asm_js()); \
44 : if (!FLAG_experimental_wasm_##flag) { \
45 : this->error("Invalid opcode (enable with --experimental-wasm-" #flag ")"); \
46 : break; \
47 : }
48 :
49 : #define OPCODE_ERROR(opcode, message) \
50 : (this->errorf(this->pc_, "%s: %s", WasmOpcodes::OpcodeName(opcode), \
51 : (message)))
52 :
53 : #define ATOMIC_OP_LIST(V) \
54 : V(I32AtomicLoad, Uint32) \
55 : V(I32AtomicAdd, Uint32) \
56 : V(I32AtomicSub, Uint32) \
57 : V(I32AtomicAnd, Uint32) \
58 : V(I32AtomicOr, Uint32) \
59 : V(I32AtomicXor, Uint32) \
60 : V(I32AtomicExchange, Uint32) \
61 : V(I32AtomicLoad8U, Uint8) \
62 : V(I32AtomicAdd8U, Uint8) \
63 : V(I32AtomicSub8U, Uint8) \
64 : V(I32AtomicAnd8U, Uint8) \
65 : V(I32AtomicOr8U, Uint8) \
66 : V(I32AtomicXor8U, Uint8) \
67 : V(I32AtomicExchange8U, Uint8) \
68 : V(I32AtomicLoad16U, Uint16) \
69 : V(I32AtomicAdd16U, Uint16) \
70 : V(I32AtomicSub16U, Uint16) \
71 : V(I32AtomicAnd16U, Uint16) \
72 : V(I32AtomicOr16U, Uint16) \
73 : V(I32AtomicXor16U, Uint16) \
74 : V(I32AtomicExchange16U, Uint16) \
75 : V(I32AtomicCompareExchange, Uint32) \
76 : V(I32AtomicCompareExchange8U, Uint8) \
77 : V(I32AtomicCompareExchange16U, Uint16)
78 :
79 : #define ATOMIC_STORE_OP_LIST(V) \
80 : V(I32AtomicStore, Uint32) \
81 : V(I32AtomicStore8U, Uint8) \
82 : V(I32AtomicStore16U, Uint16)
83 :
84 : template <typename T>
85 291841 : Vector<T> vec2vec(std::vector<T>& vec) {
86 : return Vector<T>(vec.data(), vec.size());
87 : }
88 :
89 : // Helpers for decoding different kinds of operands which follow bytecodes.
90 : template <Decoder::ValidateFlag validate>
91 : struct LocalIndexOperand {
92 : uint32_t index;
93 : ValueType type = kWasmStmt;
94 : unsigned length;
95 :
96 6854197 : inline LocalIndexOperand(Decoder* decoder, const byte* pc) {
97 13708410 : index = decoder->read_u32v<validate>(pc + 1, &length, "local index");
98 : }
99 : };
100 :
101 : template <Decoder::ValidateFlag validate>
102 : struct ExceptionIndexOperand {
103 : uint32_t index;
104 : const WasmException* exception = nullptr;
105 : unsigned length;
106 :
107 220 : inline ExceptionIndexOperand(Decoder* decoder, const byte* pc) {
108 440 : index = decoder->read_u32v<validate>(pc + 1, &length, "exception index");
109 : }
110 : };
111 :
112 : template <Decoder::ValidateFlag validate>
113 : struct ImmI32Operand {
114 : int32_t value;
115 : unsigned length;
116 : inline ImmI32Operand(Decoder* decoder, const byte* pc) {
117 4125290 : value = decoder->read_i32v<validate>(pc + 1, &length, "immi32");
118 : }
119 : };
120 :
121 : template <Decoder::ValidateFlag validate>
122 : struct ImmI64Operand {
123 : int64_t value;
124 : unsigned length;
125 : inline ImmI64Operand(Decoder* decoder, const byte* pc) {
126 198994 : value = decoder->read_i64v<validate>(pc + 1, &length, "immi64");
127 : }
128 : };
129 :
130 : template <Decoder::ValidateFlag validate>
131 : struct ImmF32Operand {
132 : float value;
133 : unsigned length = 4;
134 728563 : inline ImmF32Operand(Decoder* decoder, const byte* pc) {
135 : // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
136 1457126 : uint32_t tmp = decoder->read_u32<validate>(pc + 1, "immf32");
137 728563 : memcpy(&value, &tmp, sizeof(value));
138 728563 : }
139 : };
140 :
141 : template <Decoder::ValidateFlag validate>
142 : struct ImmF64Operand {
143 : double value;
144 : unsigned length = 8;
145 303622 : inline ImmF64Operand(Decoder* decoder, const byte* pc) {
146 : // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
147 607246 : uint64_t tmp = decoder->read_u64<validate>(pc + 1, "immf64");
148 303624 : memcpy(&value, &tmp, sizeof(value));
149 303624 : }
150 : };
151 :
152 : template <Decoder::ValidateFlag validate>
153 : struct GlobalIndexOperand {
154 : uint32_t index;
155 : ValueType type = kWasmStmt;
156 : const WasmGlobal* global = nullptr;
157 : unsigned length;
158 :
159 37383 : inline GlobalIndexOperand(Decoder* decoder, const byte* pc) {
160 74766 : index = decoder->read_u32v<validate>(pc + 1, &length, "global index");
161 36618 : }
162 : };
163 :
164 : template <Decoder::ValidateFlag validate>
165 : struct BlockTypeOperand {
166 : unsigned length = 1;
167 : ValueType type = kWasmStmt;
168 : uint32_t sig_index = 0;
169 : FunctionSig* sig = nullptr;
170 :
171 2421231 : inline BlockTypeOperand(Decoder* decoder, const byte* pc) {
172 2421231 : uint8_t val = decoder->read_u8<validate>(pc + 1, "block type");
173 2421236 : if (!decode_local_type(val, &type)) {
174 : // Handle multi-value blocks.
175 98 : if (!VALIDATE(FLAG_experimental_wasm_mv)) {
176 : decoder->error(pc + 1, "invalid block type");
177 : return;
178 : }
179 : int32_t index =
180 60652 : decoder->read_i32v<validate>(pc + 1, &length, "block arity");
181 64 : if (!VALIDATE(length > 0 && index >= 0)) {
182 : decoder->error(pc + 1, "invalid block type index");
183 : return;
184 : }
185 60652 : sig_index = static_cast<uint32_t>(index);
186 : }
187 : }
188 :
189 : // Decode a byte representing a local type. Return {false} if the encoded
190 : // byte was invalid or the start of a type index.
191 2421240 : inline bool decode_local_type(uint8_t val, ValueType* result) {
192 2421240 : switch (static_cast<ValueTypeCode>(val)) {
193 : case kLocalVoid:
194 2323056 : *result = kWasmStmt;
195 : return true;
196 : case kLocalI32:
197 32587 : *result = kWasmI32;
198 : return true;
199 : case kLocalI64:
200 553 : *result = kWasmI64;
201 : return true;
202 : case kLocalF32:
203 1996 : *result = kWasmF32;
204 : return true;
205 : case kLocalF64:
206 2362 : *result = kWasmF64;
207 : return true;
208 : case kLocalS128:
209 0 : *result = kWasmS128;
210 : return true;
211 : default:
212 60686 : *result = kWasmVar;
213 : return false;
214 : }
215 : }
216 :
217 : uint32_t in_arity() const {
218 220 : if (type != kWasmVar) return 0;
219 0 : return static_cast<uint32_t>(sig->parameter_count());
220 : }
221 : uint32_t out_arity() const {
222 527139 : if (type == kWasmStmt) return 0;
223 19706 : if (type != kWasmVar) return 1;
224 120 : return static_cast<uint32_t>(sig->return_count());
225 : }
226 : ValueType in_type(uint32_t index) {
227 : DCHECK_EQ(kWasmVar, type);
228 : return sig->GetParam(index);
229 : }
230 : ValueType out_type(uint32_t index) {
231 18446 : if (type == kWasmVar) return sig->GetReturn(index);
232 : DCHECK_NE(kWasmStmt, type);
233 : DCHECK_EQ(0, index);
234 : return type;
235 : }
236 : };
237 :
238 : template <Decoder::ValidateFlag validate>
239 : struct BreakDepthOperand {
240 : uint32_t depth;
241 : unsigned length;
242 : inline BreakDepthOperand(Decoder* decoder, const byte* pc) {
243 944808 : depth = decoder->read_u32v<validate>(pc + 1, &length, "break depth");
244 : }
245 : };
246 :
247 : template <Decoder::ValidateFlag validate>
248 : struct CallIndirectOperand {
249 : uint32_t table_index;
250 : uint32_t index;
251 : FunctionSig* sig = nullptr;
252 : unsigned length;
253 6051 : inline CallIndirectOperand(Decoder* decoder, const byte* pc) {
254 6051 : unsigned len = 0;
255 12102 : index = decoder->read_u32v<validate>(pc + 1, &len, "signature index");
256 11629 : table_index = decoder->read_u8<validate>(pc + 1 + len, "table index");
257 5578 : if (!VALIDATE(table_index == 0)) {
258 0 : decoder->errorf(pc + 1 + len, "expected table index 0, found %u",
259 0 : table_index);
260 : }
261 6051 : length = 1 + len;
262 6051 : }
263 : };
264 :
265 : template <Decoder::ValidateFlag validate>
266 : struct CallFunctionOperand {
267 : uint32_t index;
268 : FunctionSig* sig = nullptr;
269 : unsigned length;
270 1293125 : inline CallFunctionOperand(Decoder* decoder, const byte* pc) {
271 2586232 : index = decoder->read_u32v<validate>(pc + 1, &length, "function index");
272 : }
273 : };
274 :
275 : template <Decoder::ValidateFlag validate>
276 : struct MemoryIndexOperand {
277 : uint32_t index;
278 : unsigned length = 1;
279 2007 : inline MemoryIndexOperand(Decoder* decoder, const byte* pc) {
280 4079 : index = decoder->read_u8<validate>(pc + 1, "memory index");
281 2008 : if (!VALIDATE(index == 0)) {
282 10 : decoder->errorf(pc + 1, "expected memory index 0, found %u", index);
283 : }
284 2008 : }
285 : };
286 :
287 : template <Decoder::ValidateFlag validate>
288 : struct BranchTableOperand {
289 : uint32_t table_count;
290 : const byte* start;
291 : const byte* table;
292 361256 : inline BranchTableOperand(Decoder* decoder, const byte* pc) {
293 : DCHECK_EQ(kExprBrTable, decoder->read_u8<validate>(pc, "opcode"));
294 361256 : start = pc + 1;
295 361256 : unsigned len = 0;
296 361256 : table_count = decoder->read_u32v<validate>(pc + 1, &len, "table count");
297 361256 : table = pc + 1 + len;
298 361256 : }
299 : };
300 :
301 : // A helper to iterate over a branch table.
302 : template <Decoder::ValidateFlag validate>
303 : class BranchTableIterator {
304 : public:
305 : unsigned cur_index() { return index_; }
306 1906124 : bool has_next() { return decoder_->ok() && index_ <= table_count_; }
307 2186583 : uint32_t next() {
308 : DCHECK(has_next());
309 2186583 : index_++;
310 : unsigned length;
311 : uint32_t result =
312 2186583 : decoder_->read_u32v<validate>(pc_, &length, "branch table entry");
313 2186565 : pc_ += length;
314 2186565 : return result;
315 : }
316 : // length, including the length of the {BranchTableOperand}, but not the
317 : // opcode.
318 22045 : unsigned length() {
319 69549 : while (has_next()) next();
320 22045 : return static_cast<unsigned>(pc_ - start_);
321 : }
322 : const byte* pc() { return pc_; }
323 :
324 : BranchTableIterator(Decoder* decoder,
325 : const BranchTableOperand<validate>& operand)
326 : : decoder_(decoder),
327 : start_(operand.start),
328 : pc_(operand.table),
329 : index_(0),
330 374867 : table_count_(operand.table_count) {}
331 :
332 : private:
333 : Decoder* decoder_;
334 : const byte* start_;
335 : const byte* pc_;
336 : uint32_t index_; // the current index.
337 : uint32_t table_count_; // the count of entries, not including default.
338 : };
339 :
340 : template <Decoder::ValidateFlag validate>
341 : struct MemoryAccessOperand {
342 : uint32_t alignment;
343 : uint32_t offset;
344 : unsigned length;
345 202833 : inline MemoryAccessOperand(Decoder* decoder, const byte* pc,
346 : uint32_t max_alignment) {
347 : unsigned alignment_length;
348 405670 : alignment =
349 : decoder->read_u32v<validate>(pc + 1, &alignment_length, "alignment");
350 73850 : if (!VALIDATE(alignment <= max_alignment)) {
351 218 : decoder->errorf(pc + 1,
352 : "invalid alignment; expected maximum alignment is %u, "
353 : "actual alignment is %u",
354 : max_alignment, alignment);
355 : }
356 : unsigned offset_length;
357 405670 : offset = decoder->read_u32v<validate>(pc + 1 + alignment_length,
358 : &offset_length, "offset");
359 202833 : length = alignment_length + offset_length;
360 202833 : }
361 : };
362 :
363 : // Operand for SIMD lane operations.
364 : template <Decoder::ValidateFlag validate>
365 : struct SimdLaneOperand {
366 : uint8_t lane;
367 : unsigned length = 1;
368 :
369 12654 : inline SimdLaneOperand(Decoder* decoder, const byte* pc) {
370 25308 : lane = decoder->read_u8<validate>(pc + 2, "lane");
371 : }
372 : };
373 :
374 : // Operand for SIMD shift operations.
375 : template <Decoder::ValidateFlag validate>
376 : struct SimdShiftOperand {
377 : uint8_t shift;
378 : unsigned length = 1;
379 :
380 72 : inline SimdShiftOperand(Decoder* decoder, const byte* pc) {
381 144 : shift = decoder->read_u8<validate>(pc + 2, "shift");
382 : }
383 : };
384 :
385 : // Operand for SIMD S8x16 shuffle operations.
386 : template <Decoder::ValidateFlag validate>
387 : struct Simd8x16ShuffleOperand {
388 : uint8_t shuffle[kSimd128Size];
389 :
390 0 : inline Simd8x16ShuffleOperand(Decoder* decoder, const byte* pc) {
391 0 : for (uint32_t i = 0; i < kSimd128Size; ++i) {
392 0 : shuffle[i] = decoder->read_u8<validate>(pc + 2 + i, "shuffle");
393 : }
394 0 : }
395 : };
396 :
397 : // An entry on the value stack.
398 : struct ValueBase {
399 : const byte* pc;
400 : ValueType type;
401 :
402 : // Named constructors.
403 : static ValueBase Unreachable(const byte* pc) { return {pc, kWasmVar}; }
404 :
405 : static ValueBase New(const byte* pc, ValueType type) { return {pc, type}; }
406 : };
407 :
408 : template <typename Value>
409 : struct Merge {
410 : uint32_t arity;
411 : union {
412 : Value* array;
413 : Value first;
414 : } vals; // Either multiple values or a single value.
415 :
416 : // Tracks whether this merge was ever reached. Uses precise reachability, like
417 : // Reachability::kReachable.
418 : bool reached;
419 :
420 867638 : Merge(bool reached = false) : reached(reached) {}
421 :
422 : Value& operator[](uint32_t i) {
423 : DCHECK_GT(arity, i);
424 227513 : return arity == 1 ? vals.first : vals.array[i];
425 : }
426 : };
427 :
428 : enum ControlKind : uint8_t {
429 : kControlIf,
430 : kControlIfElse,
431 : kControlBlock,
432 : kControlLoop,
433 : kControlTry,
434 : kControlTryCatch
435 : };
436 :
437 : enum Reachability : uint8_t {
438 : // reachable code.
439 : kReachable,
440 : // reachable code in unreachable block (implies normal validation).
441 : kSpecOnlyReachable,
442 : // code unreachable in its own block (implies polymorphic validation).
443 : kUnreachable
444 : };
445 :
446 : // An entry on the control stack (i.e. if, block, loop, or try).
447 : template <typename Value>
448 : struct ControlBase {
449 : Reachability reachability = kReachable;
450 : ControlKind kind;
451 : uint32_t stack_depth; // stack height at the beginning of the construct.
452 : const byte* pc;
453 :
454 : // Values merged into the end of this control construct.
455 : Merge<Value> merge;
456 :
457 549948 : ControlBase() = default;
458 : ControlBase(ControlKind kind, uint32_t stack_depth, const byte* pc,
459 : bool merge_reached = false)
460 317690 : : kind(kind), stack_depth(stack_depth), pc(pc), merge(merge_reached) {}
461 :
462 : // Check whether the current block is reachable.
463 30584 : bool reachable() const { return reachability == kReachable; }
464 :
465 : // Check whether the rest of the block is unreachable.
466 : // Note that this is different from {!reachable()}, as there is also the
467 : // "indirect unreachable state", for which both {reachable()} and
468 : // {unreachable()} return false.
469 : bool unreachable() const { return reachability == kUnreachable; }
470 :
471 : // Return the reachability of new control structs started in this block.
472 : Reachability innerReachability() const {
473 487152 : return reachability == kReachable ? kReachable : kSpecOnlyReachable;
474 : }
475 :
476 24884 : bool is_if() const { return is_onearmed_if() || is_if_else(); }
477 : bool is_onearmed_if() const { return kind == kControlIf; }
478 : bool is_if_else() const { return kind == kControlIfElse; }
479 : bool is_block() const { return kind == kControlBlock; }
480 : bool is_loop() const { return kind == kControlLoop; }
481 74 : bool is_try() const { return is_incomplete_try() || is_try_catch(); }
482 : bool is_incomplete_try() const { return kind == kControlTry; }
483 : bool is_try_catch() const { return kind == kControlTryCatch; }
484 :
485 : // Named constructors.
486 : static ControlBase Block(const byte* pc, uint32_t stack_depth) {
487 : return {kControlBlock, stack_depth, pc};
488 : }
489 :
490 : static ControlBase If(const byte* pc, uint32_t stack_depth) {
491 : return {kControlIf, stack_depth, pc};
492 : }
493 :
494 : static ControlBase Loop(const byte* pc, uint32_t stack_depth, bool reached) {
495 : return {kControlLoop, stack_depth, pc, reached};
496 : }
497 :
498 : static ControlBase Try(const byte* pc, uint32_t stack_depth) {
499 : return {kControlTry, stack_depth, pc};
500 : }
501 : };
502 :
503 : #define CONCRETE_NAMED_CONSTRUCTOR(concrete_type, abstract_type, name) \
504 : template <typename... Args> \
505 : static concrete_type name(Args&&... args) { \
506 : concrete_type val; \
507 : static_cast<abstract_type&>(val) = \
508 : abstract_type::name(std::forward<Args>(args)...); \
509 : return val; \
510 : }
511 :
512 : // Provide the default named constructors, which default-initialize the
513 : // ConcreteType and the initialize the fields of ValueBase correctly.
514 : // Use like this:
515 : // struct Value : public ValueWithNamedConstructors<Value> { int new_field; };
516 : template <typename ConcreteType>
517 : struct ValueWithNamedConstructors : public ValueBase {
518 : // Named constructors.
519 12342 : CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ValueBase, Unreachable)
520 3614188 : CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ValueBase, New)
521 : };
522 :
523 : // Provide the default named constructors, which default-initialize the
524 : // ConcreteType and the initialize the fields of ControlBase correctly.
525 : // Use like this:
526 : // struct Control : public ControlWithNamedConstructors<Control, Value> {
527 : // int my_uninitialized_field;
528 : // char* other_field = nullptr;
529 : // };
530 : template <typename ConcreteType, typename Value>
531 : struct ControlWithNamedConstructors : public ControlBase<Value> {
532 : // Named constructors.
533 476098 : CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Block)
534 62117 : CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, If)
535 11663 : CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Loop)
536 70 : CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Try)
537 : };
538 :
539 : // This is the list of callback functions that an interface for the
540 : // WasmFullDecoder should implement.
541 : // F(Name, args...)
542 : #define INTERFACE_FUNCTIONS(F) \
543 : /* General: */ \
544 : F(StartFunction) \
545 : F(StartFunctionBody, Control* block) \
546 : F(FinishFunction) \
547 : F(OnFirstError) \
548 : /* Control: */ \
549 : F(Block, Control* block) \
550 : F(Loop, Control* block) \
551 : F(Try, Control* block) \
552 : F(If, const Value& cond, Control* if_block) \
553 : F(FallThruTo, Control* c) \
554 : F(PopControl, Control* block) \
555 : F(EndControl, Control* block) \
556 : /* Instructions: */ \
557 : F(UnOp, WasmOpcode opcode, FunctionSig*, const Value& value, Value* result) \
558 : F(BinOp, WasmOpcode opcode, FunctionSig*, const Value& lhs, \
559 : const Value& rhs, Value* result) \
560 : F(I32Const, Value* result, int32_t value) \
561 : F(I64Const, Value* result, int64_t value) \
562 : F(F32Const, Value* result, float value) \
563 : F(F64Const, Value* result, double value) \
564 : F(Drop, const Value& value) \
565 : F(DoReturn, Vector<Value> values, bool implicit) \
566 : F(GetLocal, Value* result, const LocalIndexOperand<validate>& operand) \
567 : F(SetLocal, const Value& value, const LocalIndexOperand<validate>& operand) \
568 : F(TeeLocal, const Value& value, Value* result, \
569 : const LocalIndexOperand<validate>& operand) \
570 : F(GetGlobal, Value* result, const GlobalIndexOperand<validate>& operand) \
571 : F(SetGlobal, const Value& value, \
572 : const GlobalIndexOperand<validate>& operand) \
573 : F(Unreachable) \
574 : F(Select, const Value& cond, const Value& fval, const Value& tval, \
575 : Value* result) \
576 : F(BreakTo, Control* target) \
577 : F(BrIf, const Value& cond, Control* target) \
578 : F(BrTable, const BranchTableOperand<validate>& operand, const Value& key) \
579 : F(Else, Control* if_block) \
580 : F(LoadMem, ValueType type, MachineType mem_type, \
581 : const MemoryAccessOperand<validate>& operand, const Value& index, \
582 : Value* result) \
583 : F(StoreMem, ValueType type, MachineType mem_type, \
584 : const MemoryAccessOperand<validate>& operand, const Value& index, \
585 : const Value& value) \
586 : F(CurrentMemoryPages, Value* result) \
587 : F(GrowMemory, const Value& value, Value* result) \
588 : F(CallDirect, const CallFunctionOperand<validate>& operand, \
589 : const Value args[], Value returns[]) \
590 : F(CallIndirect, const Value& index, \
591 : const CallIndirectOperand<validate>& operand, const Value args[], \
592 : Value returns[]) \
593 : F(SimdOp, WasmOpcode opcode, Vector<Value> args, Value* result) \
594 : F(SimdLaneOp, WasmOpcode opcode, const SimdLaneOperand<validate>& operand, \
595 : const Vector<Value> inputs, Value* result) \
596 : F(SimdShiftOp, WasmOpcode opcode, const SimdShiftOperand<validate>& operand, \
597 : const Value& input, Value* result) \
598 : F(Simd8x16ShuffleOp, const Simd8x16ShuffleOperand<validate>& operand, \
599 : const Value& input0, const Value& input1, Value* result) \
600 : F(Throw, const ExceptionIndexOperand<validate>&, Control* block, \
601 : const Vector<Value>& args) \
602 : F(CatchException, const ExceptionIndexOperand<validate>& operand, \
603 : Control* block, Vector<Value> caught_values) \
604 : F(AtomicOp, WasmOpcode opcode, Vector<Value> args, \
605 : const MemoryAccessOperand<validate>& operand, Value* result)
606 :
607 : // Generic Wasm bytecode decoder with utilities for decoding operands,
608 : // lengths, etc.
609 : template <Decoder::ValidateFlag validate>
610 584625 : class WasmDecoder : public Decoder {
611 : public:
612 : WasmDecoder(const WasmModule* module, FunctionSig* sig, const byte* start,
613 : const byte* end, uint32_t buffer_offset = 0)
614 : : Decoder(start, end, buffer_offset),
615 : module_(module),
616 : sig_(sig),
617 584784 : local_types_(nullptr) {}
618 : const WasmModule* module_;
619 : FunctionSig* sig_;
620 :
621 : ZoneVector<ValueType>* local_types_;
622 :
623 : uint32_t total_locals() const {
624 : return local_types_ == nullptr
625 : ? 0
626 1687082 : : static_cast<uint32_t>(local_types_->size());
627 : }
628 :
629 439394 : static bool DecodeLocals(Decoder* decoder, const FunctionSig* sig,
630 : ZoneVector<ValueType>* type_list) {
631 : DCHECK_NOT_NULL(type_list);
632 : DCHECK_EQ(0, type_list->size());
633 : // Initialize from signature.
634 425961 : if (sig != nullptr) {
635 418858 : type_list->assign(sig->parameters().begin(), sig->parameters().end());
636 : }
637 : // Decode local declarations, if any.
638 : uint32_t entries = decoder->consume_u32v("local decls count");
639 426074 : if (decoder->failed()) return false;
640 :
641 : TRACE("local decls count: %u\n", entries);
642 466196 : while (entries-- > 0 && decoder->ok() && decoder->more()) {
643 : uint32_t count = decoder->consume_u32v("local count");
644 13437 : if (decoder->failed()) return false;
645 :
646 13389 : if ((count + type_list->size()) > kV8MaxWasmFunctionLocals) {
647 3 : decoder->error(decoder->pc() - 1, "local count too large");
648 3 : return false;
649 : }
650 : byte code = decoder->consume_u8("local type");
651 13386 : if (decoder->failed()) return false;
652 :
653 : ValueType type;
654 13385 : switch (code) {
655 : case kLocalI32:
656 7236 : type = kWasmI32;
657 7236 : break;
658 : case kLocalI64:
659 1411 : type = kWasmI64;
660 1411 : break;
661 : case kLocalF32:
662 1267 : type = kWasmF32;
663 1267 : break;
664 : case kLocalF64:
665 2436 : type = kWasmF64;
666 2436 : break;
667 : case kLocalS128:
668 1006 : if (FLAG_experimental_wasm_simd) {
669 996 : type = kWasmS128;
670 996 : break;
671 : }
672 : // else fall through to default.
673 : default:
674 39 : decoder->error(decoder->pc() - 1, "invalid local type");
675 40 : return false;
676 : }
677 13346 : type_list->insert(type_list->end(), count, type);
678 : }
679 : DCHECK(decoder->ok());
680 : return true;
681 : }
682 :
683 2152493 : static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc,
684 : uint32_t locals_count, Zone* zone) {
685 11700 : if (pc >= decoder->end()) return nullptr;
686 11701 : if (*pc != kExprLoop) return nullptr;
687 :
688 : // The number of locals_count is augmented by 2 so that 'locals_count - 2'
689 : // can be used to track mem_size, and 'locals_count - 1' to track mem_start.
690 163750 : BitVector* assigned = new (zone) BitVector(locals_count, zone);
691 : int depth = 0;
692 : // Iteratively process all AST nodes nested inside the loop.
693 4293275 : while (pc < decoder->end() && decoder->ok()) {
694 2140807 : WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
695 : unsigned length = 1;
696 2140807 : switch (opcode) {
697 : case kExprLoop:
698 : case kExprIf:
699 : case kExprBlock:
700 : case kExprTry:
701 111290 : length = OpcodeLength(decoder, pc);
702 111294 : depth++;
703 111294 : break;
704 : case kExprSetLocal: // fallthru
705 : case kExprTeeLocal: {
706 : LocalIndexOperand<Decoder::kValidate> operand(decoder, pc);
707 152049 : if (assigned->length() > 0 &&
708 : operand.index < static_cast<uint32_t>(assigned->length())) {
709 : // Unverified code might have an out-of-bounds index.
710 152048 : assigned->Add(operand.index);
711 : }
712 152049 : length = 1 + operand.length;
713 : break;
714 : }
715 : case kExprGrowMemory:
716 : case kExprCallFunction:
717 : case kExprCallIndirect:
718 : // Add mem_size and mem_start to the assigned set.
719 23269 : assigned->Add(locals_count - 2); // mem_size
720 23269 : assigned->Add(locals_count - 1); // mem_start
721 23269 : length = OpcodeLength(decoder, pc);
722 23269 : break;
723 : case kExprEnd:
724 111292 : depth--;
725 111292 : break;
726 : default:
727 1742907 : length = OpcodeLength(decoder, pc);
728 1742930 : break;
729 : }
730 2140834 : if (depth <= 0) break;
731 2129118 : pc += length;
732 : }
733 11702 : return decoder->ok() ? assigned : nullptr;
734 : }
735 :
736 808688 : inline bool Validate(const byte* pc,
737 808688 : LocalIndexOperand<Decoder::kValidate>& operand) {
738 1617376 : if (!VALIDATE(operand.index < total_locals())) {
739 413 : errorf(pc + 1, "invalid local index: %u", operand.index);
740 413 : return false;
741 : }
742 1616528 : operand.type = local_types_ ? local_types_->at(operand.index) : kWasmStmt;
743 808275 : return true;
744 : }
745 :
746 218 : inline bool Validate(const byte* pc,
747 : ExceptionIndexOperand<validate>& operand) {
748 653 : if (!VALIDATE(module_ != nullptr &&
749 : operand.index < module_->exceptions.size())) {
750 1 : errorf(pc + 1, "Invalid exception index: %u", operand.index);
751 : return false;
752 : }
753 434 : operand.exception = &module_->exceptions[operand.index];
754 : return true;
755 : }
756 :
757 31880 : inline bool Validate(const byte* pc, GlobalIndexOperand<validate>& operand) {
758 95619 : if (!VALIDATE(module_ != nullptr &&
759 : operand.index < module_->globals.size())) {
760 20 : errorf(pc + 1, "invalid global index: %u", operand.index);
761 20 : return false;
762 : }
763 63720 : operand.global = &module_->globals[operand.index];
764 31860 : operand.type = operand.global->type;
765 31860 : return true;
766 : }
767 :
768 : inline bool Complete(const byte* pc, CallFunctionOperand<validate>& operand) {
769 931711 : if (!VALIDATE(module_ != nullptr &&
770 : operand.index < module_->functions.size())) {
771 : return false;
772 : }
773 627576 : operand.sig = module_->functions[operand.index].sig;
774 : return true;
775 : }
776 :
777 310561 : inline bool Validate(const byte* pc, CallFunctionOperand<validate>& operand) {
778 310561 : if (Complete(pc, operand)) {
779 : return true;
780 : }
781 60 : errorf(pc + 1, "invalid function index: %u", operand.index);
782 60 : return false;
783 : }
784 :
785 : inline bool Complete(const byte* pc, CallIndirectOperand<validate>& operand) {
786 13019 : if (!VALIDATE(module_ != nullptr &&
787 : operand.index < module_->signatures.size())) {
788 : return false;
789 : }
790 8730 : operand.sig = module_->signatures[operand.index];
791 : return true;
792 : }
793 :
794 4380 : inline bool Validate(const byte* pc, CallIndirectOperand<validate>& operand) {
795 8760 : if (!VALIDATE(module_ != nullptr && !module_->function_tables.empty())) {
796 23 : error("function table has to exist to execute call_indirect");
797 23 : return false;
798 : }
799 4357 : if (!Complete(pc, operand)) {
800 52 : errorf(pc + 1, "invalid signature index: #%u", operand.index);
801 52 : return false;
802 : }
803 : return true;
804 : }
805 :
806 : inline bool Validate(const byte* pc, BreakDepthOperand<validate>& operand,
807 : size_t control_depth) {
808 328071 : if (!VALIDATE(operand.depth < control_depth)) {
809 601 : errorf(pc + 1, "invalid break depth: %u", operand.depth);
810 : return false;
811 : }
812 : return true;
813 : }
814 :
815 15617 : bool Validate(const byte* pc, BranchTableOperand<validate>& operand,
816 : size_t block_depth) {
817 15617 : if (!VALIDATE(operand.table_count < kV8MaxWasmFunctionSize)) {
818 20 : errorf(pc + 1, "invalid table count (> max function size): %u",
819 : operand.table_count);
820 : return false;
821 : }
822 15597 : return checkAvailable(operand.table_count);
823 : }
824 :
825 12654 : inline bool Validate(const byte* pc, WasmOpcode opcode,
826 : SimdLaneOperand<validate>& operand) {
827 : uint8_t num_lanes = 0;
828 12654 : switch (opcode) {
829 : case kExprF32x4ExtractLane:
830 : case kExprF32x4ReplaceLane:
831 : case kExprI32x4ExtractLane:
832 : case kExprI32x4ReplaceLane:
833 : num_lanes = 4;
834 : break;
835 : case kExprI16x8ExtractLane:
836 : case kExprI16x8ReplaceLane:
837 : num_lanes = 8;
838 : break;
839 : case kExprI8x16ExtractLane:
840 : case kExprI8x16ReplaceLane:
841 : num_lanes = 16;
842 : break;
843 : default:
844 0 : UNREACHABLE();
845 : break;
846 : }
847 12654 : if (!VALIDATE(operand.lane >= 0 && operand.lane < num_lanes)) {
848 0 : error(pc_ + 2, "invalid lane index");
849 : return false;
850 : } else {
851 : return true;
852 : }
853 : }
854 :
855 72 : inline bool Validate(const byte* pc, WasmOpcode opcode,
856 : SimdShiftOperand<validate>& operand) {
857 : uint8_t max_shift = 0;
858 72 : switch (opcode) {
859 : case kExprI32x4Shl:
860 : case kExprI32x4ShrS:
861 : case kExprI32x4ShrU:
862 : max_shift = 32;
863 : break;
864 : case kExprI16x8Shl:
865 : case kExprI16x8ShrS:
866 : case kExprI16x8ShrU:
867 : max_shift = 16;
868 : break;
869 : case kExprI8x16Shl:
870 : case kExprI8x16ShrS:
871 : case kExprI8x16ShrU:
872 : max_shift = 8;
873 : break;
874 : default:
875 0 : UNREACHABLE();
876 : break;
877 : }
878 72 : if (!VALIDATE(operand.shift >= 0 && operand.shift < max_shift)) {
879 0 : error(pc_ + 2, "invalid shift amount");
880 : return false;
881 : } else {
882 : return true;
883 : }
884 : }
885 :
886 0 : inline bool Validate(const byte* pc,
887 : Simd8x16ShuffleOperand<validate>& operand) {
888 0 : uint8_t max_lane = 0;
889 0 : for (uint32_t i = 0; i < kSimd128Size; ++i)
890 0 : max_lane = std::max(max_lane, operand.shuffle[i]);
891 : // Shuffle indices must be in [0..31] for a 16 lane shuffle.
892 0 : if (!VALIDATE(max_lane <= 2 * kSimd128Size)) {
893 0 : error(pc_ + 2, "invalid shuffle mask");
894 : return false;
895 : }
896 : return true;
897 : }
898 :
899 2091788 : static unsigned OpcodeLength(Decoder* decoder, const byte* pc) {
900 2091788 : WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
901 2091788 : switch (opcode) {
902 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
903 : FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
904 : FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
905 : #undef DECLARE_OPCODE_CASE
906 : {
907 9467 : MemoryAccessOperand<validate> operand(decoder, pc, UINT32_MAX);
908 9465 : return 1 + operand.length;
909 : }
910 : case kExprBr:
911 : case kExprBrIf: {
912 : BreakDepthOperand<validate> operand(decoder, pc);
913 74085 : return 1 + operand.length;
914 : }
915 : case kExprSetGlobal:
916 : case kExprGetGlobal: {
917 4455 : GlobalIndexOperand<validate> operand(decoder, pc);
918 4668 : return 1 + operand.length;
919 : }
920 :
921 : case kExprCallFunction: {
922 : CallFunctionOperand<validate> operand(decoder, pc);
923 25280 : return 1 + operand.length;
924 : }
925 : case kExprCallIndirect: {
926 1264 : CallIndirectOperand<validate> operand(decoder, pc);
927 1264 : return 1 + operand.length;
928 : }
929 :
930 : case kExprTry:
931 : case kExprIf: // fall through
932 : case kExprLoop:
933 : case kExprBlock: {
934 143920 : BlockTypeOperand<validate> operand(decoder, pc);
935 143922 : return 1 + operand.length;
936 : }
937 :
938 : case kExprThrow:
939 : case kExprCatch: {
940 : ExceptionIndexOperand<validate> operand(decoder, pc);
941 2 : return 1 + operand.length;
942 : }
943 :
944 : case kExprSetLocal:
945 : case kExprTeeLocal:
946 : case kExprGetLocal: {
947 : LocalIndexOperand<Decoder::kValidate> operand(decoder, pc);
948 431762 : return 1 + operand.length;
949 : }
950 : case kExprBrTable: {
951 6430 : BranchTableOperand<validate> operand(decoder, pc);
952 : BranchTableIterator<validate> iterator(decoder, operand);
953 6430 : return 1 + iterator.length();
954 : }
955 : case kExprI32Const: {
956 : ImmI32Operand<validate> operand(decoder, pc);
957 451809 : return 1 + operand.length;
958 : }
959 : case kExprI64Const: {
960 : ImmI64Operand<validate> operand(decoder, pc);
961 3889 : return 1 + operand.length;
962 : }
963 : case kExprGrowMemory:
964 : case kExprMemorySize: {
965 80 : MemoryIndexOperand<validate> operand(decoder, pc);
966 80 : return 1 + operand.length;
967 : }
968 : case kExprF32Const:
969 : return 5;
970 : case kExprF64Const:
971 5061 : return 9;
972 : case kSimdPrefix: {
973 166 : byte simd_index = decoder->read_u8<validate>(pc + 1, "simd_index");
974 : WasmOpcode opcode =
975 154 : static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
976 154 : switch (opcode) {
977 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
978 : FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
979 : #undef DECLARE_OPCODE_CASE
980 : return 2;
981 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
982 : FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
983 : #undef DECLARE_OPCODE_CASE
984 17 : return 3;
985 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
986 : FOREACH_SIMD_MEM_OPCODE(DECLARE_OPCODE_CASE)
987 : #undef DECLARE_OPCODE_CASE
988 : {
989 0 : MemoryAccessOperand<validate> operand(decoder, pc + 1, UINT32_MAX);
990 0 : return 2 + operand.length;
991 : }
992 : // Shuffles require a byte per lane, or 16 immediate bytes.
993 : case kExprS8x16Shuffle:
994 1 : return 2 + kSimd128Size;
995 : default:
996 : decoder->error(pc, "invalid SIMD opcode");
997 1 : return 2;
998 : }
999 : }
1000 : case kAtomicPrefix: {
1001 20 : byte atomic_index = decoder->read_u8<validate>(pc + 1, "atomic_index");
1002 : WasmOpcode opcode =
1003 32 : static_cast<WasmOpcode>(kAtomicPrefix << 8 | atomic_index);
1004 : switch (opcode) {
1005 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1006 : FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE)
1007 : #undef DECLARE_OPCODE_CASE
1008 : {
1009 32 : MemoryAccessOperand<validate> operand(decoder, pc + 1, UINT32_MAX);
1010 32 : return 2 + operand.length;
1011 : }
1012 : default:
1013 : decoder->error(pc, "invalid Atomics opcode");
1014 0 : return 2;
1015 : }
1016 : }
1017 : default:
1018 933296 : return 1;
1019 : }
1020 : }
1021 :
1022 182613 : std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) {
1023 179323 : WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
1024 : // Handle "simple" opcodes with a fixed signature first.
1025 183939 : FunctionSig* sig = WasmOpcodes::Signature(opcode);
1026 179323 : if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode);
1027 183939 : if (sig) return {sig->parameter_count(), sig->return_count()};
1028 174707 : if (WasmOpcodes::IsPrefixOpcode(opcode)) {
1029 0 : opcode = static_cast<WasmOpcode>(opcode << 8 | *(pc + 1));
1030 : }
1031 :
1032 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1033 : // clang-format off
1034 174707 : switch (opcode) {
1035 : case kExprSelect:
1036 30 : return {3, 1};
1037 : case kExprS128StoreMem:
1038 : FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
1039 798 : return {2, 0};
1040 : case kExprS128LoadMem:
1041 : FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
1042 : case kExprTeeLocal:
1043 : case kExprGrowMemory:
1044 8308 : return {1, 1};
1045 : case kExprSetLocal:
1046 : case kExprSetGlobal:
1047 : case kExprDrop:
1048 : case kExprBrIf:
1049 : case kExprBrTable:
1050 : case kExprIf:
1051 9015 : return {1, 0};
1052 : case kExprGetLocal:
1053 : case kExprGetGlobal:
1054 : case kExprI32Const:
1055 : case kExprI64Const:
1056 : case kExprF32Const:
1057 : case kExprF64Const:
1058 : case kExprMemorySize:
1059 73004 : return {0, 1};
1060 : case kExprCallFunction: {
1061 : CallFunctionOperand<validate> operand(this, pc);
1062 : CHECK(Complete(pc, operand));
1063 6460 : return {operand.sig->parameter_count(), operand.sig->return_count()};
1064 : }
1065 : case kExprCallIndirect: {
1066 60 : CallIndirectOperand<validate> operand(this, pc);
1067 60 : CHECK(Complete(pc, operand));
1068 : // Indirect calls pop an additional argument for the table index.
1069 : return {operand.sig->parameter_count() + 1,
1070 120 : operand.sig->return_count()};
1071 : }
1072 : case kExprBr:
1073 : case kExprBlock:
1074 : case kExprLoop:
1075 : case kExprEnd:
1076 : case kExprElse:
1077 : case kExprNop:
1078 : case kExprReturn:
1079 : case kExprUnreachable:
1080 80262 : return {0, 0};
1081 : default:
1082 0 : V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x (%s)", opcode,
1083 0 : WasmOpcodes::OpcodeName(opcode));
1084 : return {0, 0};
1085 : }
1086 : #undef DECLARE_OPCODE_CASE
1087 : // clang-format on
1088 : }
1089 : };
1090 :
1091 : #define CALL_INTERFACE(name, ...) interface_.name(this, ##__VA_ARGS__)
1092 : #define CALL_INTERFACE_IF_REACHABLE(name, ...) \
1093 : do { \
1094 : DCHECK(!control_.empty()); \
1095 : if (this->ok() && control_.back().reachable()) { \
1096 : interface_.name(this, ##__VA_ARGS__); \
1097 : } \
1098 : } while (false)
1099 : #define CALL_INTERFACE_IF_PARENT_REACHABLE(name, ...) \
1100 : do { \
1101 : DCHECK(!control_.empty()); \
1102 : if (this->ok() && (control_.size() == 1 || control_at(1)->reachable())) { \
1103 : interface_.name(this, ##__VA_ARGS__); \
1104 : } \
1105 : } while (false)
1106 :
1107 : template <Decoder::ValidateFlag validate, typename Interface>
1108 405302 : class WasmFullDecoder : public WasmDecoder<validate> {
1109 : using Value = typename Interface::Value;
1110 : using Control = typename Interface::Control;
1111 : using MergeValues = Merge<Value>;
1112 :
1113 : // All Value types should be trivially copyable for performance. We push, pop,
1114 : // and store them in local variables.
1115 : static_assert(IS_TRIVIALLY_COPYABLE(Value),
1116 : "all Value<...> types should be trivially copyable");
1117 :
1118 : public:
1119 : template <typename... InterfaceArgs>
1120 : WasmFullDecoder(Zone* zone, const wasm::WasmModule* module,
1121 : const FunctionBody& body, InterfaceArgs&&... interface_args)
1122 : : WasmDecoder<validate>(module, body.sig, body.start, body.end,
1123 : body.offset),
1124 : zone_(zone),
1125 : interface_(std::forward<InterfaceArgs>(interface_args)...),
1126 : local_type_vec_(zone),
1127 : stack_(zone),
1128 : control_(zone),
1129 1216383 : last_end_found_(false) {
1130 405461 : this->local_types_ = &local_type_vec_;
1131 : }
1132 :
1133 : Interface& interface() { return interface_; }
1134 :
1135 405464 : bool Decode() {
1136 : DCHECK(stack_.empty());
1137 : DCHECK(control_.empty());
1138 :
1139 405464 : if (FLAG_wasm_code_fuzzer_gen_test) {
1140 0 : PrintRawWasmCode(this->start_, this->end_);
1141 : }
1142 : base::ElapsedTimer decode_timer;
1143 405504 : if (FLAG_trace_wasm_decode_time) {
1144 : decode_timer.Start();
1145 : }
1146 :
1147 405504 : if (this->end_ < this->pc_) {
1148 0 : this->error("function body end < start");
1149 0 : return false;
1150 : }
1151 :
1152 : DCHECK_EQ(0, this->local_types_->size());
1153 405504 : WasmDecoder<validate>::DecodeLocals(this, this->sig_, this->local_types_);
1154 463059 : CALL_INTERFACE(StartFunction);
1155 405476 : DecodeFunctionBody();
1156 234320 : if (!this->failed()) CALL_INTERFACE(FinishFunction);
1157 :
1158 405278 : if (this->failed()) return this->TraceFailed();
1159 :
1160 383652 : if (!control_.empty()) {
1161 : // Generate a better error message whether the unterminated control
1162 : // structure is the function body block or an innner structure.
1163 28 : if (control_.size() > 1) {
1164 0 : this->error(control_.back().pc, "unterminated control structure");
1165 : } else {
1166 : this->error("function body must end with \"end\" opcode");
1167 : }
1168 : return TraceFailed();
1169 : }
1170 :
1171 383624 : if (!last_end_found_) {
1172 : this->error("function body must end with \"end\" opcode");
1173 0 : return false;
1174 : }
1175 :
1176 383624 : if (FLAG_trace_wasm_decode_time) {
1177 0 : double ms = decode_timer.Elapsed().InMillisecondsF();
1178 0 : PrintF("wasm-decode %s (%0.3f ms)\n\n", this->ok() ? "ok" : "failed", ms);
1179 : } else {
1180 : TRACE("wasm-decode %s\n\n", this->ok() ? "ok" : "failed");
1181 : }
1182 :
1183 : return true;
1184 : }
1185 :
1186 : bool TraceFailed() {
1187 : TRACE("wasm-error module+%-6d func+%d: %s\n\n", this->error_offset_,
1188 : this->GetBufferRelativeOffset(this->error_offset_),
1189 : this->error_msg_.c_str());
1190 : return false;
1191 : }
1192 :
1193 : const char* SafeOpcodeNameAt(const byte* pc) {
1194 39892 : if (pc >= this->end_) return "<end>";
1195 33566 : return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(*pc));
1196 : }
1197 :
1198 : inline Zone* zone() const { return zone_; }
1199 :
1200 : inline uint32_t NumLocals() {
1201 2204014 : return static_cast<uint32_t>(local_type_vec_.size());
1202 : }
1203 :
1204 : inline ValueType GetLocalType(uint32_t index) {
1205 1838184 : return local_type_vec_[index];
1206 : }
1207 :
1208 : inline wasm::WasmCodePosition position() {
1209 1701281 : int offset = static_cast<int>(this->pc_ - this->start_);
1210 : DCHECK_EQ(this->pc_ - this->start_, offset); // overflows cannot happen
1211 : return offset;
1212 : }
1213 :
1214 : inline uint32_t control_depth() const {
1215 320 : return static_cast<uint32_t>(control_.size());
1216 : }
1217 :
1218 : inline Control* control_at(uint32_t depth) {
1219 : DCHECK_GT(control_.size(), depth);
1220 1173732 : return &control_.back() - depth;
1221 : }
1222 :
1223 : inline uint32_t stack_size() const {
1224 2968496 : return static_cast<uint32_t>(stack_.size());
1225 : }
1226 :
1227 : inline Value* stack_value(uint32_t depth) {
1228 : DCHECK_GT(stack_.size(), depth);
1229 : return &stack_[stack_.size() - depth - 1];
1230 : }
1231 :
1232 : inline Value& GetMergeValueFromStack(Control* c, uint32_t i) {
1233 : DCHECK_GT(c->merge.arity, i);
1234 : DCHECK_GE(stack_.size(), c->stack_depth + c->merge.arity);
1235 455026 : return stack_[stack_.size() - c->merge.arity + i];
1236 : }
1237 :
1238 : private:
1239 : static constexpr size_t kErrorMsgSize = 128;
1240 :
1241 : Zone* zone_;
1242 :
1243 : Interface interface_;
1244 :
1245 : ZoneVector<ValueType> local_type_vec_; // types of local variables.
1246 : ZoneVector<Value> stack_; // stack of values.
1247 : ZoneVector<Control> control_; // stack of blocks, loops, and ifs.
1248 : bool last_end_found_;
1249 :
1250 74934 : bool CheckHasMemory() {
1251 74934 : if (!VALIDATE(this->module_->has_memory)) {
1252 130 : this->error(this->pc_ - 1, "memory instruction with no memory");
1253 130 : return false;
1254 : }
1255 : return true;
1256 : }
1257 :
1258 521 : bool CheckHasSharedMemory() {
1259 521 : if (!VALIDATE(this->module_->has_shared_memory)) {
1260 10 : this->error(this->pc_ - 1, "Atomic opcodes used without shared memory");
1261 10 : return false;
1262 : }
1263 : return true;
1264 : }
1265 :
1266 : // Decodes the body of a function.
1267 405452 : void DecodeFunctionBody() {
1268 : TRACE("wasm-decode %p...%p (module+%u, %d bytes)\n",
1269 : reinterpret_cast<const void*>(this->start()),
1270 : reinterpret_cast<const void*>(this->end()), this->pc_offset(),
1271 : static_cast<int>(this->end() - this->start()));
1272 :
1273 : // Set up initial function block.
1274 : {
1275 405452 : auto* c = PushBlock();
1276 526713 : c->merge.arity = static_cast<uint32_t>(this->sig_->return_count());
1277 :
1278 405374 : if (c->merge.arity == 1) {
1279 237490 : c->merge.vals.first = Value::New(this->pc_, this->sig_->GetReturn(0));
1280 288177 : } else if (c->merge.arity > 1) {
1281 4138 : c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity);
1282 6211 : for (unsigned i = 0; i < c->merge.arity; i++) {
1283 8284 : c->merge.vals.array[i] =
1284 5188 : Value::New(this->pc_, this->sig_->GetReturn(i));
1285 : }
1286 : }
1287 2168129 : CALL_INTERFACE(StartFunctionBody, c);
1288 : }
1289 :
1290 8603461 : while (this->pc_ < this->end_) { // decoding loop.
1291 : unsigned len = 1;
1292 7963727 : WasmOpcode opcode = static_cast<WasmOpcode>(*this->pc_);
1293 : #if DEBUG
1294 : if (FLAG_trace_wasm_decoder && !WasmOpcodes::IsPrefixOpcode(opcode)) {
1295 : TRACE(" @%-8d #%-20s|", startrel(this->pc_),
1296 : WasmOpcodes::OpcodeName(opcode));
1297 : }
1298 : #endif
1299 :
1300 7963727 : FunctionSig* sig = WasmOpcodes::Signature(opcode);
1301 7963817 : if (sig) {
1302 1630550 : BuildSimpleOperator(opcode, sig);
1303 : } else {
1304 : // Complex bytecode.
1305 6333267 : switch (opcode) {
1306 : case kExprNop:
1307 : break;
1308 : case kExprBlock: {
1309 382076 : BlockTypeOperand<validate> operand(this, this->pc_);
1310 382078 : if (!LookupBlockType(&operand)) break;
1311 382070 : auto* block = PushBlock();
1312 382074 : SetBlockType(block, operand);
1313 382073 : len = 1 + operand.length;
1314 2492138 : CALL_INTERFACE_IF_REACHABLE(Block, block);
1315 : break;
1316 : }
1317 : case kExprRethrow: {
1318 : // TODO(kschimpf): Implement.
1319 0 : CHECK_PROTOTYPE_OPCODE(eh);
1320 0 : OPCODE_ERROR(opcode, "not implemented yet");
1321 0 : break;
1322 : }
1323 : case kExprThrow: {
1324 144 : CHECK_PROTOTYPE_OPCODE(eh);
1325 144 : ExceptionIndexOperand<Decoder::kValidate> operand(this, this->pc_);
1326 144 : len = 1 + operand.length;
1327 144 : if (!this->Validate(this->pc_, operand)) break;
1328 : std::vector<Value> args;
1329 286 : PopArgs(operand.exception->ToFunctionSig(), &args);
1330 426 : CALL_INTERFACE_IF_REACHABLE(Throw, operand, &control_.back(),
1331 : vec2vec(args));
1332 140 : EndControl();
1333 : break;
1334 : }
1335 : case kExprTry: {
1336 74 : CHECK_PROTOTYPE_OPCODE(eh);
1337 74 : BlockTypeOperand<validate> operand(this, this->pc_);
1338 74 : if (!LookupBlockType(&operand)) break;
1339 74 : auto* try_block = PushTry();
1340 74 : SetBlockType(try_block, operand);
1341 74 : len = 1 + operand.length;
1342 148 : CALL_INTERFACE_IF_REACHABLE(Try, try_block);
1343 : break;
1344 : }
1345 : case kExprCatch: {
1346 : // TODO(kschimpf): Fix to use type signature of exception.
1347 74 : CHECK_PROTOTYPE_OPCODE(eh);
1348 74 : ExceptionIndexOperand<Decoder::kValidate> operand(this, this->pc_);
1349 74 : len = 1 + operand.length;
1350 :
1351 74 : if (!this->Validate(this->pc_, operand)) break;
1352 :
1353 74 : if (!VALIDATE(!control_.empty())) {
1354 : this->error("catch does not match any try");
1355 : break;
1356 : }
1357 :
1358 144 : Control* c = &control_.back();
1359 74 : if (!VALIDATE(c->is_try())) {
1360 : this->error("catch does not match any try");
1361 : break;
1362 : }
1363 :
1364 74 : if (!VALIDATE(c->is_incomplete_try())) {
1365 1 : OPCODE_ERROR(opcode, "multiple catch blocks not implemented");
1366 1 : break;
1367 : }
1368 73 : c->kind = kControlTryCatch;
1369 73 : FallThruTo(c);
1370 12387 : stack_.resize(c->stack_depth);
1371 183 : const WasmExceptionSig* sig = operand.exception->sig;
1372 113 : for (size_t i = 0, e = sig->parameter_count(); i < e; ++i) {
1373 : Push(sig->GetParam(i));
1374 : }
1375 : Vector<Value> values(stack_.data() + c->stack_depth,
1376 70 : sig->parameter_count());
1377 210 : CALL_INTERFACE_IF_PARENT_REACHABLE(CatchException, operand, c,
1378 : values);
1379 146 : c->reachability = control_at(1)->innerReachability();
1380 73 : break;
1381 : }
1382 : case kExprCatchAll: {
1383 : // TODO(kschimpf): Implement.
1384 0 : CHECK_PROTOTYPE_OPCODE(eh);
1385 0 : OPCODE_ERROR(opcode, "not implemented yet");
1386 0 : break;
1387 : }
1388 : case kExprLoop: {
1389 16029 : BlockTypeOperand<validate> operand(this, this->pc_);
1390 16028 : if (!LookupBlockType(&operand)) break;
1391 16028 : auto* block = PushLoop();
1392 16029 : SetBlockType(&control_.back(), operand);
1393 16029 : len = 1 + operand.length;
1394 32048 : CALL_INTERFACE_IF_REACHABLE(Loop, block);
1395 : break;
1396 : }
1397 : case kExprIf: {
1398 64169 : BlockTypeOperand<validate> operand(this, this->pc_);
1399 64166 : if (!LookupBlockType(&operand)) break;
1400 64158 : auto cond = Pop(0, kWasmI32);
1401 64153 : if (!this->ok()) break;
1402 64027 : auto* if_block = PushIf();
1403 64028 : SetBlockType(if_block, operand);
1404 124243 : CALL_INTERFACE_IF_REACHABLE(If, cond, if_block);
1405 64025 : len = 1 + operand.length;
1406 64025 : break;
1407 : }
1408 : case kExprElse: {
1409 24884 : if (!VALIDATE(!control_.empty())) {
1410 0 : this->error("else does not match any if");
1411 : break;
1412 : }
1413 48428 : Control* c = &control_.back();
1414 24884 : if (!VALIDATE(c->is_if())) {
1415 0 : this->error(this->pc_, "else does not match an if");
1416 : break;
1417 : }
1418 24884 : if (c->is_if_else()) {
1419 2 : this->error(this->pc_, "else already present for if");
1420 : break;
1421 : }
1422 24882 : c->kind = kControlIfElse;
1423 24882 : FallThruTo(c);
1424 24882 : stack_.resize(c->stack_depth);
1425 47274 : CALL_INTERFACE_IF_PARENT_REACHABLE(Else, c);
1426 49770 : c->reachability = control_at(1)->innerReachability();
1427 24885 : break;
1428 : }
1429 : case kExprEnd: {
1430 842803 : if (!VALIDATE(!control_.empty())) {
1431 0 : this->error("end does not match any if, try, or block");
1432 : return;
1433 : }
1434 843305 : Control* c = &control_.back();
1435 881072 : if (c->is_loop()) {
1436 : // A loop just leaves the values on the stack.
1437 14555 : TypeCheckFallThru(c);
1438 14555 : PopControl(c);
1439 14556 : break;
1440 : }
1441 828248 : if (c->is_onearmed_if()) {
1442 : // The merge point is reached if the if is not taken.
1443 38771 : if (control_at(1)->reachable()) c->merge.reached = true;
1444 : // End the true branch of a one-armed if.
1445 51085 : if (!VALIDATE(c->unreachable() ||
1446 : stack_.size() == c->stack_depth)) {
1447 121 : this->error("end of if expected empty stack");
1448 121 : stack_.resize(c->stack_depth);
1449 : }
1450 38771 : if (!VALIDATE(c->merge.arity == 0)) {
1451 80 : this->error("non-void one-armed if");
1452 : }
1453 789477 : } else if (!VALIDATE(!c->is_incomplete_try())) {
1454 1 : this->error(this->pc_, "missing catch in try");
1455 : break;
1456 : }
1457 828247 : FallThruTo(c);
1458 828150 : PushEndValues(c);
1459 :
1460 828246 : if (control_.size() == 1) {
1461 : // If at the last (implicit) control, check we are at end.
1462 386355 : if (!VALIDATE(this->pc_ + 1 == this->end_)) {
1463 2723 : this->error(this->pc_ + 1, "trailing code after function end");
1464 : break;
1465 : }
1466 383632 : last_end_found_ = true;
1467 : // The result of the block is the return value.
1468 : TRACE(" @%-8d #xx:%-20s|", startrel(this->pc_),
1469 : "(implicit) return");
1470 383632 : DoReturn(c, true);
1471 : TRACE("\n");
1472 : }
1473 :
1474 825779 : PopControl(c);
1475 825595 : break;
1476 : }
1477 : case kExprSelect: {
1478 1425 : auto cond = Pop(2, kWasmI32);
1479 1425 : auto fval = Pop();
1480 1426 : auto tval = Pop(0, fval.type);
1481 1426 : auto* result = Push(tval.type == kWasmVar ? fval.type : tval.type);
1482 1471 : CALL_INTERFACE_IF_REACHABLE(Select, cond, fval, tval, result);
1483 : break;
1484 : }
1485 : case kExprBr: {
1486 34858 : BreakDepthOperand<validate> operand(this, this->pc_);
1487 69717 : if (!this->Validate(this->pc_, operand, control_.size())) break;
1488 34317 : Control* c = control_at(operand.depth);
1489 34317 : if (!TypeCheckBreak(c)) break;
1490 61842 : CALL_INTERFACE_IF_REACHABLE(BreakTo, c);
1491 33612 : if (control_.back().reachable()) c->merge.reached = true;
1492 33612 : len = 1 + operand.length;
1493 30923 : EndControl();
1494 30922 : break;
1495 : }
1496 : case kExprBrIf: {
1497 293214 : BreakDepthOperand<validate> operand(this, this->pc_);
1498 293214 : auto cond = Pop(0, kWasmI32);
1499 586429 : if (!this->Validate(this->pc_, operand, control_.size())) break;
1500 293154 : Control* c = control_at(operand.depth);
1501 293154 : if (!TypeCheckBreak(c)) break;
1502 327564 : CALL_INTERFACE_IF_REACHABLE(BrIf, cond, c);
1503 292972 : if (control_.back().reachable()) c->merge.reached = true;
1504 292972 : len = 1 + operand.length;
1505 292972 : break;
1506 : }
1507 : case kExprBrTable: {
1508 15617 : BranchTableOperand<validate> operand(this, this->pc_);
1509 : BranchTableIterator<validate> iterator(this, operand);
1510 15617 : if (!this->Validate(this->pc_, operand, control_.size())) break;
1511 15597 : auto key = Pop(0, kWasmI32);
1512 : uint32_t br_arity = 0;
1513 578900 : while (iterator.has_next()) {
1514 548023 : const uint32_t i = iterator.cur_index();
1515 548023 : const byte* pos = iterator.pc();
1516 548023 : uint32_t target = iterator.next();
1517 1096032 : if (!VALIDATE(target < control_.size())) {
1518 : this->error(pos, "improper branch in br_table");
1519 : break;
1520 : }
1521 : // Check that label types match up.
1522 248946 : Control* c = control_at(target);
1523 547866 : uint32_t arity = c->is_loop() ? 0 : c->merge.arity;
1524 547866 : if (i == 0) {
1525 : br_arity = arity;
1526 532436 : } else if (!VALIDATE(br_arity == arity)) {
1527 64 : this->errorf(pos,
1528 : "inconsistent arity in br_table target %d"
1529 : " (previous was %u, this one %u)",
1530 : i, br_arity, arity);
1531 : }
1532 547866 : if (!TypeCheckBreak(c)) break;
1533 547706 : if (control_.back().reachable()) c->merge.reached = true;
1534 : }
1535 :
1536 27860 : CALL_INTERFACE_IF_REACHABLE(BrTable, operand, key);
1537 :
1538 15597 : len = 1 + iterator.length();
1539 14030 : EndControl();
1540 14030 : break;
1541 : }
1542 : case kExprReturn: {
1543 361284 : DoReturn(&control_.back(), false);
1544 361283 : break;
1545 : }
1546 : case kExprUnreachable: {
1547 265434 : CALL_INTERFACE_IF_REACHABLE(Unreachable);
1548 132715 : EndControl();
1549 132719 : break;
1550 : }
1551 : case kExprI32Const: {
1552 1114765 : ImmI32Operand<validate> operand(this, this->pc_);
1553 : auto* value = Push(kWasmI32);
1554 1996282 : CALL_INTERFACE_IF_REACHABLE(I32Const, value, operand.value);
1555 1114789 : len = 1 + operand.length;
1556 : break;
1557 : }
1558 : case kExprI64Const: {
1559 85239 : ImmI64Operand<validate> operand(this, this->pc_);
1560 : auto* value = Push(kWasmI64);
1561 92227 : CALL_INTERFACE_IF_REACHABLE(I64Const, value, operand.value);
1562 85243 : len = 1 + operand.length;
1563 : break;
1564 : }
1565 : case kExprF32Const: {
1566 292501 : ImmF32Operand<validate> operand(this, this->pc_);
1567 : auto* value = Push(kWasmF32);
1568 293947 : CALL_INTERFACE_IF_REACHABLE(F32Const, value, operand.value);
1569 292502 : len = 1 + operand.length;
1570 : break;
1571 : }
1572 : case kExprF64Const: {
1573 302918 : ImmF64Operand<validate> operand(this, this->pc_);
1574 : auto* value = Push(kWasmF64);
1575 315184 : CALL_INTERFACE_IF_REACHABLE(F64Const, value, operand.value);
1576 302918 : len = 1 + operand.length;
1577 : break;
1578 : }
1579 : case kExprGetLocal: {
1580 614034 : LocalIndexOperand<Decoder::kValidate> operand(this, this->pc_);
1581 614050 : if (!this->Validate(this->pc_, operand)) break;
1582 613628 : auto* value = Push(operand.type);
1583 1136272 : CALL_INTERFACE_IF_REACHABLE(GetLocal, value, operand);
1584 613642 : len = 1 + operand.length;
1585 613642 : break;
1586 : }
1587 : case kExprSetLocal: {
1588 61869 : LocalIndexOperand<Decoder::kValidate> operand(this, this->pc_);
1589 61869 : if (!this->Validate(this->pc_, operand)) break;
1590 256491 : auto value = Pop(0, local_type_vec_[operand.index]);
1591 97421 : CALL_INTERFACE_IF_REACHABLE(SetLocal, value, operand);
1592 61866 : len = 1 + operand.length;
1593 61866 : break;
1594 : }
1595 : case kExprTeeLocal: {
1596 132763 : LocalIndexOperand<Decoder::kValidate> operand(this, this->pc_);
1597 132762 : if (!this->Validate(this->pc_, operand)) break;
1598 265522 : auto value = Pop(0, local_type_vec_[operand.index]);
1599 132762 : auto* result = Push(value.type);
1600 264060 : CALL_INTERFACE_IF_REACHABLE(TeeLocal, value, result, operand);
1601 132765 : len = 1 + operand.length;
1602 132765 : break;
1603 : }
1604 : case kExprDrop: {
1605 205953 : auto value = Pop();
1606 : CALL_INTERFACE_IF_REACHABLE(Drop, value);
1607 : break;
1608 : }
1609 : case kExprGetGlobal: {
1610 19848 : GlobalIndexOperand<validate> operand(this, this->pc_);
1611 19847 : len = 1 + operand.length;
1612 19847 : if (!this->Validate(this->pc_, operand)) break;
1613 19827 : auto* result = Push(operand.type);
1614 39323 : CALL_INTERFACE_IF_REACHABLE(GetGlobal, result, operand);
1615 : break;
1616 : }
1617 : case kExprSetGlobal: {
1618 12033 : GlobalIndexOperand<validate> operand(this, this->pc_);
1619 12033 : len = 1 + operand.length;
1620 12033 : if (!this->Validate(this->pc_, operand)) break;
1621 12034 : if (!VALIDATE(operand.global->mutability)) {
1622 21 : this->errorf(this->pc_, "immutable global #%u cannot be assigned",
1623 : operand.index);
1624 21 : break;
1625 : }
1626 12013 : auto value = Pop(0, operand.type);
1627 23892 : CALL_INTERFACE_IF_REACHABLE(SetGlobal, value, operand);
1628 : break;
1629 : }
1630 : case kExprI32LoadMem8S:
1631 3443 : len = DecodeLoadMem(kWasmI32, MachineType::Int8());
1632 3443 : break;
1633 : case kExprI32LoadMem8U:
1634 863 : len = DecodeLoadMem(kWasmI32, MachineType::Uint8());
1635 863 : break;
1636 : case kExprI32LoadMem16S:
1637 151 : len = DecodeLoadMem(kWasmI32, MachineType::Int16());
1638 151 : break;
1639 : case kExprI32LoadMem16U:
1640 501 : len = DecodeLoadMem(kWasmI32, MachineType::Uint16());
1641 501 : break;
1642 : case kExprI32LoadMem:
1643 9985 : len = DecodeLoadMem(kWasmI32, MachineType::Int32());
1644 9985 : break;
1645 : case kExprI64LoadMem8S:
1646 189 : len = DecodeLoadMem(kWasmI64, MachineType::Int8());
1647 189 : break;
1648 : case kExprI64LoadMem8U:
1649 85 : len = DecodeLoadMem(kWasmI64, MachineType::Uint8());
1650 85 : break;
1651 : case kExprI64LoadMem16S:
1652 129 : len = DecodeLoadMem(kWasmI64, MachineType::Int16());
1653 129 : break;
1654 : case kExprI64LoadMem16U:
1655 105 : len = DecodeLoadMem(kWasmI64, MachineType::Uint16());
1656 105 : break;
1657 : case kExprI64LoadMem32S:
1658 129 : len = DecodeLoadMem(kWasmI64, MachineType::Int32());
1659 129 : break;
1660 : case kExprI64LoadMem32U:
1661 105 : len = DecodeLoadMem(kWasmI64, MachineType::Uint32());
1662 105 : break;
1663 : case kExprI64LoadMem:
1664 23129 : len = DecodeLoadMem(kWasmI64, MachineType::Int64());
1665 23129 : break;
1666 : case kExprF32LoadMem:
1667 3320 : len = DecodeLoadMem(kWasmF32, MachineType::Float32());
1668 3320 : break;
1669 : case kExprF64LoadMem:
1670 3654 : len = DecodeLoadMem(kWasmF64, MachineType::Float64());
1671 3654 : break;
1672 : case kExprI32StoreMem8:
1673 1114 : len = DecodeStoreMem(kWasmI32, MachineType::Int8());
1674 1114 : break;
1675 : case kExprI32StoreMem16:
1676 408 : len = DecodeStoreMem(kWasmI32, MachineType::Int16());
1677 408 : break;
1678 : case kExprI32StoreMem:
1679 1953 : len = DecodeStoreMem(kWasmI32, MachineType::Int32());
1680 1950 : break;
1681 : case kExprI64StoreMem8:
1682 140 : len = DecodeStoreMem(kWasmI64, MachineType::Int8());
1683 140 : break;
1684 : case kExprI64StoreMem16:
1685 240 : len = DecodeStoreMem(kWasmI64, MachineType::Int16());
1686 240 : break;
1687 : case kExprI64StoreMem32:
1688 160 : len = DecodeStoreMem(kWasmI64, MachineType::Int32());
1689 160 : break;
1690 : case kExprI64StoreMem:
1691 21760 : len = DecodeStoreMem(kWasmI64, MachineType::Int64());
1692 21760 : break;
1693 : case kExprF32StoreMem:
1694 640 : len = DecodeStoreMem(kWasmF32, MachineType::Float32());
1695 640 : break;
1696 : case kExprF64StoreMem:
1697 754 : len = DecodeStoreMem(kWasmF64, MachineType::Float64());
1698 754 : break;
1699 : case kExprGrowMemory: {
1700 1319 : if (!CheckHasMemory()) break;
1701 1289 : MemoryIndexOperand<validate> operand(this, this->pc_);
1702 1289 : len = 1 + operand.length;
1703 : DCHECK_NOT_NULL(this->module_);
1704 134572 : if (!VALIDATE(this->module_->is_wasm())) {
1705 : this->error("grow_memory is not supported for asmjs modules");
1706 : break;
1707 : }
1708 1288 : auto value = Pop(0, kWasmI32);
1709 : auto* result = Push(kWasmI32);
1710 2555 : CALL_INTERFACE_IF_REACHABLE(GrowMemory, value, result);
1711 : break;
1712 : }
1713 : case kExprMemorySize: {
1714 660 : if (!CheckHasMemory()) break;
1715 640 : MemoryIndexOperand<validate> operand(this, this->pc_);
1716 : auto* result = Push(kWasmI32);
1717 640 : len = 1 + operand.length;
1718 1270 : CALL_INTERFACE_IF_REACHABLE(CurrentMemoryPages, result);
1719 : break;
1720 : }
1721 : case kExprCallFunction: {
1722 310607 : CallFunctionOperand<validate> operand(this, this->pc_);
1723 310589 : len = 1 + operand.length;
1724 310589 : if (!this->Validate(this->pc_, operand)) break;
1725 : // TODO(clemensh): Better memory management.
1726 : std::vector<Value> args;
1727 310557 : PopArgs(operand.sig, &args);
1728 310550 : auto* returns = PushReturns(operand.sig);
1729 345546 : CALL_INTERFACE_IF_REACHABLE(CallDirect, operand, args.data(),
1730 : returns);
1731 : break;
1732 : }
1733 : case kExprCallIndirect: {
1734 4380 : CallIndirectOperand<validate> operand(this, this->pc_);
1735 4380 : len = 1 + operand.length;
1736 4380 : if (!this->Validate(this->pc_, operand)) break;
1737 4305 : auto index = Pop(0, kWasmI32);
1738 : // TODO(clemensh): Better memory management.
1739 : std::vector<Value> args;
1740 4304 : PopArgs(operand.sig, &args);
1741 4305 : auto* returns = PushReturns(operand.sig);
1742 7000 : CALL_INTERFACE_IF_REACHABLE(CallIndirect, index, operand,
1743 : args.data(), returns);
1744 : break;
1745 : }
1746 : case kSimdPrefix: {
1747 15438 : CHECK_PROTOTYPE_OPCODE(simd);
1748 : len++;
1749 : byte simd_index =
1750 15438 : this->template read_u8<validate>(this->pc_ + 1, "simd index");
1751 15438 : opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
1752 : TRACE(" @%-4d #%-20s|", startrel(this->pc_),
1753 : WasmOpcodes::OpcodeName(opcode));
1754 15438 : len += DecodeSimdOpcode(opcode);
1755 15438 : break;
1756 : }
1757 : case kAtomicPrefix: {
1758 521 : CHECK_PROTOTYPE_OPCODE(threads);
1759 521 : if (!CheckHasSharedMemory()) break;
1760 : len++;
1761 : byte atomic_index =
1762 511 : this->template read_u8<validate>(this->pc_ + 1, "atomic index");
1763 511 : opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_index);
1764 : TRACE(" @%-4d #%-20s|", startrel(this->pc_),
1765 : WasmOpcodes::OpcodeName(opcode));
1766 511 : len += DecodeAtomicOpcode(opcode);
1767 512 : break;
1768 : }
1769 : default: {
1770 : // Deal with special asmjs opcodes.
1771 266566 : if (this->module_ != nullptr && this->module_->is_asm_js()) {
1772 133252 : sig = WasmOpcodes::AsmjsSignature(opcode);
1773 133252 : if (sig) {
1774 133252 : BuildSimpleOperator(opcode, sig);
1775 : }
1776 : } else {
1777 31 : this->error("Invalid opcode");
1778 : return;
1779 : }
1780 : }
1781 : }
1782 : }
1783 :
1784 : #if DEBUG
1785 : if (FLAG_trace_wasm_decoder) {
1786 : PrintF(" ");
1787 : for (Control& c : control_) {
1788 : switch (c.kind) {
1789 : case kControlIf:
1790 : PrintF("I");
1791 : break;
1792 : case kControlBlock:
1793 : PrintF("B");
1794 : break;
1795 : case kControlLoop:
1796 : PrintF("L");
1797 : break;
1798 : case kControlTry:
1799 : PrintF("T");
1800 : break;
1801 : default:
1802 : break;
1803 : }
1804 : PrintF("%u", c.merge.arity);
1805 : if (!c.reachable()) PrintF("%c", c.unreachable() ? '*' : '#');
1806 : }
1807 : PrintF(" | ");
1808 : for (size_t i = 0; i < stack_.size(); ++i) {
1809 : auto& val = stack_[i];
1810 : WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
1811 : if (WasmOpcodes::IsPrefixOpcode(opcode)) {
1812 : opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1));
1813 : }
1814 : PrintF(" %c@%d:%s", WasmOpcodes::ShortNameOf(val.type),
1815 : static_cast<int>(val.pc - this->start_),
1816 : WasmOpcodes::OpcodeName(opcode));
1817 : switch (opcode) {
1818 : case kExprI32Const: {
1819 : ImmI32Operand<validate> operand(this, val.pc);
1820 : PrintF("[%d]", operand.value);
1821 : break;
1822 : }
1823 : case kExprGetLocal:
1824 : case kExprSetLocal:
1825 : case kExprTeeLocal: {
1826 : LocalIndexOperand<Decoder::kValidate> operand(this, val.pc);
1827 : PrintF("[%u]", operand.index);
1828 : break;
1829 : }
1830 : case kExprGetGlobal:
1831 : case kExprSetGlobal: {
1832 : GlobalIndexOperand<validate> operand(this, val.pc);
1833 : PrintF("[%u]", operand.index);
1834 : break;
1835 : }
1836 : default:
1837 : break;
1838 : }
1839 : }
1840 : PrintF("\n");
1841 : }
1842 : #endif
1843 7963801 : this->pc_ += len;
1844 : } // end decode loop
1845 426957 : if (this->pc_ > this->end_ && this->ok()) this->error("Beyond end of code");
1846 : }
1847 :
1848 635235 : void EndControl() {
1849 : DCHECK(!control_.empty());
1850 : auto* current = &control_.back();
1851 1059802 : stack_.resize(current->stack_depth);
1852 1270568 : CALL_INTERFACE_IF_REACHABLE(EndControl, current);
1853 1060029 : current->reachability = kUnreachable;
1854 635462 : }
1855 :
1856 462342 : bool LookupBlockType(BlockTypeOperand<validate>* operand) {
1857 462342 : if (operand->type == kWasmVar) {
1858 266 : if (!VALIDATE(this->module_ &&
1859 : operand->sig_index < this->module_->signatures.size())) {
1860 14 : this->errorf(
1861 : this->pc_, "block type index %u out of bounds (%d signatures)",
1862 : operand->sig_index,
1863 : static_cast<int>(this->module_
1864 : ? this->module_->signatures.size() : 0));
1865 14 : return false;
1866 : }
1867 168 : operand->sig = this->module_->signatures[operand->sig_index];
1868 : }
1869 : return true;
1870 : }
1871 :
1872 480650 : void SetBlockType(Control* c, BlockTypeOperand<validate>& operand) {
1873 462204 : c->merge.arity = operand.out_arity();
1874 462204 : if (c->merge.arity == 1) {
1875 18390 : c->merge.vals.first = Value::New(this->pc_, operand.out_type(0));
1876 443886 : } else if (c->merge.arity > 1) {
1877 128 : c->merge.vals.array = zone_->NewArray<Value>(c->merge.arity);
1878 192 : for (unsigned i = 0; i < c->merge.arity; i++) {
1879 256 : c->merge.vals.array[i] = Value::New(this->pc_, operand.out_type(i));
1880 : }
1881 : }
1882 462204 : }
1883 :
1884 : // TODO(clemensh): Better memory management.
1885 1612296 : void PopArgs(FunctionSig* sig, std::vector<Value>* result) {
1886 : DCHECK(result->empty());
1887 317682 : int count = static_cast<int>(sig->parameter_count());
1888 317682 : result->resize(count);
1889 965001 : for (int i = count - 1; i >= 0; --i) {
1890 1294614 : (*result)[i] = Pop(i, sig->GetParam(i));
1891 : }
1892 317694 : }
1893 :
1894 4406 : ValueType GetReturnType(FunctionSig* sig) {
1895 : DCHECK_GE(1, sig->return_count());
1896 3550 : return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn();
1897 : }
1898 :
1899 867634 : Control* PushControl(Control&& new_control) {
1900 : Reachability reachability =
1901 867634 : control_.empty() ? kReachable : control_.back().innerReachability();
1902 867634 : control_.emplace_back(std::move(new_control));
1903 867608 : Control* c = &control_.back();
1904 867608 : c->reachability = reachability;
1905 867608 : return c;
1906 : }
1907 :
1908 787513 : Control* PushBlock() {
1909 1575026 : return PushControl(Control::Block(this->pc_, stack_size()));
1910 : }
1911 16028 : Control* PushLoop() {
1912 : return PushControl(
1913 48084 : Control::Loop(this->pc_, stack_size(), control_.back().reachable()));
1914 : }
1915 64023 : Control* PushIf() {
1916 128046 : return PushControl(Control::If(this->pc_, stack_size()));
1917 : }
1918 74 : Control* PushTry() {
1919 : // current_catch_ = static_cast<int32_t>(control_.size() - 1);
1920 148 : return PushControl(Control::Try(this->pc_, stack_size()));
1921 : }
1922 :
1923 843145 : void PopControl(Control* c) {
1924 : DCHECK_EQ(c, &control_.back());
1925 1085052 : CALL_INTERFACE_IF_PARENT_REACHABLE(PopControl, c);
1926 1665728 : bool reached = c->is_loop() ? c->reachable() : c->merge.reached;
1927 : control_.pop_back();
1928 : // If the parent block was reachable before, but the popped control does not
1929 : // return to here, this block becomes indirectly unreachable.
1930 840142 : if (!control_.empty() && !reached && control_.back().reachable()) {
1931 50087 : control_.back().reachability = kSpecOnlyReachable;
1932 : }
1933 840142 : }
1934 :
1935 45779 : int DecodeLoadMem(ValueType type, MachineType mem_type) {
1936 45779 : if (!CheckHasMemory()) return 0;
1937 : MemoryAccessOperand<validate> operand(
1938 45738 : this, this->pc_, ElementSizeLog2Of(mem_type.representation()));
1939 :
1940 45742 : auto index = Pop(0, kWasmI32);
1941 : auto* result = Push(type);
1942 66541 : CALL_INTERFACE_IF_REACHABLE(LoadMem, type, mem_type, operand, index,
1943 : result);
1944 45744 : return 1 + operand.length;
1945 : }
1946 :
1947 27162 : int DecodeStoreMem(ValueType type, MachineType mem_type) {
1948 27162 : if (!CheckHasMemory()) return 0;
1949 : MemoryAccessOperand<validate> operand(
1950 27122 : this, this->pc_, ElementSizeLog2Of(mem_type.representation()));
1951 27125 : auto value = Pop(1, type);
1952 27123 : auto index = Pop(0, kWasmI32);
1953 29642 : CALL_INTERFACE_IF_REACHABLE(StoreMem, type, mem_type, operand, index,
1954 : value);
1955 27123 : return 1 + operand.length;
1956 : }
1957 :
1958 12 : int DecodePrefixedLoadMem(ValueType type, MachineType mem_type) {
1959 12 : if (!CheckHasMemory()) return 0;
1960 : MemoryAccessOperand<validate> operand(
1961 12 : this, this->pc_ + 1, ElementSizeLog2Of(mem_type.representation()));
1962 :
1963 12 : auto index = Pop(0, kWasmI32);
1964 : auto* result = Push(type);
1965 24 : CALL_INTERFACE_IF_REACHABLE(LoadMem, type, mem_type, operand, index,
1966 : result);
1967 12 : return operand.length;
1968 : }
1969 :
1970 6 : int DecodePrefixedStoreMem(ValueType type, MachineType mem_type) {
1971 6 : if (!CheckHasMemory()) return 0;
1972 : MemoryAccessOperand<validate> operand(
1973 6 : this, this->pc_ + 1, ElementSizeLog2Of(mem_type.representation()));
1974 6 : auto value = Pop(1, type);
1975 6 : auto index = Pop(0, kWasmI32);
1976 12 : CALL_INTERFACE_IF_REACHABLE(StoreMem, type, mem_type, operand, index,
1977 : value);
1978 6 : return operand.length;
1979 : }
1980 :
1981 12186 : unsigned SimdExtractLane(WasmOpcode opcode, ValueType type) {
1982 12186 : SimdLaneOperand<validate> operand(this, this->pc_);
1983 12186 : if (this->Validate(this->pc_, opcode, operand)) {
1984 12186 : Value inputs[] = {Pop(0, ValueType::kSimd128)};
1985 : auto* result = Push(type);
1986 24372 : CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, operand,
1987 : ArrayVector(inputs), result);
1988 : }
1989 12186 : return operand.length;
1990 : }
1991 :
1992 468 : unsigned SimdReplaceLane(WasmOpcode opcode, ValueType type) {
1993 468 : SimdLaneOperand<validate> operand(this, this->pc_);
1994 468 : if (this->Validate(this->pc_, opcode, operand)) {
1995 : Value inputs[2];
1996 468 : inputs[1] = Pop(1, type);
1997 468 : inputs[0] = Pop(0, ValueType::kSimd128);
1998 : auto* result = Push(ValueType::kSimd128);
1999 936 : CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, operand,
2000 : ArrayVector(inputs), result);
2001 : }
2002 468 : return operand.length;
2003 : }
2004 :
2005 72 : unsigned SimdShiftOp(WasmOpcode opcode) {
2006 72 : SimdShiftOperand<validate> operand(this, this->pc_);
2007 72 : if (this->Validate(this->pc_, opcode, operand)) {
2008 72 : auto input = Pop(0, ValueType::kSimd128);
2009 : auto* result = Push(ValueType::kSimd128);
2010 144 : CALL_INTERFACE_IF_REACHABLE(SimdShiftOp, opcode, operand, input, result);
2011 : }
2012 72 : return operand.length;
2013 : }
2014 :
2015 0 : unsigned Simd8x16ShuffleOp() {
2016 0 : Simd8x16ShuffleOperand<validate> operand(this, this->pc_);
2017 0 : if (this->Validate(this->pc_, operand)) {
2018 0 : auto input1 = Pop(1, ValueType::kSimd128);
2019 0 : auto input0 = Pop(0, ValueType::kSimd128);
2020 : auto* result = Push(ValueType::kSimd128);
2021 0 : CALL_INTERFACE_IF_REACHABLE(Simd8x16ShuffleOp, operand, input0, input1,
2022 : result);
2023 : }
2024 0 : return 16;
2025 : }
2026 :
2027 15438 : unsigned DecodeSimdOpcode(WasmOpcode opcode) {
2028 : unsigned len = 0;
2029 15438 : switch (opcode) {
2030 : case kExprF32x4ExtractLane: {
2031 0 : len = SimdExtractLane(opcode, ValueType::kFloat32);
2032 0 : break;
2033 : }
2034 : case kExprI32x4ExtractLane:
2035 : case kExprI16x8ExtractLane:
2036 : case kExprI8x16ExtractLane: {
2037 12186 : len = SimdExtractLane(opcode, ValueType::kWord32);
2038 12186 : break;
2039 : }
2040 : case kExprF32x4ReplaceLane: {
2041 0 : len = SimdReplaceLane(opcode, ValueType::kFloat32);
2042 0 : break;
2043 : }
2044 : case kExprI32x4ReplaceLane:
2045 : case kExprI16x8ReplaceLane:
2046 : case kExprI8x16ReplaceLane: {
2047 468 : len = SimdReplaceLane(opcode, ValueType::kWord32);
2048 468 : break;
2049 : }
2050 : case kExprI32x4Shl:
2051 : case kExprI32x4ShrS:
2052 : case kExprI32x4ShrU:
2053 : case kExprI16x8Shl:
2054 : case kExprI16x8ShrS:
2055 : case kExprI16x8ShrU:
2056 : case kExprI8x16Shl:
2057 : case kExprI8x16ShrS:
2058 : case kExprI8x16ShrU: {
2059 72 : len = SimdShiftOp(opcode);
2060 72 : break;
2061 : }
2062 : case kExprS8x16Shuffle: {
2063 0 : len = Simd8x16ShuffleOp();
2064 0 : break;
2065 : }
2066 : case kExprS128LoadMem:
2067 12 : len = DecodePrefixedLoadMem(kWasmS128, MachineType::Simd128());
2068 12 : break;
2069 : case kExprS128StoreMem:
2070 6 : len = DecodePrefixedStoreMem(kWasmS128, MachineType::Simd128());
2071 6 : break;
2072 : default: {
2073 5388 : FunctionSig* sig = WasmOpcodes::Signature(opcode);
2074 2694 : if (!VALIDATE(sig != nullptr)) {
2075 0 : this->error("invalid simd opcode");
2076 0 : break;
2077 : }
2078 : std::vector<Value> args;
2079 2694 : PopArgs(sig, &args);
2080 : auto* result =
2081 5388 : sig->return_count() == 0 ? nullptr : Push(GetReturnType(sig));
2082 8082 : CALL_INTERFACE_IF_REACHABLE(SimdOp, opcode, vec2vec(args), result);
2083 : }
2084 : }
2085 15438 : return len;
2086 : }
2087 :
2088 512 : unsigned DecodeAtomicOpcode(WasmOpcode opcode) {
2089 : unsigned len = 0;
2090 : ValueType ret_type;
2091 2518 : FunctionSig* sig = WasmOpcodes::AtomicSignature(opcode);
2092 512 : if (sig != nullptr) {
2093 : MachineType memtype;
2094 512 : switch (opcode) {
2095 : #define CASE_ATOMIC_STORE_OP(Name, Type) \
2096 : case kExpr##Name: { \
2097 : memtype = MachineType::Type(); \
2098 : ret_type = MachineRepresentation::kNone; \
2099 : break; \
2100 : }
2101 16 : ATOMIC_STORE_OP_LIST(CASE_ATOMIC_STORE_OP)
2102 : #undef CASE_ATOMIC_OP
2103 : #define CASE_ATOMIC_OP(Name, Type) \
2104 : case kExpr##Name: { \
2105 : memtype = MachineType::Type(); \
2106 : ret_type = GetReturnType(sig); \
2107 : break; \
2108 : }
2109 428 : ATOMIC_OP_LIST(CASE_ATOMIC_OP)
2110 : #undef CASE_ATOMIC_OP
2111 : default:
2112 0 : this->error("invalid atomic opcode");
2113 : break;
2114 : }
2115 : // TODO(clemensh): Better memory management here.
2116 512 : std::vector<Value> args(sig->parameter_count());
2117 : MemoryAccessOperand<validate> operand(
2118 511 : this, this->pc_ + 1, ElementSizeLog2Of(memtype.representation()));
2119 514 : len += operand.length;
2120 1492 : for (int i = static_cast<int>(sig->parameter_count() - 1); i >= 0; --i) {
2121 1960 : args[i] = Pop(i, sig->GetParam(i));
2122 : }
2123 : auto result = ret_type == MachineRepresentation::kNone
2124 : ? nullptr
2125 940 : : Push(GetReturnType(sig));
2126 1536 : CALL_INTERFACE_IF_REACHABLE(AtomicOp, opcode, vec2vec(args), operand,
2127 : result);
2128 : } else {
2129 0 : this->error("invalid atomic opcode");
2130 : }
2131 512 : return len;
2132 : }
2133 :
2134 744878 : void DoReturn(Control* c, bool implicit) {
2135 : // TODO(clemensh): Optimize memory usage here (it will be mostly 0 or 1
2136 : // returned values).
2137 948950 : int return_count = static_cast<int>(this->sig_->return_count());
2138 744878 : std::vector<Value> values(return_count);
2139 :
2140 : // Pop return values off the stack in reverse order.
2141 949222 : for (int i = return_count - 1; i >= 0; --i) {
2142 612216 : values[i] = Pop(i, this->sig_->GetReturn(i));
2143 : }
2144 :
2145 457655 : if (this->ok() && (c->reachable() || (implicit && c->merge.reached))) {
2146 576990 : CALL_INTERFACE(DoReturn, vec2vec(values), implicit);
2147 : }
2148 :
2149 457638 : EndControl();
2150 745158 : }
2151 :
2152 : inline Value* Push(ValueType type) {
2153 : DCHECK_NE(kWasmStmt, type);
2154 12975199 : stack_.push_back(Value::New(this->pc_, type));
2155 : return &stack_.back();
2156 : }
2157 :
2158 828133 : void PushEndValues(Control* c) {
2159 : DCHECK_EQ(c, &control_.back());
2160 828133 : stack_.resize(c->stack_depth);
2161 828220 : if (c->merge.arity == 1) {
2162 121662 : stack_.push_back(c->merge.vals.first);
2163 : } else {
2164 4241 : for (unsigned i = 0; i < c->merge.arity; i++) {
2165 4241 : stack_.push_back(c->merge.vals.array[i]);
2166 : }
2167 : }
2168 : DCHECK_EQ(c->stack_depth + c->merge.arity, stack_.size());
2169 828256 : }
2170 :
2171 604901 : Value* PushReturns(FunctionSig* sig) {
2172 : size_t return_count = sig->return_count();
2173 314846 : if (return_count == 0) return nullptr;
2174 287995 : size_t old_size = stack_.size();
2175 578041 : for (size_t i = 0; i < return_count; ++i) {
2176 : Push(sig->GetReturn(i));
2177 : }
2178 287986 : return stack_.data() + old_size;
2179 : }
2180 :
2181 4491907 : Value Pop(int index, ValueType expected) {
2182 4453873 : auto val = Pop();
2183 4453908 : if (!VALIDATE(val.type == expected || val.type == kWasmVar ||
2184 : expected == kWasmVar)) {
2185 57051 : this->errorf(val.pc, "%s[%d] expected type %s, found %s of type %s",
2186 : SafeOpcodeNameAt(this->pc_), index,
2187 : WasmOpcodes::TypeName(expected), SafeOpcodeNameAt(val.pc),
2188 : WasmOpcodes::TypeName(val.type));
2189 : }
2190 4453908 : return val;
2191 : }
2192 :
2193 4663093 : Value Pop() {
2194 : DCHECK(!control_.empty());
2195 4661235 : uint32_t limit = control_.back().stack_depth;
2196 9322470 : if (stack_.size() <= limit) {
2197 : // Popping past the current control start in reachable code.
2198 7977 : if (!VALIDATE(control_.back().unreachable())) {
2199 3716 : this->errorf(this->pc_, "%s found empty stack",
2200 : SafeOpcodeNameAt(this->pc_));
2201 : }
2202 7977 : return Value::Unreachable(this->pc_);
2203 : }
2204 4653258 : auto val = stack_.back();
2205 : stack_.pop_back();
2206 4653258 : return val;
2207 : }
2208 :
2209 2997 : int startrel(const byte* ptr) { return static_cast<int>(ptr - this->start_); }
2210 :
2211 1148242 : void FallThruTo(Control* c) {
2212 : DCHECK(!c->is_loop());
2213 : DCHECK_EQ(c, &control_.back());
2214 853159 : if (!TypeCheckFallThru(c)) return;
2215 849586 : if (!c->reachable()) return;
2216 :
2217 135591 : CALL_INTERFACE(FallThruTo, c);
2218 161657 : c->merge.reached = true;
2219 : }
2220 :
2221 1728125 : bool TypeCheckMergeValues(Control* c) {
2222 : DCHECK_GE(stack_.size(), c->stack_depth + c->merge.arity);
2223 : // Typecheck the topmost {c->merge.arity} values on the stack.
2224 1868047 : for (uint32_t i = 0; i < c->merge.arity; ++i) {
2225 : auto& val = GetMergeValueFromStack(c, i);
2226 : auto& old = c->merge[i];
2227 142034 : if (val.type != old.type) {
2228 : // If {val.type} is polymorphic, which results from unreachable, make
2229 : // it more specific by using the merge value's expected type.
2230 : // If it is not polymorphic, this is a type error.
2231 12690 : if (!VALIDATE(val.type == kWasmVar)) {
2232 2112 : this->errorf(
2233 : this->pc_, "type error in merge[%u] (expected %s, got %s)", i,
2234 : WasmOpcodes::TypeName(old.type), WasmOpcodes::TypeName(val.type));
2235 2135 : return false;
2236 : }
2237 10578 : val.type = old.type;
2238 : }
2239 : }
2240 :
2241 : return true;
2242 : }
2243 :
2244 870023 : bool TypeCheckFallThru(Control* c) {
2245 : DCHECK_EQ(c, &control_.back());
2246 : if (!validate) return true;
2247 867708 : uint32_t expected = c->merge.arity;
2248 : DCHECK_GE(stack_.size(), c->stack_depth);
2249 1735416 : uint32_t actual = static_cast<uint32_t>(stack_.size()) - c->stack_depth;
2250 : // Fallthrus must match the arity of the control exactly.
2251 867708 : if (!InsertUnreachablesIfNecessary(expected, actual) || actual > expected) {
2252 4630 : this->errorf(
2253 : this->pc_,
2254 : "expected %u elements on the stack for fallthru to @%d, found %u",
2255 : expected, startrel(c->pc), actual);
2256 2315 : return false;
2257 : }
2258 :
2259 865594 : return TypeCheckMergeValues(c);
2260 : }
2261 :
2262 876021 : bool TypeCheckBreak(Control* c) {
2263 875339 : if (c->is_loop()) {
2264 : // This is the inner loop block, which does not have a value.
2265 : return true;
2266 : }
2267 : // Breaks must have at least the number of values expected; can have more.
2268 863278 : uint32_t expected = c->merge.arity;
2269 : DCHECK_GE(stack_.size(), control_.back().stack_depth);
2270 : uint32_t actual =
2271 2589834 : static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth;
2272 863278 : if (!InsertUnreachablesIfNecessary(expected, actual)) {
2273 1364 : this->errorf(this->pc_,
2274 : "expected %u elements on the stack for br to @%d, found %u",
2275 : expected, startrel(c->pc), actual);
2276 682 : return false;
2277 : }
2278 862597 : return TypeCheckMergeValues(c);
2279 : }
2280 :
2281 1730904 : inline bool InsertUnreachablesIfNecessary(uint32_t expected,
2282 : uint32_t actual) {
2283 1730904 : if (V8_LIKELY(actual >= expected)) {
2284 : return true; // enough actual values are there.
2285 : }
2286 12098 : if (!VALIDATE(control_.back().unreachable())) {
2287 : // There aren't enough values on the stack.
2288 : return false;
2289 : }
2290 : // A slow path. When the actual number of values on the stack is less
2291 : // than the expected number of values and the current control is
2292 : // unreachable, insert unreachable values below the actual values.
2293 : // This simplifies {TypeCheckMergeValues}.
2294 20360 : auto pos = stack_.begin() + (stack_.size() - actual);
2295 28871 : stack_.insert(pos, (expected - actual), Value::Unreachable(this->pc_));
2296 10178 : return true;
2297 : }
2298 :
2299 21654 : virtual void onFirstError() {
2300 21654 : this->end_ = this->pc_; // Terminate decoding loop.
2301 : TRACE(" !%s\n", this->error_msg_.c_str());
2302 : CALL_INTERFACE(OnFirstError);
2303 21654 : }
2304 :
2305 8191786 : inline void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
2306 1763786 : switch (sig->parameter_count()) {
2307 : case 1: {
2308 627210 : auto val = Pop(0, sig->GetParam(0));
2309 : auto* ret =
2310 995838 : sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
2311 736292 : CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, sig, val, ret);
2312 : break;
2313 : }
2314 : case 2: {
2315 1136576 : auto rval = Pop(1, sig->GetParam(1));
2316 1136577 : auto lval = Pop(0, sig->GetParam(0));
2317 : auto* ret =
2318 2106460 : sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
2319 1938771 : CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, sig, lval, rval, ret);
2320 : break;
2321 : }
2322 : default:
2323 0 : UNREACHABLE();
2324 : }
2325 1763814 : }
2326 : };
2327 :
2328 : #undef CALL_INTERFACE
2329 : #undef CALL_INTERFACE_IF_REACHABLE
2330 : #undef CALL_INTERFACE_IF_PARENT_REACHABLE
2331 :
2332 : class EmptyInterface {
2333 : public:
2334 : static constexpr wasm::Decoder::ValidateFlag validate =
2335 : wasm::Decoder::kValidate;
2336 : using Value = ValueBase;
2337 : using Control = ControlBase<Value>;
2338 : using Decoder = WasmFullDecoder<validate, EmptyInterface>;
2339 :
2340 : #define DEFINE_EMPTY_CALLBACK(name, ...) \
2341 : void name(Decoder* decoder, ##__VA_ARGS__) {}
2342 : INTERFACE_FUNCTIONS(DEFINE_EMPTY_CALLBACK)
2343 : #undef DEFINE_EMPTY_CALLBACK
2344 : };
2345 :
2346 : #undef TRACE
2347 : #undef VALIDATE
2348 : #undef CHECK_PROTOTYPE_OPCODE
2349 : #undef OPCODE_ERROR
2350 :
2351 : } // namespace wasm
2352 : } // namespace internal
2353 : } // namespace v8
2354 :
2355 : #endif // V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
|