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