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(AtomicWake, 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 24222174 : inline LocalIndexImmediate(Decoder* decoder, const byte* pc) {
141 48444424 : 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 1065 : inline ExceptionIndexImmediate(Decoder* decoder, const byte* pc) {
152 2131 : 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 23305242 : 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 210560 : 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 675223 : inline ImmF32Immediate(Decoder* decoder, const byte* pc) {
179 : // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
180 1350446 : uint32_t tmp = decoder->read_u32<validate>(pc + 1, "immf32");
181 675223 : memcpy(&value, &tmp, sizeof(value));
182 675223 : }
183 : };
184 :
185 : template <Decoder::ValidateFlag validate>
186 : struct ImmF64Immediate {
187 : double value;
188 : uint32_t length = 8;
189 246183 : inline ImmF64Immediate(Decoder* decoder, const byte* pc) {
190 : // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
191 492366 : uint64_t tmp = decoder->read_u64<validate>(pc + 1, "immf64");
192 246183 : memcpy(&value, &tmp, sizeof(value));
193 246183 : }
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 96585 : inline GlobalIndexImmediate(Decoder* decoder, const byte* pc) {
204 193170 : index = decoder->read_u32v<validate>(pc + 1, &length, "global index");
205 58358 : }
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 4900576 : inline BlockTypeImmediate(const WasmFeatures& enabled, Decoder* decoder,
216 4900576 : const byte* pc) {
217 4900576 : uint8_t val = decoder->read_u8<validate>(pc + 1, "block type");
218 4900577 : if (!decode_local_type(val, &type)) {
219 : // Handle multi-value blocks.
220 276 : if (!VALIDATE(enabled.mv)) {
221 49 : decoder->error(pc + 1, "invalid block type");
222 49 : return;
223 : }
224 227 : 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 4900582 : inline bool decode_local_type(uint8_t val, ValueType* result) {
238 4900582 : switch (static_cast<ValueTypeCode>(val)) {
239 : case kLocalVoid:
240 4817218 : *result = kWasmStmt;
241 : return true;
242 : case kLocalI32:
243 35934 : *result = kWasmI32;
244 : return true;
245 : case kLocalI64:
246 1519 : *result = kWasmI64;
247 : return true;
248 : case kLocalF32:
249 2557 : *result = kWasmF32;
250 : return true;
251 : case kLocalF64:
252 2619 : *result = kWasmF64;
253 : return true;
254 : case kLocalS128:
255 8 : *result = kWasmS128;
256 : return true;
257 : case kLocalAnyFunc:
258 0 : *result = kWasmAnyFunc;
259 : return true;
260 : case kLocalAnyRef:
261 59 : *result = kWasmAnyRef;
262 : return true;
263 : default:
264 40668 : *result = kWasmVar;
265 : return false;
266 : }
267 : }
268 :
269 : uint32_t in_arity() const {
270 392696 : if (type != kWasmVar) return 0;
271 243 : return static_cast<uint32_t>(sig->parameter_count());
272 : }
273 : uint32_t out_arity() const {
274 454307 : if (type == kWasmStmt) return 0;
275 29521 : if (type != kWasmVar) return 1;
276 267 : 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 28651 : 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 747470 : 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 10144 : inline CallIndirectImmediate(Decoder* decoder, const byte* pc) {
306 10144 : uint32_t len = 0;
307 20288 : sig_index = decoder->read_u32v<validate>(pc + 1, &len, "signature index");
308 10145 : if (!VALIDATE(decoder->ok())) return;
309 19521 : table_index = decoder->read_u8<validate>(pc + 1 + len, "table index");
310 9378 : if (!VALIDATE(table_index == 0)) {
311 112 : decoder->errorf(pc + 1 + len, "expected table index 0, found %u",
312 56 : table_index);
313 : }
314 10143 : length = 1 + len;
315 : }
316 : };
317 :
318 : template <Decoder::ValidateFlag validate>
319 : struct CallFunctionImmediate {
320 : uint32_t index;
321 : FunctionSig* sig = nullptr;
322 : uint32_t length;
323 850938 : inline CallFunctionImmediate(Decoder* decoder, const byte* pc) {
324 1701877 : 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 : inline MemoryIndexImmediate() = default;
333 4455 : inline MemoryIndexImmediate(Decoder* decoder, const byte* pc) {
334 8910 : index = decoder->read_u8<validate>(pc + 1, "memory index");
335 4455 : if (!VALIDATE(index == 0)) {
336 256 : decoder->errorf(pc + 1, "expected memory index 0, found %u", index);
337 : }
338 4455 : }
339 : };
340 :
341 : template <Decoder::ValidateFlag validate>
342 : struct TableIndexImmediate {
343 : uint32_t index = 0;
344 : unsigned length = 1;
345 : inline TableIndexImmediate() = default;
346 24 : inline TableIndexImmediate(Decoder* decoder, const byte* pc) {
347 580 : index = decoder->read_u8<validate>(pc + 1, "table index");
348 : }
349 : };
350 :
351 : template <Decoder::ValidateFlag validate>
352 : struct BranchTableImmediate {
353 : uint32_t table_count;
354 : const byte* start;
355 : const byte* table;
356 243321 : inline BranchTableImmediate(Decoder* decoder, const byte* pc) {
357 : DCHECK_EQ(kExprBrTable, decoder->read_u8<validate>(pc, "opcode"));
358 243321 : start = pc + 1;
359 243321 : uint32_t len = 0;
360 243321 : table_count = decoder->read_u32v<validate>(pc + 1, &len, "table count");
361 243321 : table = pc + 1 + len;
362 243321 : }
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 1798906 : bool has_next() { return VALIDATE(decoder_->ok()) && index_ <= table_count_; }
371 1958579 : uint32_t next() {
372 : DCHECK(has_next());
373 1958579 : index_++;
374 : uint32_t length;
375 : uint32_t result =
376 1958579 : decoder_->read_u32v<validate>(pc_, &length, "branch table entry");
377 1958591 : pc_ += length;
378 1958591 : return result;
379 : }
380 : // length, including the length of the {BranchTableImmediate}, but not the
381 : // opcode.
382 37554 : uint32_t length() {
383 50215 : while (has_next()) next();
384 16609 : 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 253936 : 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 6784322 : inline MemoryAccessImmediate(Decoder* decoder, const byte* pc,
409 6784322 : uint32_t max_alignment) {
410 : uint32_t alignment_length;
411 13568674 : alignment =
412 : decoder->read_u32v<validate>(pc + 1, &alignment_length, "alignment");
413 509950 : if (!VALIDATE(alignment <= max_alignment)) {
414 942 : decoder->errorf(pc + 1,
415 : "invalid alignment; expected maximum alignment is %u, "
416 : "actual alignment is %u",
417 : max_alignment, alignment);
418 : }
419 6785288 : if (!VALIDATE(decoder->ok())) return;
420 : uint32_t offset_length;
421 13566798 : offset = decoder->read_u32v<validate>(pc + 1 + alignment_length,
422 : &offset_length, "offset");
423 6783396 : length = alignment_length + offset_length;
424 : }
425 : };
426 :
427 : // Immediate for SIMD lane operations.
428 : template <Decoder::ValidateFlag validate>
429 : struct SimdLaneImmediate {
430 : uint8_t lane;
431 : uint32_t length = 1;
432 :
433 18676 : inline SimdLaneImmediate(Decoder* decoder, const byte* pc) {
434 3209700 : lane = decoder->read_u8<validate>(pc + 2, "lane");
435 : }
436 : };
437 :
438 : // Immediate for SIMD shift operations.
439 : template <Decoder::ValidateFlag validate>
440 : struct SimdShiftImmediate {
441 : uint8_t shift;
442 : uint32_t length = 1;
443 :
444 1272 : inline SimdShiftImmediate(Decoder* decoder, const byte* pc) {
445 26496 : shift = decoder->read_u8<validate>(pc + 2, "shift");
446 : }
447 : };
448 :
449 : // Immediate for SIMD S8x16 shuffle operations.
450 : template <Decoder::ValidateFlag validate>
451 : struct Simd8x16ShuffleImmediate {
452 : uint8_t shuffle[kSimd128Size] = {0};
453 :
454 26513 : inline Simd8x16ShuffleImmediate(Decoder* decoder, const byte* pc) {
455 438737 : for (uint32_t i = 0; i < kSimd128Size; ++i) {
456 656898 : shuffle[i] = decoder->read_u8<validate>(pc + 2 + i, "shuffle");
457 247250 : if (!VALIDATE(decoder->ok())) return;
458 : }
459 : }
460 : };
461 :
462 : template <Decoder::ValidateFlag validate>
463 : struct MemoryInitImmediate {
464 : uint32_t data_segment_index = 0;
465 : MemoryIndexImmediate<validate> memory;
466 : unsigned length = 0;
467 :
468 78 : inline MemoryInitImmediate(Decoder* decoder, const byte* pc) {
469 78 : uint32_t len = 0;
470 156 : data_segment_index =
471 : decoder->read_i32v<validate>(pc + 2, &len, "data segment index");
472 79 : if (!VALIDATE(decoder->ok())) return;
473 77 : memory = MemoryIndexImmediate<validate>(decoder, pc + 1 + len);
474 77 : length = len + memory.length;
475 : }
476 : };
477 :
478 : template <Decoder::ValidateFlag validate>
479 : struct DataDropImmediate {
480 : uint32_t index;
481 : unsigned length;
482 :
483 : inline DataDropImmediate(Decoder* decoder, const byte* pc) {
484 84 : index = decoder->read_i32v<validate>(pc + 2, &length, "data segment index");
485 : }
486 : };
487 :
488 : template <Decoder::ValidateFlag validate>
489 : struct MemoryCopyImmediate {
490 : MemoryIndexImmediate<validate> memory_src;
491 : MemoryIndexImmediate<validate> memory_dst;
492 : unsigned length = 0;
493 :
494 50 : inline MemoryCopyImmediate(Decoder* decoder, const byte* pc) {
495 50 : memory_src = MemoryIndexImmediate<validate>(decoder, pc + 1);
496 50 : if (!VALIDATE(decoder->ok())) return;
497 50 : memory_dst =
498 50 : MemoryIndexImmediate<validate>(decoder, pc + 1 + memory_src.length);
499 50 : if (!VALIDATE(decoder->ok())) return;
500 50 : length = memory_src.length + memory_dst.length;
501 : }
502 : };
503 :
504 : template <Decoder::ValidateFlag validate>
505 : struct TableInitImmediate {
506 : uint32_t elem_segment_index = 0;
507 : TableIndexImmediate<validate> table;
508 : unsigned length = 0;
509 :
510 56 : inline TableInitImmediate(Decoder* decoder, const byte* pc) {
511 56 : uint32_t len = 0;
512 111 : elem_segment_index =
513 : decoder->read_i32v<validate>(pc + 2, &len, "elem segment index");
514 56 : if (!VALIDATE(decoder->ok())) return;
515 108 : table = TableIndexImmediate<validate>(decoder, pc + 1 + len);
516 54 : length = len + table.length;
517 : }
518 : };
519 :
520 : template <Decoder::ValidateFlag validate>
521 : struct ElemDropImmediate {
522 : uint32_t index;
523 : unsigned length;
524 :
525 : inline ElemDropImmediate(Decoder* decoder, const byte* pc) {
526 70 : index = decoder->read_i32v<validate>(pc + 2, &length, "elem segment index");
527 : }
528 : };
529 :
530 : template <Decoder::ValidateFlag validate>
531 : struct TableCopyImmediate {
532 : TableIndexImmediate<validate> table_src;
533 : TableIndexImmediate<validate> table_dst;
534 : unsigned length = 0;
535 :
536 106 : inline TableCopyImmediate(Decoder* decoder, const byte* pc) {
537 106 : table_src = TableIndexImmediate<validate>(decoder, pc + 1);
538 106 : if (!VALIDATE(decoder->ok())) return;
539 212 : table_dst =
540 : TableIndexImmediate<validate>(decoder, pc + 1 + table_src.length);
541 106 : if (!VALIDATE(decoder->ok())) return;
542 106 : length = table_src.length + table_dst.length;
543 : }
544 : };
545 :
546 : // An entry on the value stack.
547 : struct ValueBase {
548 : const byte* pc = nullptr;
549 : ValueType type = kWasmStmt;
550 :
551 7668601 : ValueBase(const byte* pc, ValueType type) : pc(pc), type(type) {}
552 : };
553 :
554 : template <typename Value>
555 : struct Merge {
556 : uint32_t arity = 0;
557 : union { // Either multiple values or a single value.
558 : Value* array;
559 : Value first;
560 : } vals = {nullptr}; // Initialize {array} with {nullptr}.
561 :
562 : // Tracks whether this merge was ever reached. Uses precise reachability, like
563 : // Reachability::kReachable.
564 : bool reached;
565 :
566 1648931 : Merge(bool reached = false) : reached(reached) {}
567 :
568 : Value& operator[](uint32_t i) {
569 : DCHECK_GT(arity, i);
570 1016516 : return arity == 1 ? vals.first : vals.array[i];
571 : }
572 : };
573 :
574 : enum ControlKind : uint8_t {
575 : kControlIf,
576 : kControlIfElse,
577 : kControlBlock,
578 : kControlLoop,
579 : kControlTry,
580 : kControlTryCatch
581 : };
582 :
583 : enum Reachability : uint8_t {
584 : // reachable code.
585 : kReachable,
586 : // reachable code in unreachable block (implies normal validation).
587 : kSpecOnlyReachable,
588 : // code unreachable in its own block (implies polymorphic validation).
589 : kUnreachable
590 : };
591 :
592 : // An entry on the control stack (i.e. if, block, loop, or try).
593 : template <typename Value>
594 : struct ControlBase {
595 : ControlKind kind = kControlBlock;
596 : uint32_t stack_depth = 0; // stack height at the beginning of the construct.
597 : const uint8_t* pc = nullptr;
598 : Reachability reachability = kReachable;
599 :
600 : // Values merged into the start or end of this control construct.
601 : Merge<Value> start_merge;
602 : Merge<Value> end_merge;
603 :
604 : MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ControlBase);
605 :
606 : ControlBase(ControlKind kind, uint32_t stack_depth, const uint8_t* pc,
607 : Reachability reachability)
608 : : kind(kind),
609 : stack_depth(stack_depth),
610 : pc(pc),
611 : reachability(reachability),
612 1648931 : start_merge(reachability == kReachable) {}
613 :
614 : // Check whether the current block is reachable.
615 : bool reachable() const { return reachability == kReachable; }
616 :
617 : // Check whether the rest of the block is unreachable.
618 : // Note that this is different from {!reachable()}, as there is also the
619 : // "indirect unreachable state", for which both {reachable()} and
620 : // {unreachable()} return false.
621 12929 : bool unreachable() const { return reachability == kUnreachable; }
622 :
623 : // Return the reachability of new control structs started in this block.
624 : Reachability innerReachability() const {
625 414126 : return reachability == kReachable ? kReachable : kSpecOnlyReachable;
626 : }
627 :
628 21275 : bool is_if() const { return is_onearmed_if() || is_if_else(); }
629 : bool is_onearmed_if() const { return kind == kControlIf; }
630 : bool is_if_else() const { return kind == kControlIfElse; }
631 : bool is_block() const { return kind == kControlBlock; }
632 : bool is_loop() const { return kind == kControlLoop; }
633 : bool is_incomplete_try() const { return kind == kControlTry; }
634 : bool is_try_catch() const { return kind == kControlTryCatch; }
635 532 : bool is_try() const { return is_incomplete_try() || is_try_catch(); }
636 :
637 1141887 : inline Merge<Value>* br_merge() {
638 1262186 : return is_loop() ? &this->start_merge : &this->end_merge;
639 : }
640 : };
641 :
642 : // This is the list of callback functions that an interface for the
643 : // WasmFullDecoder should implement.
644 : // F(Name, args...)
645 : #define INTERFACE_FUNCTIONS(F) \
646 : /* General: */ \
647 : F(StartFunction) \
648 : F(StartFunctionBody, Control* block) \
649 : F(FinishFunction) \
650 : F(OnFirstError) \
651 : F(NextInstruction, WasmOpcode) \
652 : /* Control: */ \
653 : F(Block, Control* block) \
654 : F(Loop, Control* block) \
655 : F(Try, Control* block) \
656 : F(Catch, Control* block, Value* exception) \
657 : F(If, const Value& cond, Control* if_block) \
658 : F(FallThruTo, Control* c) \
659 : F(PopControl, Control* block) \
660 : F(EndControl, Control* block) \
661 : /* Instructions: */ \
662 : F(UnOp, WasmOpcode opcode, const Value& value, Value* result) \
663 : F(BinOp, WasmOpcode opcode, const Value& lhs, const Value& rhs, \
664 : Value* result) \
665 : F(I32Const, Value* result, int32_t value) \
666 : F(I64Const, Value* result, int64_t value) \
667 : F(F32Const, Value* result, float value) \
668 : F(F64Const, Value* result, double value) \
669 : F(RefNull, Value* result) \
670 : F(Drop, const Value& value) \
671 : F(DoReturn, Vector<Value> values) \
672 : F(GetLocal, Value* result, const LocalIndexImmediate<validate>& imm) \
673 : F(SetLocal, const Value& value, const LocalIndexImmediate<validate>& imm) \
674 : F(TeeLocal, const Value& value, Value* result, \
675 : const LocalIndexImmediate<validate>& imm) \
676 : F(GetGlobal, Value* result, const GlobalIndexImmediate<validate>& imm) \
677 : F(SetGlobal, const Value& value, const GlobalIndexImmediate<validate>& imm) \
678 : F(GetTable, const Value& index, Value* result, \
679 : const TableIndexImmediate<validate>& imm) \
680 : F(SetTable, const Value& index, const Value& value, \
681 : const TableIndexImmediate<validate>& imm) \
682 : F(Unreachable) \
683 : F(Select, const Value& cond, const Value& fval, const Value& tval, \
684 : Value* result) \
685 : F(Br, Control* target) \
686 : F(BrIf, const Value& cond, uint32_t depth) \
687 : F(BrTable, const BranchTableImmediate<validate>& imm, const Value& key) \
688 : F(Else, Control* if_block) \
689 : F(LoadMem, LoadType type, const MemoryAccessImmediate<validate>& imm, \
690 : const Value& index, Value* result) \
691 : F(StoreMem, StoreType type, const MemoryAccessImmediate<validate>& imm, \
692 : const Value& index, const Value& value) \
693 : F(CurrentMemoryPages, Value* result) \
694 : F(MemoryGrow, const Value& value, Value* result) \
695 : F(CallDirect, const CallFunctionImmediate<validate>& imm, \
696 : const Value args[], Value returns[]) \
697 : F(CallIndirect, const Value& index, \
698 : const CallIndirectImmediate<validate>& imm, const Value args[], \
699 : Value returns[]) \
700 : F(ReturnCall, const CallFunctionImmediate<validate>& imm, \
701 : const Value args[]) \
702 : F(ReturnCallIndirect, const Value& index, \
703 : const CallIndirectImmediate<validate>& imm, const Value args[]) \
704 : F(SimdOp, WasmOpcode opcode, Vector<Value> args, Value* result) \
705 : F(SimdLaneOp, WasmOpcode opcode, const SimdLaneImmediate<validate>& imm, \
706 : const Vector<Value> inputs, Value* result) \
707 : F(SimdShiftOp, WasmOpcode opcode, const SimdShiftImmediate<validate>& imm, \
708 : const Value& input, Value* result) \
709 : F(Simd8x16ShuffleOp, const Simd8x16ShuffleImmediate<validate>& imm, \
710 : const Value& input0, const Value& input1, Value* result) \
711 : F(Throw, const ExceptionIndexImmediate<validate>& imm, \
712 : const Vector<Value>& args) \
713 : F(Rethrow, const Value& exception) \
714 : F(BrOnException, const Value& exception, \
715 : const ExceptionIndexImmediate<validate>& imm, uint32_t depth, \
716 : Vector<Value> values) \
717 : F(AtomicOp, WasmOpcode opcode, Vector<Value> args, \
718 : const MemoryAccessImmediate<validate>& imm, Value* result) \
719 : F(MemoryInit, const MemoryInitImmediate<validate>& imm, const Value& dst, \
720 : const Value& src, const Value& size) \
721 : F(DataDrop, const DataDropImmediate<validate>& imm) \
722 : F(MemoryCopy, const MemoryCopyImmediate<validate>& imm, const Value& dst, \
723 : const Value& src, const Value& size) \
724 : F(MemoryFill, const MemoryIndexImmediate<validate>& imm, const Value& dst, \
725 : const Value& value, const Value& size) \
726 : F(TableInit, const TableInitImmediate<validate>& imm, Vector<Value> args) \
727 : F(ElemDrop, const ElemDropImmediate<validate>& imm) \
728 : F(TableCopy, const TableCopyImmediate<validate>& imm, Vector<Value> args)
729 :
730 : // Generic Wasm bytecode decoder with utilities for decoding immediates,
731 : // lengths, etc.
732 : template <Decoder::ValidateFlag validate>
733 3296829 : class WasmDecoder : public Decoder {
734 : public:
735 : WasmDecoder(const WasmModule* module, const WasmFeatures& enabled,
736 : WasmFeatures* detected, FunctionSig* sig, const byte* start,
737 : const byte* end, uint32_t buffer_offset = 0)
738 : : Decoder(start, end, buffer_offset),
739 : module_(module),
740 : enabled_(enabled),
741 : detected_(detected),
742 : sig_(sig),
743 3296845 : local_types_(nullptr) {}
744 : const WasmModule* module_;
745 : const WasmFeatures enabled_;
746 : WasmFeatures* detected_;
747 : FunctionSig* sig_;
748 :
749 : ZoneVector<ValueType>* local_types_;
750 :
751 : uint32_t total_locals() const {
752 : return local_types_ == nullptr
753 : ? 0
754 2946428 : : static_cast<uint32_t>(local_types_->size());
755 : }
756 :
757 1673004 : static bool DecodeLocals(const WasmFeatures& enabled, Decoder* decoder,
758 : const FunctionSig* sig,
759 : ZoneVector<ValueType>* type_list) {
760 : DCHECK_NOT_NULL(type_list);
761 : DCHECK_EQ(0, type_list->size());
762 : // Initialize from signature.
763 1623435 : if (sig != nullptr) {
764 1305976 : type_list->assign(sig->parameters().begin(), sig->parameters().end());
765 : }
766 : // Decode local declarations, if any.
767 : uint32_t entries = decoder->consume_u32v("local decls count");
768 1623590 : if (decoder->failed()) return false;
769 :
770 : TRACE("local decls count: %u\n", entries);
771 1771986 : while (entries-- > 0 && VALIDATE(decoder->ok()) && decoder->more()) {
772 : uint32_t count = decoder->consume_u32v("local count");
773 49567 : if (decoder->failed()) return false;
774 :
775 : DCHECK_LE(type_list->size(), kV8MaxWasmFunctionLocals);
776 98972 : if (count > kV8MaxWasmFunctionLocals - type_list->size()) {
777 43 : decoder->error(decoder->pc() - 1, "local count too large");
778 43 : return false;
779 : }
780 : byte code = decoder->consume_u8("local type");
781 49443 : if (decoder->failed()) return false;
782 :
783 : ValueType type;
784 49443 : switch (code) {
785 : case kLocalI32:
786 23483 : type = kWasmI32;
787 23483 : break;
788 : case kLocalI64:
789 18973 : type = kWasmI64;
790 18973 : break;
791 : case kLocalF32:
792 1337 : type = kWasmF32;
793 1337 : break;
794 : case kLocalF64:
795 2172 : type = kWasmF64;
796 2172 : break;
797 : case kLocalAnyRef:
798 34 : if (enabled.anyref) {
799 34 : type = kWasmAnyRef;
800 34 : break;
801 : }
802 0 : decoder->error(decoder->pc() - 1, "invalid local type");
803 0 : return false;
804 : case kLocalAnyFunc:
805 64 : if (enabled.anyref) {
806 64 : type = kWasmAnyFunc;
807 64 : break;
808 : }
809 0 : decoder->error(decoder->pc() - 1,
810 : "local type 'anyfunc' is not enabled with "
811 0 : "--experimental-wasm-anyref");
812 0 : return false;
813 : case kLocalExceptRef:
814 129 : if (enabled.eh) {
815 129 : type = kWasmExceptRef;
816 129 : break;
817 : }
818 0 : decoder->error(decoder->pc() - 1, "invalid local type");
819 0 : return false;
820 : case kLocalS128:
821 3220 : if (enabled.simd) {
822 3212 : type = kWasmS128;
823 3212 : break;
824 : }
825 : V8_FALLTHROUGH;
826 : default:
827 39 : decoder->error(decoder->pc() - 1, "invalid local type");
828 38 : return false;
829 : }
830 49404 : type_list->insert(type_list->end(), count, type);
831 : }
832 : DCHECK(decoder->ok());
833 : return true;
834 : }
835 :
836 1602417 : static BitVector* AnalyzeLoopAssignment(Decoder* decoder, const byte* pc,
837 : uint32_t locals_count, Zone* zone) {
838 9168 : if (pc >= decoder->end()) return nullptr;
839 9167 : if (*pc != kExprLoop) return nullptr;
840 :
841 : // The number of locals_count is augmented by 2 so that 'locals_count - 2'
842 : // can be used to track mem_size, and 'locals_count - 1' to track mem_start.
843 121862 : BitVector* assigned = new (zone) BitVector(locals_count, zone);
844 : int depth = 0;
845 : // Iteratively process all AST nodes nested inside the loop.
846 3195648 : while (pc < decoder->end() && VALIDATE(decoder->ok())) {
847 1593242 : WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
848 : uint32_t length = 1;
849 1593242 : switch (opcode) {
850 : case kExprLoop:
851 : case kExprIf:
852 : case kExprBlock:
853 : case kExprTry:
854 83963 : length = OpcodeLength(decoder, pc);
855 83963 : depth++;
856 83963 : break;
857 : case kExprSetLocal: // fallthru
858 : case kExprTeeLocal: {
859 : LocalIndexImmediate<validate> imm(decoder, pc);
860 112695 : if (assigned->length() > 0 &&
861 : imm.index < static_cast<uint32_t>(assigned->length())) {
862 : // Unverified code might have an out-of-bounds index.
863 112694 : assigned->Add(imm.index);
864 : }
865 112695 : length = 1 + imm.length;
866 : break;
867 : }
868 : case kExprMemoryGrow:
869 : case kExprCallFunction:
870 : case kExprCallIndirect:
871 : case kExprReturnCall:
872 : case kExprReturnCallIndirect:
873 : // Add instance cache nodes to the assigned set.
874 : // TODO(titzer): make this more clear.
875 18210 : assigned->Add(locals_count - 1);
876 18210 : length = OpcodeLength(decoder, pc);
877 18210 : break;
878 : case kExprEnd:
879 83951 : depth--;
880 83951 : break;
881 : default:
882 1294423 : length = OpcodeLength(decoder, pc);
883 1294433 : break;
884 : }
885 1593252 : if (depth <= 0) break;
886 1584092 : pc += length;
887 : }
888 9167 : return VALIDATE(decoder->ok()) ? assigned : nullptr;
889 : }
890 :
891 2910150 : inline bool Validate(const byte* pc, LocalIndexImmediate<validate>& imm) {
892 2910150 : if (!VALIDATE(imm.index < total_locals())) {
893 523 : errorf(pc + 1, "invalid local index: %u", imm.index);
894 522 : return false;
895 : }
896 2909067 : imm.type = local_types_ ? local_types_->at(imm.index) : kWasmStmt;
897 1454552 : return true;
898 : }
899 :
900 : inline bool Complete(const byte* pc, ExceptionIndexImmediate<validate>& imm) {
901 3080 : if (!VALIDATE(module_ != nullptr &&
902 : imm.index < module_->exceptions.size())) {
903 : return false;
904 : }
905 2076 : imm.exception = &module_->exceptions[imm.index];
906 : return true;
907 : }
908 :
909 1027 : inline bool Validate(const byte* pc, ExceptionIndexImmediate<validate>& imm) {
910 1027 : if (!Complete(pc, imm)) {
911 1 : errorf(pc + 1, "Invalid exception index: %u", imm.index);
912 1 : return false;
913 : }
914 : return true;
915 : }
916 :
917 54512 : inline bool Validate(const byte* pc, GlobalIndexImmediate<validate>& imm) {
918 163509 : if (!VALIDATE(module_ != nullptr && imm.index < module_->globals.size())) {
919 24 : errorf(pc + 1, "invalid global index: %u", imm.index);
920 24 : return false;
921 : }
922 108976 : imm.global = &module_->globals[imm.index];
923 54488 : imm.type = imm.global->type;
924 54488 : return true;
925 : }
926 :
927 51 : inline bool CanTailCall(FunctionSig* tgt_sig) {
928 17 : if (tgt_sig == nullptr) return false;
929 34 : size_t num_returns = sig_->return_count();
930 17 : if (num_returns != tgt_sig->return_count()) return false;
931 13 : for (size_t i = 0; i < num_returns; ++i) {
932 17 : if (sig_->GetReturn(i) != tgt_sig->GetReturn(i)) return false;
933 : }
934 : return true;
935 : }
936 :
937 : inline bool Complete(const byte* pc, CallFunctionImmediate<validate>& imm) {
938 797037 : if (!VALIDATE(module_ != nullptr &&
939 : imm.index < module_->functions.size())) {
940 : return false;
941 : }
942 536024 : imm.sig = module_->functions[imm.index].sig;
943 : return true;
944 : }
945 :
946 265702 : inline bool Validate(const byte* pc, CallFunctionImmediate<validate>& imm) {
947 265702 : if (Complete(pc, imm)) {
948 : return true;
949 : }
950 72 : errorf(pc + 1, "invalid function index: %u", imm.index);
951 72 : return false;
952 : }
953 :
954 : inline bool Complete(const byte* pc, CallIndirectImmediate<validate>& imm) {
955 24944 : if (!VALIDATE(module_ != nullptr &&
956 : imm.sig_index < module_->signatures.size())) {
957 : return false;
958 : }
959 17012 : imm.sig = module_->signatures[imm.sig_index];
960 : return true;
961 : }
962 :
963 8369 : inline bool Validate(const byte* pc, CallIndirectImmediate<validate>& imm) {
964 16737 : if (!VALIDATE(module_ != nullptr && !module_->tables.empty())) {
965 30 : error("function table has to exist to execute call_indirect");
966 30 : return false;
967 : }
968 8339 : if (!Complete(pc, imm)) {
969 73 : errorf(pc + 1, "invalid signature index: #%u", imm.sig_index);
970 73 : return false;
971 : }
972 : return true;
973 : }
974 :
975 : inline bool Validate(const byte* pc, BranchDepthImmediate<validate>& imm,
976 : size_t control_depth) {
977 270494 : if (!VALIDATE(imm.depth < control_depth)) {
978 630 : errorf(pc + 1, "invalid branch depth: %u", imm.depth);
979 : return false;
980 : }
981 : return true;
982 : }
983 :
984 12758 : bool Validate(const byte* pc, BranchTableImmediate<validate>& imm,
985 : size_t block_depth) {
986 12758 : if (!VALIDATE(imm.table_count < kV8MaxWasmFunctionSize)) {
987 16 : errorf(pc + 1, "invalid table count (> max function size): %u",
988 : imm.table_count);
989 : return false;
990 : }
991 12742 : return checkAvailable(imm.table_count);
992 : }
993 :
994 18676 : inline bool Validate(const byte* pc, WasmOpcode opcode,
995 : SimdLaneImmediate<validate>& imm) {
996 : uint8_t num_lanes = 0;
997 18676 : switch (opcode) {
998 : case kExprF32x4ExtractLane:
999 : case kExprF32x4ReplaceLane:
1000 : case kExprI32x4ExtractLane:
1001 : case kExprI32x4ReplaceLane:
1002 : num_lanes = 4;
1003 : break;
1004 : case kExprI16x8ExtractLane:
1005 : case kExprI16x8ReplaceLane:
1006 : num_lanes = 8;
1007 : break;
1008 : case kExprI8x16ExtractLane:
1009 : case kExprI8x16ReplaceLane:
1010 : num_lanes = 16;
1011 : break;
1012 : default:
1013 0 : UNREACHABLE();
1014 : break;
1015 : }
1016 18676 : if (!VALIDATE(imm.lane >= 0 && imm.lane < num_lanes)) {
1017 0 : error(pc_ + 2, "invalid lane index");
1018 : return false;
1019 : } else {
1020 : return true;
1021 : }
1022 : }
1023 :
1024 1272 : inline bool Validate(const byte* pc, WasmOpcode opcode,
1025 : SimdShiftImmediate<validate>& imm) {
1026 : uint8_t max_shift = 0;
1027 1272 : switch (opcode) {
1028 : case kExprI32x4Shl:
1029 : case kExprI32x4ShrS:
1030 : case kExprI32x4ShrU:
1031 : max_shift = 32;
1032 : break;
1033 : case kExprI16x8Shl:
1034 : case kExprI16x8ShrS:
1035 : case kExprI16x8ShrU:
1036 : max_shift = 16;
1037 : break;
1038 : case kExprI8x16Shl:
1039 : case kExprI8x16ShrS:
1040 : case kExprI8x16ShrU:
1041 : max_shift = 8;
1042 : break;
1043 : default:
1044 0 : UNREACHABLE();
1045 : break;
1046 : }
1047 1272 : if (!VALIDATE(imm.shift >= 0 && imm.shift < max_shift)) {
1048 0 : error(pc_ + 2, "invalid shift amount");
1049 : return false;
1050 : } else {
1051 : return true;
1052 : }
1053 : }
1054 :
1055 14545 : inline bool Validate(const byte* pc,
1056 : Simd8x16ShuffleImmediate<validate>& imm) {
1057 14545 : uint8_t max_lane = 0;
1058 232720 : for (uint32_t i = 0; i < kSimd128Size; ++i) {
1059 465440 : max_lane = std::max(max_lane, imm.shuffle[i]);
1060 : }
1061 : // Shuffle indices must be in [0..31] for a 16 lane shuffle.
1062 14545 : if (!VALIDATE(max_lane <= 2 * kSimd128Size)) {
1063 0 : error(pc_ + 2, "invalid shuffle mask");
1064 : return false;
1065 : }
1066 : return true;
1067 : }
1068 :
1069 392693 : inline bool Complete(BlockTypeImmediate<validate>& imm) {
1070 392693 : if (imm.type != kWasmVar) return true;
1071 746 : if (!VALIDATE((module_ && imm.sig_index < module_->signatures.size()))) {
1072 : return false;
1073 : }
1074 486 : imm.sig = module_->signatures[imm.sig_index];
1075 : return true;
1076 : }
1077 :
1078 392694 : inline bool Validate(BlockTypeImmediate<validate>& imm) {
1079 392694 : if (!Complete(imm)) {
1080 34 : errorf(pc_, "block type index %u out of bounds (%zu signatures)",
1081 0 : imm.sig_index, module_ ? module_->signatures.size() : 0);
1082 17 : return false;
1083 : }
1084 : return true;
1085 : }
1086 :
1087 226 : inline bool Validate(const byte* pc, MemoryIndexImmediate<validate>& imm) {
1088 226 : if (!VALIDATE(module_ != nullptr && module_->has_memory)) {
1089 2 : errorf(pc + 1, "memory instruction with no memory");
1090 : return false;
1091 : }
1092 : return true;
1093 : }
1094 :
1095 78 : inline bool Validate(MemoryInitImmediate<validate>& imm) {
1096 78 : if (!VALIDATE(module_ != nullptr &&
1097 : imm.data_segment_index <
1098 : module_->num_declared_data_segments)) {
1099 1 : errorf(pc_ + 2, "invalid data segment index: %u", imm.data_segment_index);
1100 1 : return false;
1101 : }
1102 77 : if (!Validate(pc_ + imm.length - imm.memory.length - 1, imm.memory))
1103 : return false;
1104 77 : return true;
1105 : }
1106 :
1107 42 : inline bool Validate(DataDropImmediate<validate>& imm) {
1108 42 : if (!VALIDATE(module_ != nullptr &&
1109 : imm.index < module_->num_declared_data_segments)) {
1110 1 : errorf(pc_ + 2, "invalid data segment index: %u", imm.index);
1111 : return false;
1112 : }
1113 : return true;
1114 : }
1115 :
1116 50 : inline bool Validate(MemoryCopyImmediate<validate>& imm) {
1117 50 : if (!Validate(pc_ + 1, imm.memory_src)) return false;
1118 49 : if (!Validate(pc_ + 2, imm.memory_dst)) return false;
1119 : return true;
1120 : }
1121 :
1122 288 : inline bool Validate(const byte* pc, TableIndexImmediate<validate>& imm) {
1123 575 : if (!VALIDATE(module_ != nullptr && imm.index < module_->tables.size())) {
1124 5 : errorf(pc, "invalid table index: %u", imm.index);
1125 5 : return false;
1126 : }
1127 : return true;
1128 : }
1129 :
1130 56 : inline bool Validate(TableInitImmediate<validate>& imm) {
1131 111 : if (!VALIDATE(module_ != nullptr &&
1132 : imm.elem_segment_index < module_->elem_segments.size())) {
1133 3 : errorf(pc_ + 2, "invalid element segment index: %u",
1134 : imm.elem_segment_index);
1135 3 : return false;
1136 : }
1137 53 : if (!Validate(pc_ + imm.length - imm.table.length - 1, imm.table))
1138 : return false;
1139 53 : return true;
1140 : }
1141 :
1142 35 : inline bool Validate(ElemDropImmediate<validate>& imm) {
1143 69 : if (!VALIDATE(module_ != nullptr &&
1144 : imm.index < module_->elem_segments.size())) {
1145 2 : errorf(pc_ + 2, "invalid element segment index: %u", imm.index);
1146 2 : return false;
1147 : }
1148 : return true;
1149 : }
1150 :
1151 106 : inline bool Validate(TableCopyImmediate<validate>& imm) {
1152 106 : if (!Validate(pc_ + 1, imm.table_src)) return false;
1153 105 : if (!Validate(pc_ + 2, imm.table_dst)) return false;
1154 105 : return true;
1155 : }
1156 :
1157 3469705 : static uint32_t OpcodeLength(Decoder* decoder, const byte* pc) {
1158 3469705 : WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
1159 3469705 : switch (opcode) {
1160 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1161 : FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
1162 : FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
1163 : #undef DECLARE_OPCODE_CASE
1164 : {
1165 143250 : MemoryAccessImmediate<validate> imm(decoder, pc, UINT32_MAX);
1166 143250 : return 1 + imm.length;
1167 : }
1168 : case kExprBr:
1169 : case kExprBrIf: {
1170 : BranchDepthImmediate<validate> imm(decoder, pc);
1171 55695 : return 1 + imm.length;
1172 : }
1173 : case kExprGetGlobal:
1174 : case kExprSetGlobal: {
1175 3477 : GlobalIndexImmediate<validate> imm(decoder, pc);
1176 22476 : return 1 + imm.length;
1177 : }
1178 : case kExprGetTable:
1179 : case kExprSetTable: {
1180 : TableIndexImmediate<validate> imm(decoder, pc);
1181 : return 1 + imm.length;
1182 : }
1183 : case kExprCallFunction:
1184 : case kExprReturnCall: {
1185 : CallFunctionImmediate<validate> imm(decoder, pc);
1186 19565 : return 1 + imm.length;
1187 : }
1188 : case kExprCallIndirect:
1189 : case kExprReturnCallIndirect: {
1190 1255 : CallIndirectImmediate<validate> imm(decoder, pc);
1191 1255 : return 1 + imm.length;
1192 : }
1193 :
1194 : case kExprTry:
1195 : case kExprIf: // fall through
1196 : case kExprLoop:
1197 : case kExprBlock: {
1198 114987 : BlockTypeImmediate<validate> imm(kAllWasmFeatures, decoder, pc);
1199 114985 : return 1 + imm.length;
1200 : }
1201 :
1202 : case kExprThrow: {
1203 : ExceptionIndexImmediate<validate> imm(decoder, pc);
1204 13 : return 1 + imm.length;
1205 : }
1206 :
1207 : case kExprBrOnExn: {
1208 : BranchDepthImmediate<validate> imm_br(decoder, pc);
1209 8 : if (!VALIDATE(decoder->ok())) return 1 + imm_br.length;
1210 1 : ExceptionIndexImmediate<validate> imm_idx(decoder, pc + imm_br.length);
1211 1 : return 1 + imm_br.length + imm_idx.length;
1212 : }
1213 :
1214 : case kExprSetLocal:
1215 : case kExprTeeLocal:
1216 : case kExprGetLocal: {
1217 : LocalIndexImmediate<validate> imm(decoder, pc);
1218 494154 : return 1 + imm.length;
1219 : }
1220 : case kExprBrTable: {
1221 4294 : BranchTableImmediate<validate> imm(decoder, pc);
1222 : BranchTableIterator<validate> iterator(decoder, imm);
1223 4294 : return 1 + iterator.length();
1224 : }
1225 : case kExprI32Const: {
1226 : ImmI32Immediate<validate> imm(decoder, pc);
1227 1168635 : return 1 + imm.length;
1228 : }
1229 : case kExprI64Const: {
1230 : ImmI64Immediate<validate> imm(decoder, pc);
1231 2716 : return 1 + imm.length;
1232 : }
1233 : case kExprRefNull: {
1234 : return 1;
1235 : }
1236 : case kExprMemoryGrow:
1237 : case kExprMemorySize: {
1238 64 : MemoryIndexImmediate<validate> imm(decoder, pc);
1239 64 : return 1 + imm.length;
1240 : }
1241 : case kExprF32Const:
1242 525 : return 5;
1243 : case kExprF64Const:
1244 3661 : return 9;
1245 : case kNumericPrefix: {
1246 : byte numeric_index =
1247 24394 : decoder->read_u8<validate>(pc + 1, "numeric_index");
1248 0 : if (!VALIDATE(decoder->ok())) return 2;
1249 : WasmOpcode opcode =
1250 32 : static_cast<WasmOpcode>(kNumericPrefix << 8 | numeric_index);
1251 32 : switch (opcode) {
1252 : case kExprI32SConvertSatF32:
1253 : case kExprI32UConvertSatF32:
1254 : case kExprI32SConvertSatF64:
1255 : case kExprI32UConvertSatF64:
1256 : case kExprI64SConvertSatF32:
1257 : case kExprI64UConvertSatF32:
1258 : case kExprI64SConvertSatF64:
1259 : case kExprI64UConvertSatF64:
1260 : return 2;
1261 : case kExprMemoryInit: {
1262 0 : MemoryInitImmediate<validate> imm(decoder, pc);
1263 0 : return 2 + imm.length;
1264 : }
1265 : case kExprDataDrop: {
1266 : DataDropImmediate<validate> imm(decoder, pc);
1267 0 : return 2 + imm.length;
1268 : }
1269 : case kExprMemoryCopy: {
1270 0 : MemoryCopyImmediate<validate> imm(decoder, pc);
1271 0 : return 2 + imm.length;
1272 : }
1273 : case kExprMemoryFill: {
1274 0 : MemoryIndexImmediate<validate> imm(decoder, pc + 1);
1275 0 : return 2 + imm.length;
1276 : }
1277 : case kExprTableInit: {
1278 0 : TableInitImmediate<validate> imm(decoder, pc);
1279 0 : return 2 + imm.length;
1280 : }
1281 : case kExprElemDrop: {
1282 : ElemDropImmediate<validate> imm(decoder, pc);
1283 0 : return 2 + imm.length;
1284 : }
1285 : case kExprTableCopy: {
1286 0 : TableCopyImmediate<validate> imm(decoder, pc);
1287 0 : return 2 + imm.length;
1288 : }
1289 : default:
1290 0 : decoder->error(pc, "invalid numeric opcode");
1291 0 : return 2;
1292 : }
1293 : }
1294 : case kSimdPrefix: {
1295 32 : byte simd_index = decoder->read_u8<validate>(pc + 1, "simd_index");
1296 32 : if (!VALIDATE(decoder->ok())) return 2;
1297 : WasmOpcode opcode =
1298 23978 : static_cast<WasmOpcode>(kSimdPrefix << 8 | simd_index);
1299 23978 : switch (opcode) {
1300 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1301 : FOREACH_SIMD_0_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
1302 : #undef DECLARE_OPCODE_CASE
1303 : return 2;
1304 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1305 : FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
1306 : #undef DECLARE_OPCODE_CASE
1307 9881 : return 3;
1308 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1309 : FOREACH_SIMD_MEM_OPCODE(DECLARE_OPCODE_CASE)
1310 : #undef DECLARE_OPCODE_CASE
1311 : {
1312 0 : MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
1313 0 : return 2 + imm.length;
1314 : }
1315 : // Shuffles require a byte per lane, or 16 immediate bytes.
1316 : case kExprS8x16Shuffle:
1317 11969 : return 2 + kSimd128Size;
1318 : default:
1319 1 : decoder->error(pc, "invalid SIMD opcode");
1320 1 : return 2;
1321 : }
1322 : }
1323 : case kAtomicPrefix: {
1324 78 : byte atomic_index = decoder->read_u8<validate>(pc + 1, "atomic_index");
1325 78 : if (!VALIDATE(decoder->ok())) return 2;
1326 : WasmOpcode opcode =
1327 494 : static_cast<WasmOpcode>(kAtomicPrefix << 8 | atomic_index);
1328 494 : switch (opcode) {
1329 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1330 : FOREACH_ATOMIC_OPCODE(DECLARE_OPCODE_CASE)
1331 : #undef DECLARE_OPCODE_CASE
1332 : {
1333 494 : MemoryAccessImmediate<validate> imm(decoder, pc + 1, UINT32_MAX);
1334 494 : return 2 + imm.length;
1335 : }
1336 : default:
1337 0 : decoder->error(pc, "invalid Atomics opcode");
1338 0 : return 2;
1339 : }
1340 : }
1341 : default:
1342 : return 1;
1343 : }
1344 : }
1345 :
1346 2042940 : std::pair<uint32_t, uint32_t> StackEffect(const byte* pc) {
1347 2040308 : WasmOpcode opcode = static_cast<WasmOpcode>(*pc);
1348 : // Handle "simple" opcodes with a fixed signature first.
1349 2402774 : FunctionSig* sig = WasmOpcodes::Signature(opcode);
1350 2040308 : if (!sig) sig = WasmOpcodes::AsmjsSignature(opcode);
1351 2400350 : if (sig) return {sig->parameter_count(), sig->return_count()};
1352 :
1353 : #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name:
1354 : // clang-format off
1355 1680266 : switch (opcode) {
1356 : case kExprSelect:
1357 20 : return {3, 1};
1358 : case kExprSetTable:
1359 : FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE)
1360 74496 : return {2, 0};
1361 : FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE)
1362 : case kExprGetTable:
1363 : case kExprTeeLocal:
1364 : case kExprMemoryGrow:
1365 68533 : return {1, 1};
1366 : case kExprSetLocal:
1367 : case kExprSetGlobal:
1368 : case kExprDrop:
1369 : case kExprBrIf:
1370 : case kExprBrTable:
1371 : case kExprIf:
1372 : case kExprRethrow:
1373 84210 : return {1, 0};
1374 : case kExprGetLocal:
1375 : case kExprGetGlobal:
1376 : case kExprI32Const:
1377 : case kExprI64Const:
1378 : case kExprF32Const:
1379 : case kExprF64Const:
1380 : case kExprRefNull:
1381 : case kExprMemorySize:
1382 1010018 : return {0, 1};
1383 : case kExprCallFunction: {
1384 : CallFunctionImmediate<validate> imm(this, pc);
1385 : CHECK(Complete(pc, imm));
1386 4760 : return {imm.sig->parameter_count(), imm.sig->return_count()};
1387 : }
1388 : case kExprCallIndirect: {
1389 240 : CallIndirectImmediate<validate> imm(this, pc);
1390 240 : CHECK(Complete(pc, imm));
1391 : // Indirect calls pop an additional argument for the table index.
1392 : return {imm.sig->parameter_count() + 1,
1393 480 : imm.sig->return_count()};
1394 : }
1395 : case kExprThrow: {
1396 : ExceptionIndexImmediate<validate> imm(this, pc);
1397 : CHECK(Complete(pc, imm));
1398 : DCHECK_EQ(0, imm.exception->sig->return_count());
1399 24 : return {imm.exception->sig->parameter_count(), 0};
1400 : }
1401 : case kExprBr:
1402 : case kExprBlock:
1403 : case kExprLoop:
1404 : case kExprEnd:
1405 : case kExprElse:
1406 : case kExprTry:
1407 : case kExprCatch:
1408 : case kExprBrOnExn:
1409 : case kExprNop:
1410 : case kExprReturn:
1411 : case kExprReturnCall:
1412 : case kExprReturnCallIndirect:
1413 : case kExprUnreachable:
1414 416101 : return {0, 0};
1415 : case kNumericPrefix:
1416 : case kAtomicPrefix:
1417 : case kSimdPrefix: {
1418 24256 : opcode = static_cast<WasmOpcode>(opcode << 8 | *(pc + 1));
1419 24256 : switch (opcode) {
1420 : FOREACH_SIMD_1_OPERAND_1_PARAM_OPCODE(DECLARE_OPCODE_CASE)
1421 9680 : return {1, 1};
1422 : FOREACH_SIMD_1_OPERAND_2_PARAM_OPCODE(DECLARE_OPCODE_CASE)
1423 : FOREACH_SIMD_MASK_OPERAND_OPCODE(DECLARE_OPCODE_CASE)
1424 12152 : return {2, 1};
1425 : default: {
1426 2424 : sig = WasmOpcodes::Signature(opcode);
1427 2424 : if (sig) {
1428 2424 : return {sig->parameter_count(), sig->return_count()};
1429 : }
1430 : }
1431 : }
1432 : V8_FALLTHROUGH;
1433 : }
1434 : default:
1435 0 : V8_Fatal(__FILE__, __LINE__, "unimplemented opcode: %x (%s)", opcode,
1436 0 : WasmOpcodes::OpcodeName(opcode));
1437 : return {0, 0};
1438 : }
1439 : #undef DECLARE_OPCODE_CASE
1440 : // clang-format on
1441 : }
1442 : };
1443 :
1444 : #define CALL_INTERFACE(name, ...) interface_.name(this, ##__VA_ARGS__)
1445 : #define CALL_INTERFACE_IF_REACHABLE(name, ...) \
1446 : do { \
1447 : DCHECK(!control_.empty()); \
1448 : if (VALIDATE(this->ok()) && control_.back().reachable()) { \
1449 : interface_.name(this, ##__VA_ARGS__); \
1450 : } \
1451 : } while (false)
1452 : #define CALL_INTERFACE_IF_PARENT_REACHABLE(name, ...) \
1453 : do { \
1454 : DCHECK(!control_.empty()); \
1455 : if (VALIDATE(this->ok()) && \
1456 : (control_.size() == 1 || control_at(1)->reachable())) { \
1457 : interface_.name(this, ##__VA_ARGS__); \
1458 : } \
1459 : } while (false)
1460 :
1461 : template <Decoder::ValidateFlag validate, typename Interface>
1462 2444294 : class WasmFullDecoder : public WasmDecoder<validate> {
1463 : using Value = typename Interface::Value;
1464 : using Control = typename Interface::Control;
1465 : using MergeValues = Merge<Value>;
1466 :
1467 : // All Value types should be trivially copyable for performance. We push, pop,
1468 : // and store them in local variables.
1469 : ASSERT_TRIVIALLY_COPYABLE(Value);
1470 :
1471 : public:
1472 : template <typename... InterfaceArgs>
1473 1256537 : WasmFullDecoder(Zone* zone, const WasmModule* module,
1474 : const WasmFeatures& enabled, WasmFeatures* detected,
1475 : const FunctionBody& body, InterfaceArgs&&... interface_args)
1476 : : WasmDecoder<validate>(module, enabled, detected, body.sig, body.start,
1477 : body.end, body.offset),
1478 : zone_(zone),
1479 : interface_(std::forward<InterfaceArgs>(interface_args)...),
1480 : local_type_vec_(zone),
1481 : stack_(zone),
1482 : control_(zone),
1483 3701432 : args_(zone) {
1484 1256525 : this->local_types_ = &local_type_vec_;
1485 1256525 : }
1486 :
1487 : Interface& interface() { return interface_; }
1488 :
1489 1256520 : bool Decode() {
1490 : DCHECK(stack_.empty());
1491 : DCHECK(control_.empty());
1492 :
1493 : base::ElapsedTimer decode_timer;
1494 : if (FLAG_trace_wasm_decode_time) {
1495 : decode_timer.Start();
1496 : }
1497 :
1498 1256520 : if (this->end_ < this->pc_) {
1499 0 : this->error("function body end < start");
1500 0 : return false;
1501 : }
1502 :
1503 : DCHECK_EQ(0, this->local_types_->size());
1504 1256520 : WasmDecoder<validate>::DecodeLocals(this->enabled_, this, this->sig_,
1505 1256520 : this->local_types_);
1506 1594857 : CALL_INTERFACE(StartFunction);
1507 1256608 : DecodeFunctionBody();
1508 1097641 : if (!this->failed()) CALL_INTERFACE(FinishFunction);
1509 :
1510 : // Generate a better error message whether the unterminated control
1511 : // structure is the function body block or an innner structure.
1512 2512394 : if (control_.size() > 1) {
1513 8353 : this->error(control_.back().pc, "unterminated control structure");
1514 1247844 : } else if (control_.size() == 1) {
1515 47012 : this->error("function body must end with \"end\" opcode");
1516 : }
1517 :
1518 1256213 : if (this->failed()) return this->TraceFailed();
1519 :
1520 : if (FLAG_trace_wasm_decode_time) {
1521 : double ms = decode_timer.Elapsed().InMillisecondsF();
1522 : PrintF("wasm-decode %s (%0.3f ms)\n\n",
1523 : VALIDATE(this->ok()) ? "ok" : "failed", ms);
1524 : } else {
1525 : TRACE("wasm-decode %s\n\n", VALIDATE(this->ok()) ? "ok" : "failed");
1526 : }
1527 :
1528 1200315 : return true;
1529 : }
1530 :
1531 : bool TraceFailed() {
1532 : TRACE("wasm-error module+%-6d func+%d: %s\n\n", this->error_.offset(),
1533 : this->GetBufferRelativeOffset(this->error_.offset()),
1534 : this->error_.message().c_str());
1535 : return false;
1536 : }
1537 :
1538 71431 : const char* SafeOpcodeNameAt(const byte* pc) {
1539 71431 : if (pc >= this->end_) return "<end>";
1540 59085 : return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(*pc));
1541 : }
1542 :
1543 : inline Zone* zone() const { return zone_; }
1544 :
1545 : inline uint32_t num_locals() const {
1546 3327650 : return static_cast<uint32_t>(local_type_vec_.size());
1547 : }
1548 :
1549 : inline ValueType GetLocalType(uint32_t index) {
1550 4297880 : return local_type_vec_[index];
1551 : }
1552 :
1553 : inline WasmCodePosition position() {
1554 1671791 : int offset = static_cast<int>(this->pc_ - this->start_);
1555 : DCHECK_EQ(this->pc_ - this->start_, offset); // overflows cannot happen
1556 : return offset;
1557 : }
1558 :
1559 : inline uint32_t control_depth() const {
1560 749790 : return static_cast<uint32_t>(control_.size());
1561 : }
1562 :
1563 : inline Control* control_at(uint32_t depth) {
1564 : DCHECK_GT(control_.size(), depth);
1565 689486 : return &control_.back() - depth;
1566 : }
1567 :
1568 : inline uint32_t stack_size() const {
1569 : DCHECK_GE(kMaxUInt32, stack_.size());
1570 3331464 : return static_cast<uint32_t>(stack_.size());
1571 : }
1572 :
1573 : inline Value* stack_value(uint32_t depth) {
1574 : DCHECK_LT(0, depth);
1575 : DCHECK_GE(stack_.size(), depth);
1576 : return &*(stack_.end() - depth);
1577 : }
1578 :
1579 : private:
1580 : Zone* zone_;
1581 :
1582 : Interface interface_;
1583 :
1584 : ZoneVector<ValueType> local_type_vec_; // types of local variables.
1585 : ZoneVector<Value> stack_; // stack of values.
1586 : ZoneVector<Control> control_; // stack of blocks, loops, and ifs.
1587 : ZoneVector<Value> args_; // parameters of current block or call
1588 :
1589 731804 : static Value UnreachableValue(const uint8_t* pc) {
1590 731804 : return Value{pc, kWasmVar};
1591 : }
1592 :
1593 466531 : bool CheckHasMemory() {
1594 466531 : if (!VALIDATE(this->module_->has_memory)) {
1595 160 : this->error(this->pc_ - 1, "memory instruction with no memory");
1596 160 : return false;
1597 : }
1598 : return true;
1599 : }
1600 :
1601 47332 : bool CheckHasSharedMemory() {
1602 47332 : if (!VALIDATE(this->module_->has_shared_memory)) {
1603 16 : this->error(this->pc_ - 1, "Atomic opcodes used without shared memory");
1604 16 : return false;
1605 : }
1606 : return true;
1607 : }
1608 :
1609 : class TraceLine {
1610 : public:
1611 : static constexpr int kMaxLen = 512;
1612 : ~TraceLine() {
1613 : if (!FLAG_trace_wasm_decoder) return;
1614 : PrintF("%.*s\n", len_, buffer_);
1615 : }
1616 :
1617 : // Appends a formatted string.
1618 : PRINTF_FORMAT(2, 3)
1619 : void Append(const char* format, ...) {
1620 : if (!FLAG_trace_wasm_decoder) return;
1621 : va_list va_args;
1622 : va_start(va_args, format);
1623 : size_t remaining_len = kMaxLen - len_;
1624 : Vector<char> remaining_msg_space(buffer_ + len_, remaining_len);
1625 : int len = VSNPrintF(remaining_msg_space, format, va_args);
1626 : va_end(va_args);
1627 : len_ += len < 0 ? remaining_len : len;
1628 : }
1629 :
1630 : private:
1631 : char buffer_[kMaxLen];
1632 : int len_ = 0;
1633 : };
1634 :
1635 : // Decodes the body of a function.
1636 1256470 : void DecodeFunctionBody() {
1637 : TRACE("wasm-decode %p...%p (module+%u, %d bytes)\n",
1638 : reinterpret_cast<const void*>(this->start()),
1639 : reinterpret_cast<const void*>(this->end()), this->pc_offset(),
1640 : static_cast<int>(this->end() - this->start()));
1641 :
1642 : // Set up initial function block.
1643 : {
1644 1256470 : auto* c = PushControl(kControlBlock);
1645 1256395 : InitMerge(&c->start_merge, 0, [](uint32_t) -> Value { UNREACHABLE(); });
1646 2512812 : InitMerge(&c->end_merge,
1647 : static_cast<uint32_t>(this->sig_->return_count()),
1648 : [&](uint32_t i) {
1649 : return Value{this->pc_, this->sig_->GetReturn(i)};
1650 2755005 : });
1651 3226833 : CALL_INTERFACE(StartFunctionBody, c);
1652 : }
1653 :
1654 13809937 : while (this->pc_ < this->end_) { // decoding loop.
1655 : uint32_t len = 1;
1656 11959448 : WasmOpcode opcode = static_cast<WasmOpcode>(*this->pc_);
1657 :
1658 2546560 : CALL_INTERFACE_IF_REACHABLE(NextInstruction, opcode);
1659 :
1660 : #if DEBUG
1661 : TraceLine trace_msg;
1662 : #define TRACE_PART(...) trace_msg.Append(__VA_ARGS__)
1663 : if (!WasmOpcodes::IsPrefixOpcode(opcode)) {
1664 : TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
1665 : WasmOpcodes::OpcodeName(opcode));
1666 : }
1667 : #else
1668 : #define TRACE_PART(...)
1669 : #endif
1670 :
1671 11959448 : switch (opcode) {
1672 : #define BUILD_SIMPLE_OPCODE(op, _, sig) \
1673 : case kExpr##op: \
1674 : BuildSimpleOperator_##sig(opcode); \
1675 : break;
1676 : FOREACH_SIMPLE_OPCODE(BUILD_SIMPLE_OPCODE)
1677 : #undef BUILD_SIMPLE_OPCODE
1678 : case kExprNop:
1679 : break;
1680 : case kExprBlock: {
1681 313724 : BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
1682 313725 : if (!this->Validate(imm)) break;
1683 313720 : PopArgs(imm.sig);
1684 627436 : auto* block = PushControl(kControlBlock);
1685 313717 : SetBlockType(block, imm);
1686 119020 : CALL_INTERFACE_IF_REACHABLE(Block, block);
1687 627436 : PushMergeValues(block, &block->start_merge);
1688 313717 : len = 1 + imm.length;
1689 313717 : break;
1690 : }
1691 : case kExprRethrow: {
1692 428 : CHECK_PROTOTYPE_OPCODE(eh);
1693 : auto exception = Pop(0, kWasmExceptRef);
1694 848 : CALL_INTERFACE_IF_REACHABLE(Rethrow, exception);
1695 427 : EndControl();
1696 427 : break;
1697 : }
1698 : case kExprThrow: {
1699 643 : CHECK_PROTOTYPE_OPCODE(eh);
1700 643 : ExceptionIndexImmediate<validate> imm(this, this->pc_);
1701 644 : len = 1 + imm.length;
1702 644 : if (!this->Validate(this->pc_, imm)) break;
1703 643 : PopArgs(imm.exception->ToFunctionSig());
1704 1786 : CALL_INTERFACE_IF_REACHABLE(Throw, imm, VectorOf(args_));
1705 645 : EndControl();
1706 643 : break;
1707 : }
1708 : case kExprTry: {
1709 769 : CHECK_PROTOTYPE_OPCODE(eh);
1710 769 : BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
1711 769 : if (!this->Validate(imm)) break;
1712 770 : PopArgs(imm.sig);
1713 1539 : auto* try_block = PushControl(kControlTry);
1714 770 : SetBlockType(try_block, imm);
1715 769 : len = 1 + imm.length;
1716 1510 : CALL_INTERFACE_IF_REACHABLE(Try, try_block);
1717 1540 : PushMergeValues(try_block, &try_block->start_merge);
1718 769 : break;
1719 : }
1720 : case kExprCatch: {
1721 532 : CHECK_PROTOTYPE_OPCODE(eh);
1722 532 : if (!VALIDATE(!control_.empty())) {
1723 0 : this->error("catch does not match any try");
1724 0 : break;
1725 : }
1726 532 : Control* c = &control_.back();
1727 532 : if (!VALIDATE(c->is_try())) {
1728 1 : this->error("catch does not match any try");
1729 1 : break;
1730 : }
1731 531 : if (!VALIDATE(c->is_incomplete_try())) {
1732 1 : this->error("catch already present for try");
1733 1 : break;
1734 : }
1735 530 : c->kind = kControlTryCatch;
1736 530 : FallThruTo(c);
1737 1064 : stack_.erase(stack_.begin() + c->stack_depth, stack_.end());
1738 1064 : c->reachability = control_at(1)->innerReachability();
1739 : auto* exception = Push(kWasmExceptRef);
1740 1064 : CALL_INTERFACE_IF_PARENT_REACHABLE(Catch, c, exception);
1741 : break;
1742 : }
1743 : case kExprBrOnExn: {
1744 385 : CHECK_PROTOTYPE_OPCODE(eh);
1745 385 : BranchDepthImmediate<validate> imm_br(this, this->pc_);
1746 770 : if (!this->Validate(this->pc_, imm_br, control_.size())) break;
1747 : ExceptionIndexImmediate<validate> imm_idx(this,
1748 384 : this->pc_ + imm_br.length);
1749 384 : if (!this->Validate(this->pc_ + imm_br.length, imm_idx)) break;
1750 384 : Control* c = control_at(imm_br.depth);
1751 : auto exception = Pop(0, kWasmExceptRef);
1752 633 : const WasmExceptionSig* sig = imm_idx.exception->sig;
1753 : size_t value_count = sig->parameter_count();
1754 : // TODO(mstarzinger): This operand stack mutation is an ugly hack to
1755 : // make both type checking here as well as environment merging in the
1756 : // graph builder interface work out of the box. We should introduce
1757 : // special handling for both and do minimal/no stack mutation here.
1758 633 : for (size_t i = 0; i < value_count; ++i) Push(sig->GetParam(i));
1759 376 : Vector<Value> values(stack_.data() + c->stack_depth, value_count);
1760 384 : if (!TypeCheckBranch(c)) break;
1761 384 : if (control_.back().reachable()) {
1762 376 : CALL_INTERFACE(BrOnException, exception, imm_idx, imm_br.depth,
1763 : values);
1764 383 : c->br_merge()->reached = true;
1765 : }
1766 383 : len = 1 + imm_br.length + imm_idx.length;
1767 632 : for (size_t i = 0; i < value_count; ++i) Pop();
1768 : auto* pexception = Push(kWasmExceptRef);
1769 383 : *pexception = exception;
1770 383 : break;
1771 : }
1772 : case kExprLoop: {
1773 15971 : BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
1774 15970 : if (!this->Validate(imm)) break;
1775 15972 : PopArgs(imm.sig);
1776 31940 : auto* block = PushControl(kControlLoop);
1777 15972 : SetBlockType(&control_.back(), imm);
1778 15972 : len = 1 + imm.length;
1779 22816 : CALL_INTERFACE_IF_REACHABLE(Loop, block);
1780 31940 : PushMergeValues(block, &block->start_merge);
1781 15970 : break;
1782 : }
1783 : case kExprIf: {
1784 62235 : BlockTypeImmediate<validate> imm(this->enabled_, this, this->pc_);
1785 62233 : if (!this->Validate(imm)) break;
1786 : auto cond = Pop(0, kWasmI32);
1787 62221 : PopArgs(imm.sig);
1788 62219 : if (!VALIDATE(this->ok())) break;
1789 124135 : auto* if_block = PushControl(kControlIf);
1790 62072 : SetBlockType(if_block, imm);
1791 118935 : CALL_INTERFACE_IF_REACHABLE(If, cond, if_block);
1792 62070 : len = 1 + imm.length;
1793 124140 : PushMergeValues(if_block, &if_block->start_merge);
1794 62070 : break;
1795 : }
1796 : case kExprElse: {
1797 21275 : if (!VALIDATE(!control_.empty())) {
1798 0 : this->error("else does not match any if");
1799 0 : break;
1800 : }
1801 43854 : Control* c = &control_.back();
1802 40838 : if (!VALIDATE(c->is_if())) {
1803 0 : this->error(this->pc_, "else does not match an if");
1804 0 : break;
1805 : }
1806 21275 : if (c->is_if_else()) {
1807 2 : this->error(this->pc_, "else already present for if");
1808 2 : break;
1809 : }
1810 21273 : if (!TypeCheckFallThru(c)) break;
1811 21073 : c->kind = kControlIfElse;
1812 39132 : CALL_INTERFACE_IF_PARENT_REACHABLE(Else, c);
1813 21071 : if (c->reachable()) c->end_merge.reached = true;
1814 42142 : PushMergeValues(c, &c->start_merge);
1815 42146 : c->reachability = control_at(1)->innerReachability();
1816 21073 : break;
1817 : }
1818 : case kExprEnd: {
1819 1588141 : if (!VALIDATE(!control_.empty())) {
1820 0 : this->error("end does not match any if, try, or block");
1821 0 : break;
1822 : }
1823 1588141 : Control* c = &control_.back();
1824 1588141 : if (!VALIDATE(!c->is_incomplete_try())) {
1825 1 : this->error(this->pc_, "missing catch or catch-all in try");
1826 1 : break;
1827 : }
1828 1588140 : if (c->is_onearmed_if()) {
1829 40149 : if (!VALIDATE(c->end_merge.arity == c->start_merge.arity)) {
1830 97 : this->error(
1831 : c->pc,
1832 : "start-arity and end-arity of one-armed if must match");
1833 97 : break;
1834 : }
1835 : }
1836 :
1837 1588043 : if (!TypeCheckFallThru(c)) break;
1838 :
1839 1581646 : if (control_.size() == 1) {
1840 : // If at the last (implicit) control, check we are at end.
1841 1200930 : if (!VALIDATE(this->pc_ + 1 == this->end_)) {
1842 2 : this->error(this->pc_ + 1, "trailing code after function end");
1843 2 : break;
1844 : }
1845 : // The result of the block is the return value.
1846 : TRACE_PART("\n" TRACE_INST_FORMAT, startrel(this->pc_),
1847 : "(implicit) return");
1848 1067477 : DoReturn();
1849 : control_.clear();
1850 : break;
1851 : }
1852 :
1853 380716 : PopControl(c);
1854 380713 : break;
1855 : }
1856 : case kExprSelect: {
1857 : auto cond = Pop(2, kWasmI32);
1858 : auto fval = Pop();
1859 1211 : auto tval = Pop(0, fval.type);
1860 3676 : auto* result = Push(tval.type == kWasmVar ? fval.type : tval.type);
1861 4838 : CALL_INTERFACE_IF_REACHABLE(Select, cond, fval, tval, result);
1862 : break;
1863 : }
1864 : case kExprBr: {
1865 31020 : BranchDepthImmediate<validate> imm(this, this->pc_);
1866 62041 : if (!this->Validate(this->pc_, imm, control_.size())) break;
1867 30464 : Control* c = control_at(imm.depth);
1868 30464 : if (!TypeCheckBranch(c)) break;
1869 56988 : if (imm.depth == control_.size() - 1) {
1870 264 : DoReturn();
1871 28034 : } else if (control_.back().reachable()) {
1872 22738 : CALL_INTERFACE(Br, c);
1873 27447 : c->br_merge()->reached = true;
1874 : }
1875 28496 : len = 1 + imm.length;
1876 28496 : EndControl();
1877 28495 : break;
1878 : }
1879 : case kExprBrIf: {
1880 239301 : BranchDepthImmediate<validate> imm(this, this->pc_);
1881 : auto cond = Pop(0, kWasmI32);
1882 239302 : if (this->failed()) break;
1883 478178 : if (!this->Validate(this->pc_, imm, control_.size())) break;
1884 239017 : Control* c = control_at(imm.depth);
1885 239017 : if (!TypeCheckBranch(c)) break;
1886 238797 : if (control_.back().reachable()) {
1887 132374 : CALL_INTERFACE(BrIf, cond, imm.depth);
1888 238148 : c->br_merge()->reached = true;
1889 : }
1890 238796 : len = 1 + imm.length;
1891 238796 : break;
1892 : }
1893 : case kExprBrTable: {
1894 12880 : BranchTableImmediate<validate> imm(this, this->pc_);
1895 : BranchTableIterator<validate> iterator(this, imm);
1896 : auto key = Pop(0, kWasmI32);
1897 12877 : if (this->failed()) break;
1898 12758 : if (!this->Validate(this->pc_, imm, control_.size())) break;
1899 : uint32_t br_arity = 0;
1900 12725 : std::vector<bool> br_targets(control_.size());
1901 658194 : while (iterator.has_next()) {
1902 633100 : const uint32_t i = iterator.cur_index();
1903 633100 : const byte* pos = iterator.pc();
1904 633100 : uint32_t target = iterator.next();
1905 1266204 : if (!VALIDATE(target < control_.size())) {
1906 178 : this->errorf(pos,
1907 : "improper branch in br_table target %u (depth %u)",
1908 : i, target);
1909 178 : break;
1910 : }
1911 : // Avoid redundant branch target checks.
1912 1265848 : if (br_targets[target]) continue;
1913 : br_targets[target] = true;
1914 : // Check that label types match up.
1915 : Control* c = control_at(target);
1916 29219 : uint32_t arity = c->br_merge()->arity;
1917 29219 : if (i == 0) {
1918 : br_arity = arity;
1919 16553 : } else if (!VALIDATE(br_arity == arity)) {
1920 68 : this->errorf(pos,
1921 : "inconsistent arity in br_table target %u"
1922 : " (previous was %u, this one %u)",
1923 : i, br_arity, arity);
1924 : }
1925 29219 : if (!TypeCheckBranch(c)) break;
1926 : }
1927 12728 : if (this->failed()) break;
1928 :
1929 12298 : if (control_.back().reachable()) {
1930 10615 : CALL_INTERFACE(BrTable, imm, key);
1931 :
1932 82359 : for (uint32_t depth = control_depth(); depth-- > 0;) {
1933 117670 : if (!br_targets[depth]) continue;
1934 28173 : control_at(depth)->br_merge()->reached = true;
1935 : }
1936 : }
1937 :
1938 12298 : len = 1 + iterator.length();
1939 12297 : EndControl();
1940 12297 : break;
1941 : }
1942 : case kExprReturn: {
1943 321026 : if (!TypeCheckReturn()) break;
1944 212652 : DoReturn();
1945 320569 : EndControl();
1946 320576 : break;
1947 : }
1948 : case kExprUnreachable: {
1949 221748 : CALL_INTERFACE_IF_REACHABLE(Unreachable);
1950 219529 : EndControl();
1951 219529 : break;
1952 : }
1953 : case kExprI32Const: {
1954 3078961 : ImmI32Immediate<validate> imm(this, this->pc_);
1955 : auto* value = Push(kWasmI32);
1956 5945613 : CALL_INTERFACE_IF_REACHABLE(I32Const, value, imm.value);
1957 3079082 : len = 1 + imm.length;
1958 : break;
1959 : }
1960 : case kExprI64Const: {
1961 95448 : ImmI64Immediate<validate> imm(this, this->pc_);
1962 : auto* value = Push(kWasmI64);
1963 124701 : CALL_INTERFACE_IF_REACHABLE(I64Const, value, imm.value);
1964 95478 : len = 1 + imm.length;
1965 : break;
1966 : }
1967 : case kExprF32Const: {
1968 239185 : ImmF32Immediate<validate> imm(this, this->pc_);
1969 : auto* value = Push(kWasmF32);
1970 243647 : CALL_INTERFACE_IF_REACHABLE(F32Const, value, imm.value);
1971 239187 : len = 1 + imm.length;
1972 : break;
1973 : }
1974 : case kExprF64Const: {
1975 245608 : ImmF64Immediate<validate> imm(this, this->pc_);
1976 : auto* value = Push(kWasmF64);
1977 256716 : CALL_INTERFACE_IF_REACHABLE(F64Const, value, imm.value);
1978 245610 : len = 1 + imm.length;
1979 : break;
1980 : }
1981 : case kExprRefNull: {
1982 146 : CHECK_PROTOTYPE_OPCODE(anyref);
1983 : auto* value = Push(kWasmNullRef);
1984 290 : CALL_INTERFACE_IF_REACHABLE(RefNull, value);
1985 : len = 1;
1986 : break;
1987 : }
1988 : case kExprGetLocal: {
1989 908959 : LocalIndexImmediate<validate> imm(this, this->pc_);
1990 909033 : if (!this->Validate(this->pc_, imm)) break;
1991 908655 : auto* value = Push(imm.type);
1992 1701089 : CALL_INTERFACE_IF_REACHABLE(GetLocal, value, imm);
1993 908713 : len = 1 + imm.length;
1994 908713 : break;
1995 : }
1996 : case kExprSetLocal: {
1997 444827 : LocalIndexImmediate<validate> imm(this, this->pc_);
1998 444828 : if (!this->Validate(this->pc_, imm)) break;
1999 990556 : auto value = Pop(0, local_type_vec_[imm.index]);
2000 866717 : CALL_INTERFACE_IF_REACHABLE(SetLocal, value, imm);
2001 444676 : len = 1 + imm.length;
2002 444676 : break;
2003 : }
2004 : case kExprTeeLocal: {
2005 101199 : LocalIndexImmediate<validate> imm(this, this->pc_);
2006 101199 : if (!this->Validate(this->pc_, imm)) break;
2007 202396 : auto value = Pop(0, local_type_vec_[imm.index]);
2008 : auto* result = Push(value.type);
2009 199536 : CALL_INTERFACE_IF_REACHABLE(TeeLocal, value, result, imm);
2010 101198 : len = 1 + imm.length;
2011 101198 : break;
2012 : }
2013 : case kExprDrop: {
2014 : auto value = Pop();
2015 6631 : CALL_INTERFACE_IF_REACHABLE(Drop, value);
2016 : break;
2017 : }
2018 : case kExprGetGlobal: {
2019 38043 : GlobalIndexImmediate<validate> imm(this, this->pc_);
2020 38043 : len = 1 + imm.length;
2021 38043 : if (!this->Validate(this->pc_, imm)) break;
2022 38022 : auto* result = Push(imm.type);
2023 75014 : CALL_INTERFACE_IF_REACHABLE(GetGlobal, result, imm);
2024 : break;
2025 : }
2026 : case kExprSetGlobal: {
2027 16466 : GlobalIndexImmediate<validate> imm(this, this->pc_);
2028 16466 : len = 1 + imm.length;
2029 16466 : if (!this->Validate(this->pc_, imm)) break;
2030 16466 : if (!VALIDATE(imm.global->mutability)) {
2031 25 : this->errorf(this->pc_, "immutable global #%u cannot be assigned",
2032 : imm.index);
2033 25 : break;
2034 : }
2035 16441 : auto value = Pop(0, imm.type);
2036 32055 : CALL_INTERFACE_IF_REACHABLE(SetGlobal, value, imm);
2037 : break;
2038 : }
2039 : case kExprGetTable: {
2040 12 : CHECK_PROTOTYPE_OPCODE(anyref);
2041 12 : TableIndexImmediate<validate> imm(this, this->pc_);
2042 12 : len = 1 + imm.length;
2043 12 : if (!this->Validate(this->pc_, imm)) break;
2044 : DCHECK_NOT_NULL(this->module_);
2045 : auto index = Pop(0, kWasmI32);
2046 30 : auto* result = Push(this->module_->tables[imm.index].type);
2047 20 : CALL_INTERFACE_IF_REACHABLE(GetTable, index, result, imm);
2048 : break;
2049 : }
2050 : case kExprSetTable: {
2051 12 : CHECK_PROTOTYPE_OPCODE(anyref);
2052 12 : TableIndexImmediate<validate> imm(this, this->pc_);
2053 12 : len = 1 + imm.length;
2054 12 : if (!this->Validate(this->pc_, imm)) break;
2055 20 : auto value = Pop(0, this->module_->tables[imm.index].type);
2056 : auto index = Pop(0, kWasmI32);
2057 16 : CALL_INTERFACE_IF_REACHABLE(SetTable, index, value, imm);
2058 : break;
2059 : }
2060 :
2061 : case kExprI32LoadMem8S:
2062 3210 : len = 1 + DecodeLoadMem(LoadType::kI32Load8S);
2063 3210 : break;
2064 : case kExprI32LoadMem8U:
2065 2024 : len = 1 + DecodeLoadMem(LoadType::kI32Load8U);
2066 2024 : break;
2067 : case kExprI32LoadMem16S:
2068 466 : len = 1 + DecodeLoadMem(LoadType::kI32Load16S);
2069 466 : break;
2070 : case kExprI32LoadMem16U:
2071 784 : len = 1 + DecodeLoadMem(LoadType::kI32Load16U);
2072 784 : break;
2073 : case kExprI32LoadMem:
2074 86927 : len = 1 + DecodeLoadMem(LoadType::kI32Load);
2075 86918 : break;
2076 : case kExprI64LoadMem8S:
2077 493 : len = 1 + DecodeLoadMem(LoadType::kI64Load8S);
2078 493 : break;
2079 : case kExprI64LoadMem8U:
2080 387 : len = 1 + DecodeLoadMem(LoadType::kI64Load8U);
2081 387 : break;
2082 : case kExprI64LoadMem16S:
2083 445 : len = 1 + DecodeLoadMem(LoadType::kI64Load16S);
2084 445 : break;
2085 : case kExprI64LoadMem16U:
2086 435 : len = 1 + DecodeLoadMem(LoadType::kI64Load16U);
2087 435 : break;
2088 : case kExprI64LoadMem32S:
2089 469 : len = 1 + DecodeLoadMem(LoadType::kI64Load32S);
2090 469 : break;
2091 : case kExprI64LoadMem32U:
2092 459 : len = 1 + DecodeLoadMem(LoadType::kI64Load32U);
2093 459 : break;
2094 : case kExprI64LoadMem:
2095 89829 : len = 1 + DecodeLoadMem(LoadType::kI64Load);
2096 89829 : break;
2097 : case kExprF32LoadMem:
2098 2842 : len = 1 + DecodeLoadMem(LoadType::kF32Load);
2099 2842 : break;
2100 : case kExprF64LoadMem:
2101 3832 : len = 1 + DecodeLoadMem(LoadType::kF64Load);
2102 3832 : break;
2103 : case kExprI32StoreMem8:
2104 2394 : len = 1 + DecodeStoreMem(StoreType::kI32Store8);
2105 2394 : break;
2106 : case kExprI32StoreMem16:
2107 850 : len = 1 + DecodeStoreMem(StoreType::kI32Store16);
2108 850 : break;
2109 : case kExprI32StoreMem:
2110 160654 : len = 1 + DecodeStoreMem(StoreType::kI32Store);
2111 160661 : break;
2112 : case kExprI64StoreMem8:
2113 320 : len = 1 + DecodeStoreMem(StoreType::kI64Store8);
2114 320 : break;
2115 : case kExprI64StoreMem16:
2116 480 : len = 1 + DecodeStoreMem(StoreType::kI64Store16);
2117 480 : break;
2118 : case kExprI64StoreMem32:
2119 432 : len = 1 + DecodeStoreMem(StoreType::kI64Store32);
2120 431 : break;
2121 : case kExprI64StoreMem:
2122 102130 : len = 1 + DecodeStoreMem(StoreType::kI64Store);
2123 102130 : break;
2124 : case kExprF32StoreMem:
2125 765 : len = 1 + DecodeStoreMem(StoreType::kF32Store);
2126 765 : break;
2127 : case kExprF64StoreMem:
2128 1693 : len = 1 + DecodeStoreMem(StoreType::kF64Store);
2129 1693 : break;
2130 : case kExprMemoryGrow: {
2131 3167 : if (!CheckHasMemory()) break;
2132 3127 : MemoryIndexImmediate<validate> imm(this, this->pc_);
2133 3127 : len = 1 + imm.length;
2134 : DCHECK_NOT_NULL(this->module_);
2135 3127 : if (!VALIDATE(this->module_->origin == kWasmOrigin)) {
2136 1 : this->error("grow_memory is not supported for asmjs modules");
2137 1 : break;
2138 : }
2139 : auto value = Pop(0, kWasmI32);
2140 : auto* result = Push(kWasmI32);
2141 6105 : CALL_INTERFACE_IF_REACHABLE(MemoryGrow, value, result);
2142 : break;
2143 : }
2144 : case kExprMemorySize: {
2145 1062 : if (!CheckHasMemory()) break;
2146 1038 : MemoryIndexImmediate<validate> imm(this, this->pc_);
2147 : auto* result = Push(kWasmI32);
2148 1038 : len = 1 + imm.length;
2149 1940 : CALL_INTERFACE_IF_REACHABLE(CurrentMemoryPages, result);
2150 : break;
2151 : }
2152 : case kExprCallFunction: {
2153 265689 : CallFunctionImmediate<validate> imm(this, this->pc_);
2154 265690 : len = 1 + imm.length;
2155 265690 : if (!this->Validate(this->pc_, imm)) break;
2156 : // TODO(clemensh): Better memory management.
2157 265620 : PopArgs(imm.sig);
2158 265617 : auto* returns = PushReturns(imm.sig);
2159 332451 : CALL_INTERFACE_IF_REACHABLE(CallDirect, imm, args_.data(), returns);
2160 : break;
2161 : }
2162 : case kExprCallIndirect: {
2163 8347 : CallIndirectImmediate<validate> imm(this, this->pc_);
2164 8349 : len = 1 + imm.length;
2165 8349 : if (!this->Validate(this->pc_, imm)) break;
2166 : auto index = Pop(0, kWasmI32);
2167 8259 : PopArgs(imm.sig);
2168 8261 : auto* returns = PushReturns(imm.sig);
2169 16049 : CALL_INTERFACE_IF_REACHABLE(CallIndirect, index, imm, args_.data(),
2170 : returns);
2171 : break;
2172 : }
2173 : case kExprReturnCall: {
2174 12 : CHECK_PROTOTYPE_OPCODE(return_call);
2175 :
2176 12 : CallFunctionImmediate<validate> imm(this, this->pc_);
2177 12 : len = 1 + imm.length;
2178 12 : if (!this->Validate(this->pc_, imm)) break;
2179 12 : if (!this->CanTailCall(imm.sig)) {
2180 4 : OPCODE_ERROR(opcode, "tail call return types mismatch");
2181 4 : break;
2182 : }
2183 :
2184 : PopArgs(imm.sig);
2185 :
2186 0 : CALL_INTERFACE_IF_REACHABLE(ReturnCall, imm, args_.data());
2187 8 : EndControl();
2188 8 : break;
2189 : }
2190 : case kExprReturnCallIndirect: {
2191 21 : CHECK_PROTOTYPE_OPCODE(return_call);
2192 20 : CallIndirectImmediate<validate> imm(this, this->pc_);
2193 20 : len = 1 + imm.length;
2194 20 : if (!this->Validate(this->pc_, imm)) break;
2195 5 : if (!this->CanTailCall(imm.sig)) {
2196 0 : OPCODE_ERROR(opcode, "tail call return types mismatch");
2197 0 : break;
2198 : }
2199 : auto index = Pop(0, kWasmI32);
2200 5 : PopArgs(imm.sig);
2201 0 : CALL_INTERFACE_IF_REACHABLE(ReturnCallIndirect, index, imm,
2202 : args_.data());
2203 5 : EndControl();
2204 5 : break;
2205 : }
2206 : case kNumericPrefix: {
2207 : ++len;
2208 : byte numeric_index =
2209 522 : this->template read_u8<validate>(this->pc_ + 1, "numeric index");
2210 522 : opcode = static_cast<WasmOpcode>(opcode << 8 | numeric_index);
2211 522 : if (opcode < kExprMemoryInit) {
2212 98 : CHECK_PROTOTYPE_OPCODE(sat_f2i_conversions);
2213 : } else {
2214 424 : CHECK_PROTOTYPE_OPCODE(bulk_memory);
2215 : }
2216 : TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
2217 : WasmOpcodes::OpcodeName(opcode));
2218 513 : len += DecodeNumericOpcode(opcode);
2219 513 : break;
2220 : }
2221 : case kSimdPrefix: {
2222 38681 : CHECK_PROTOTYPE_OPCODE(simd);
2223 : len++;
2224 : byte simd_index =
2225 38681 : this->template read_u8<validate>(this->pc_ + 1, "simd index");
2226 38681 : opcode = static_cast<WasmOpcode>(opcode << 8 | simd_index);
2227 : TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
2228 : WasmOpcodes::OpcodeName(opcode));
2229 38681 : len += DecodeSimdOpcode(opcode);
2230 38681 : break;
2231 : }
2232 : case kAtomicPrefix: {
2233 47341 : CHECK_PROTOTYPE_OPCODE(threads);
2234 47341 : if (!CheckHasSharedMemory()) break;
2235 : len++;
2236 : byte atomic_index =
2237 47336 : this->template read_u8<validate>(this->pc_ + 1, "atomic index");
2238 47350 : opcode = static_cast<WasmOpcode>(opcode << 8 | atomic_index);
2239 : TRACE_PART(TRACE_INST_FORMAT, startrel(this->pc_),
2240 : WasmOpcodes::OpcodeName(opcode));
2241 47350 : len += DecodeAtomicOpcode(opcode);
2242 47389 : break;
2243 : }
2244 : // Note that prototype opcodes are not handled in the fastpath
2245 : // above this switch, to avoid checking a feature flag.
2246 : #define SIMPLE_PROTOTYPE_CASE(name, opc, sig) \
2247 : case kExpr##name: /* fallthrough */
2248 : FOREACH_SIMPLE_PROTOTYPE_OPCODE(SIMPLE_PROTOTYPE_CASE)
2249 : #undef SIMPLE_PROTOTYPE_CASE
2250 88 : BuildSimplePrototypeOperator(opcode);
2251 88 : break;
2252 : default: {
2253 : // Deal with special asmjs opcodes.
2254 100191 : if (this->module_ != nullptr &&
2255 : this->module_->origin == kAsmJsOrigin) {
2256 100160 : FunctionSig* sig = WasmOpcodes::AsmjsSignature(opcode);
2257 100160 : if (sig) {
2258 100160 : BuildSimpleOperator(opcode, sig);
2259 : }
2260 : } else {
2261 31 : this->error("Invalid opcode");
2262 1256474 : return;
2263 : }
2264 : }
2265 : }
2266 :
2267 : #if DEBUG
2268 : if (FLAG_trace_wasm_decoder) {
2269 : TRACE_PART(" ");
2270 : for (Control& c : control_) {
2271 : switch (c.kind) {
2272 : case kControlIf:
2273 : TRACE_PART("I");
2274 : break;
2275 : case kControlBlock:
2276 : TRACE_PART("B");
2277 : break;
2278 : case kControlLoop:
2279 : TRACE_PART("L");
2280 : break;
2281 : case kControlTry:
2282 : TRACE_PART("T");
2283 : break;
2284 : default:
2285 : break;
2286 : }
2287 : if (c.start_merge.arity) TRACE_PART("%u-", c.start_merge.arity);
2288 : TRACE_PART("%u", c.end_merge.arity);
2289 : if (!c.reachable()) TRACE_PART("%c", c.unreachable() ? '*' : '#');
2290 : }
2291 : TRACE_PART(" | ");
2292 : for (size_t i = 0; i < stack_.size(); ++i) {
2293 : auto& val = stack_[i];
2294 : WasmOpcode opcode = static_cast<WasmOpcode>(*val.pc);
2295 : if (WasmOpcodes::IsPrefixOpcode(opcode)) {
2296 : opcode = static_cast<WasmOpcode>(opcode << 8 | *(val.pc + 1));
2297 : }
2298 : TRACE_PART(" %c@%d:%s", ValueTypes::ShortNameOf(val.type),
2299 : static_cast<int>(val.pc - this->start_),
2300 : WasmOpcodes::OpcodeName(opcode));
2301 : // If the decoder failed, don't try to decode the immediates, as this
2302 : // can trigger a DCHECK failure.
2303 : if (this->failed()) continue;
2304 : switch (opcode) {
2305 : case kExprI32Const: {
2306 : ImmI32Immediate<Decoder::kNoValidate> imm(this, val.pc);
2307 : TRACE_PART("[%d]", imm.value);
2308 : break;
2309 : }
2310 : case kExprGetLocal:
2311 : case kExprSetLocal:
2312 : case kExprTeeLocal: {
2313 : LocalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
2314 : TRACE_PART("[%u]", imm.index);
2315 : break;
2316 : }
2317 : case kExprGetGlobal:
2318 : case kExprSetGlobal: {
2319 : GlobalIndexImmediate<Decoder::kNoValidate> imm(this, val.pc);
2320 : TRACE_PART("[%u]", imm.index);
2321 : break;
2322 : }
2323 : default:
2324 : break;
2325 : }
2326 : }
2327 : }
2328 : #endif
2329 11959414 : this->pc_ += len;
2330 : } // end decode loop
2331 1311739 : if (!VALIDATE(this->pc_ == this->end_) && this->ok()) {
2332 0 : this->error("Beyond end of code");
2333 : }
2334 : }
2335 :
2336 581942 : void EndControl() {
2337 : DCHECK(!control_.empty());
2338 : auto* current = &control_.back();
2339 1163884 : stack_.erase(stack_.begin() + current->stack_depth, stack_.end());
2340 238779 : CALL_INTERFACE_IF_REACHABLE(EndControl, current);
2341 581964 : current->reachability = kUnreachable;
2342 581964 : }
2343 :
2344 : template<typename func>
2345 3297903 : void InitMerge(Merge<Value>* merge, uint32_t arity, func get_val) {
2346 3297903 : merge->arity = arity;
2347 3297903 : if (arity == 1) {
2348 1009892 : merge->vals.first = get_val(0);
2349 2288011 : } else if (arity > 1) {
2350 6308 : merge->vals.array = zone_->NewArray<Value>(arity);
2351 7630 : for (uint32_t i = 0; i < arity; i++) {
2352 12672 : merge->vals.array[i] = get_val(i);
2353 : }
2354 : }
2355 3297903 : }
2356 :
2357 1177575 : void SetBlockType(Control* c, BlockTypeImmediate<validate>& imm) {
2358 : DCHECK_EQ(imm.in_arity(), this->args_.size());
2359 392524 : const byte* pc = this->pc_;
2360 : Value* args = this->args_.data();
2361 785048 : InitMerge(&c->end_merge, imm.out_arity(), [pc, &imm](uint32_t i) {
2362 : return Value{pc, imm.out_type(i)};
2363 421175 : });
2364 785054 : InitMerge(&c->start_merge, imm.in_arity(),
2365 392721 : [args](uint32_t i) { return args[i]; });
2366 392528 : }
2367 :
2368 : // Pops arguments as required by signature into {args_}.
2369 318102 : V8_INLINE void PopArgs(FunctionSig* sig) {
2370 834671 : int count = sig ? static_cast<int>(sig->parameter_count()) : 0;
2371 1061116 : args_.resize(count, UnreachableValue(nullptr));
2372 1353586 : for (int i = count - 1; i >= 0; --i) {
2373 1813938 : args_[i] = Pop(i, sig->GetParam(i));
2374 : }
2375 : }
2376 :
2377 171625 : ValueType GetReturnType(FunctionSig* sig) {
2378 : DCHECK_GE(1, sig->return_count());
2379 87894 : return sig->return_count() == 0 ? kWasmStmt : sig->GetReturn();
2380 : }
2381 :
2382 1648981 : Control* PushControl(ControlKind kind) {
2383 : Reachability reachability =
2384 3297962 : control_.empty() ? kReachable : control_.back().innerReachability();
2385 3297962 : control_.emplace_back(kind, stack_size(), this->pc_, reachability);
2386 1648903 : return &control_.back();
2387 : }
2388 :
2389 872930 : void PopControl(Control* c) {
2390 : DCHECK_EQ(c, &control_.back());
2391 522508 : CALL_INTERFACE_IF_PARENT_REACHABLE(PopControl, c);
2392 :
2393 : // A loop just leaves the values on the stack.
2394 809055 : if (!c->is_loop()) PushMergeValues(c, &c->end_merge);
2395 :
2396 : bool parent_reached =
2397 447960 : c->reachable() || c->end_merge.reached || c->is_onearmed_if();
2398 : control_.pop_back();
2399 : // If the parent block was reachable before, but the popped control does not
2400 : // return to here, this block becomes "spec only reachable".
2401 393735 : if (!parent_reached && control_.back().reachable()) {
2402 37523 : control_.back().reachability = kSpecOnlyReachable;
2403 : }
2404 380713 : }
2405 :
2406 192608 : int DecodeLoadMem(LoadType type, int prefix_len = 0) {
2407 192608 : if (!CheckHasMemory()) return 0;
2408 : MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
2409 192568 : type.size_log_2());
2410 : auto index = Pop(0, kWasmI32);
2411 : auto* result = Push(type.value_type());
2412 360551 : CALL_INTERFACE_IF_REACHABLE(LoadMem, type, imm, index, result);
2413 192570 : return imm.length;
2414 : }
2415 :
2416 269709 : int DecodeStoreMem(StoreType store, int prefix_len = 0) {
2417 269709 : if (!CheckHasMemory()) return 0;
2418 : MemoryAccessImmediate<validate> imm(this, this->pc_ + prefix_len,
2419 269686 : store.size_log_2());
2420 : auto value = Pop(1, store.value_type());
2421 : auto index = Pop(0, kWasmI32);
2422 516918 : CALL_INTERFACE_IF_REACHABLE(StoreMem, store, imm, index, value);
2423 269703 : return imm.length;
2424 : }
2425 :
2426 18260 : uint32_t SimdExtractLane(WasmOpcode opcode, ValueType type) {
2427 18260 : SimdLaneImmediate<validate> imm(this, this->pc_);
2428 18260 : if (this->Validate(this->pc_, opcode, imm)) {
2429 0 : Value inputs[] = {Pop(0, kWasmS128)};
2430 : auto* result = Push(type);
2431 36520 : CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
2432 : result);
2433 : }
2434 18260 : return imm.length;
2435 : }
2436 :
2437 416 : uint32_t SimdReplaceLane(WasmOpcode opcode, ValueType type) {
2438 416 : SimdLaneImmediate<validate> imm(this, this->pc_);
2439 416 : if (this->Validate(this->pc_, opcode, imm)) {
2440 416 : Value inputs[2] = {UnreachableValue(this->pc_),
2441 0 : UnreachableValue(this->pc_)};
2442 416 : inputs[1] = Pop(1, type);
2443 416 : inputs[0] = Pop(0, kWasmS128);
2444 : auto* result = Push(kWasmS128);
2445 832 : CALL_INTERFACE_IF_REACHABLE(SimdLaneOp, opcode, imm, ArrayVector(inputs),
2446 : result);
2447 : }
2448 416 : return imm.length;
2449 : }
2450 :
2451 1272 : uint32_t SimdShiftOp(WasmOpcode opcode) {
2452 1272 : SimdShiftImmediate<validate> imm(this, this->pc_);
2453 1272 : if (this->Validate(this->pc_, opcode, imm)) {
2454 : auto input = Pop(0, kWasmS128);
2455 : auto* result = Push(kWasmS128);
2456 2544 : CALL_INTERFACE_IF_REACHABLE(SimdShiftOp, opcode, imm, input, result);
2457 : }
2458 1272 : return imm.length;
2459 : }
2460 :
2461 14545 : uint32_t Simd8x16ShuffleOp() {
2462 14545 : Simd8x16ShuffleImmediate<validate> imm(this, this->pc_);
2463 14545 : if (this->Validate(this->pc_, imm)) {
2464 : auto input1 = Pop(1, kWasmS128);
2465 : auto input0 = Pop(0, kWasmS128);
2466 : auto* result = Push(kWasmS128);
2467 29088 : CALL_INTERFACE_IF_REACHABLE(Simd8x16ShuffleOp, imm, input0, input1,
2468 : result);
2469 : }
2470 14545 : return 16;
2471 : }
2472 :
2473 38681 : uint32_t DecodeSimdOpcode(WasmOpcode opcode) {
2474 : uint32_t len = 0;
2475 38681 : switch (opcode) {
2476 : case kExprF32x4ExtractLane: {
2477 704 : len = SimdExtractLane(opcode, kWasmF32);
2478 704 : break;
2479 : }
2480 : case kExprI32x4ExtractLane:
2481 : case kExprI16x8ExtractLane:
2482 : case kExprI8x16ExtractLane: {
2483 17556 : len = SimdExtractLane(opcode, kWasmI32);
2484 17556 : break;
2485 : }
2486 : case kExprF32x4ReplaceLane: {
2487 64 : len = SimdReplaceLane(opcode, kWasmF32);
2488 64 : break;
2489 : }
2490 : case kExprI32x4ReplaceLane:
2491 : case kExprI16x8ReplaceLane:
2492 : case kExprI8x16ReplaceLane: {
2493 352 : len = SimdReplaceLane(opcode, kWasmI32);
2494 352 : break;
2495 : }
2496 : case kExprI32x4Shl:
2497 : case kExprI32x4ShrS:
2498 : case kExprI32x4ShrU:
2499 : case kExprI16x8Shl:
2500 : case kExprI16x8ShrS:
2501 : case kExprI16x8ShrU:
2502 : case kExprI8x16Shl:
2503 : case kExprI8x16ShrS:
2504 : case kExprI8x16ShrU: {
2505 1272 : len = SimdShiftOp(opcode);
2506 1272 : break;
2507 : }
2508 : case kExprS8x16Shuffle: {
2509 14545 : len = Simd8x16ShuffleOp();
2510 14545 : break;
2511 : }
2512 : case kExprS128LoadMem:
2513 16 : len = DecodeLoadMem(LoadType::kS128Load, 1);
2514 16 : break;
2515 : case kExprS128StoreMem:
2516 8 : len = DecodeStoreMem(StoreType::kS128Store, 1);
2517 8 : break;
2518 : default: {
2519 8328 : FunctionSig* sig = WasmOpcodes::Signature(opcode);
2520 4164 : if (!VALIDATE(sig != nullptr)) {
2521 0 : this->error("invalid simd opcode");
2522 0 : break;
2523 : }
2524 : PopArgs(sig);
2525 : auto* results =
2526 8328 : sig->return_count() == 0 ? nullptr : Push(GetReturnType(sig));
2527 12492 : CALL_INTERFACE_IF_REACHABLE(SimdOp, opcode, VectorOf(args_), results);
2528 : }
2529 : }
2530 38681 : return len;
2531 : }
2532 :
2533 47344 : uint32_t DecodeAtomicOpcode(WasmOpcode opcode) {
2534 : uint32_t len = 0;
2535 : ValueType ret_type;
2536 47344 : FunctionSig* sig = WasmOpcodes::Signature(opcode);
2537 47348 : if (sig != nullptr) {
2538 : MachineType memtype;
2539 47348 : switch (opcode) {
2540 : #define CASE_ATOMIC_STORE_OP(Name, Type) \
2541 : case kExpr##Name: { \
2542 : memtype = MachineType::Type(); \
2543 : ret_type = kWasmStmt; \
2544 : break; \
2545 : }
2546 357 : ATOMIC_STORE_OP_LIST(CASE_ATOMIC_STORE_OP)
2547 : #undef CASE_ATOMIC_OP
2548 : #define CASE_ATOMIC_OP(Name, Type) \
2549 : case kExpr##Name: { \
2550 : memtype = MachineType::Type(); \
2551 : ret_type = GetReturnType(sig); \
2552 : break; \
2553 : }
2554 41877 : ATOMIC_OP_LIST(CASE_ATOMIC_OP)
2555 : #undef CASE_ATOMIC_OP
2556 : default:
2557 0 : this->error("invalid atomic opcode");
2558 0 : return 0;
2559 : }
2560 : MemoryAccessImmediate<validate> imm(
2561 47348 : this, this->pc_ + 1, ElementSizeLog2Of(memtype.representation()));
2562 47369 : len += imm.length;
2563 : PopArgs(sig);
2564 76218 : auto result = ret_type == kWasmStmt ? nullptr : Push(GetReturnType(sig));
2565 127399 : CALL_INTERFACE_IF_REACHABLE(AtomicOp, opcode, VectorOf(args_), imm,
2566 : result);
2567 : } else {
2568 0 : this->error("invalid atomic opcode");
2569 : }
2570 47387 : return len;
2571 : }
2572 :
2573 513 : unsigned DecodeNumericOpcode(WasmOpcode opcode) {
2574 : unsigned len = 0;
2575 1038 : FunctionSig* sig = WasmOpcodes::Signature(opcode);
2576 513 : if (sig != nullptr) {
2577 513 : switch (opcode) {
2578 : case kExprI32SConvertSatF32:
2579 : case kExprI32UConvertSatF32:
2580 : case kExprI32SConvertSatF64:
2581 : case kExprI32UConvertSatF64:
2582 : case kExprI64SConvertSatF32:
2583 : case kExprI64UConvertSatF32:
2584 : case kExprI64SConvertSatF64:
2585 : case kExprI64UConvertSatF64:
2586 96 : BuildSimpleOperator(opcode, sig);
2587 96 : break;
2588 : case kExprMemoryInit: {
2589 78 : MemoryInitImmediate<validate> imm(this, this->pc_);
2590 78 : if (!this->Validate(imm)) break;
2591 77 : len += imm.length;
2592 : auto size = Pop(2, sig->GetParam(2));
2593 : auto src = Pop(1, sig->GetParam(1));
2594 : auto dst = Pop(0, sig->GetParam(0));
2595 152 : CALL_INTERFACE_IF_REACHABLE(MemoryInit, imm, dst, src, size);
2596 : break;
2597 : }
2598 : case kExprDataDrop: {
2599 42 : DataDropImmediate<validate> imm(this, this->pc_);
2600 42 : if (!this->Validate(imm)) break;
2601 41 : len += imm.length;
2602 82 : CALL_INTERFACE_IF_REACHABLE(DataDrop, imm);
2603 : break;
2604 : }
2605 : case kExprMemoryCopy: {
2606 50 : MemoryCopyImmediate<validate> imm(this, this->pc_);
2607 50 : if (!this->Validate(imm)) break;
2608 49 : len += imm.length;
2609 : auto size = Pop(2, sig->GetParam(2));
2610 : auto src = Pop(1, sig->GetParam(1));
2611 : auto dst = Pop(0, sig->GetParam(0));
2612 98 : CALL_INTERFACE_IF_REACHABLE(MemoryCopy, imm, dst, src, size);
2613 : break;
2614 : }
2615 : case kExprMemoryFill: {
2616 50 : MemoryIndexImmediate<validate> imm(this, this->pc_ + 1);
2617 50 : if (!this->Validate(this->pc_ + 1, imm)) break;
2618 49 : len += imm.length;
2619 : auto size = Pop(2, sig->GetParam(2));
2620 : auto value = Pop(1, sig->GetParam(1));
2621 : auto dst = Pop(0, sig->GetParam(0));
2622 98 : CALL_INTERFACE_IF_REACHABLE(MemoryFill, imm, dst, value, size);
2623 : break;
2624 : }
2625 : case kExprTableInit: {
2626 56 : TableInitImmediate<validate> imm(this, this->pc_);
2627 55 : if (!this->Validate(imm)) break;
2628 53 : len += imm.length;
2629 : PopArgs(sig);
2630 133 : CALL_INTERFACE_IF_REACHABLE(TableInit, imm, VectorOf(args_));
2631 : break;
2632 : }
2633 : case kExprElemDrop: {
2634 35 : ElemDropImmediate<validate> imm(this, this->pc_);
2635 35 : if (!this->Validate(imm)) break;
2636 33 : len += imm.length;
2637 66 : CALL_INTERFACE_IF_REACHABLE(ElemDrop, imm);
2638 : break;
2639 : }
2640 : case kExprTableCopy: {
2641 106 : TableCopyImmediate<validate> imm(this, this->pc_);
2642 106 : if (!this->Validate(imm)) break;
2643 105 : len += imm.length;
2644 : PopArgs(sig);
2645 274 : CALL_INTERFACE_IF_REACHABLE(TableCopy, imm, VectorOf(args_));
2646 : break;
2647 : }
2648 : default:
2649 0 : this->error("invalid numeric opcode");
2650 0 : break;
2651 : }
2652 : } else {
2653 0 : this->error("invalid numeric opcode");
2654 : }
2655 513 : return len;
2656 : }
2657 :
2658 1280393 : void DoReturn() {
2659 584681 : size_t return_count = this->sig_->return_count();
2660 : DCHECK_GE(stack_.size(), return_count);
2661 : Vector<Value> return_values =
2662 : return_count == 0
2663 : ? Vector<Value>{}
2664 584681 : : Vector<Value>{&*(stack_.end() - return_count), return_count};
2665 :
2666 2560859 : CALL_INTERFACE_IF_REACHABLE(DoReturn, return_values);
2667 1280345 : }
2668 :
2669 : inline Value* Push(ValueType type) {
2670 : DCHECK_NE(kWasmStmt, type);
2671 7448701 : stack_.emplace_back(this->pc_, type);
2672 : return &stack_.back();
2673 : }
2674 :
2675 780501 : void PushMergeValues(Control* c, Merge<Value>* merge) {
2676 : DCHECK_EQ(c, &control_.back());
2677 : DCHECK(merge == &c->start_merge || merge == &c->end_merge);
2678 1561002 : stack_.erase(stack_.begin() + c->stack_depth, stack_.end());
2679 780518 : if (merge->arity == 1) {
2680 20554 : stack_.push_back(merge->vals.first);
2681 : } else {
2682 302 : for (uint32_t i = 0; i < merge->arity; i++) {
2683 302 : stack_.push_back(merge->vals.array[i]);
2684 : }
2685 : }
2686 : DCHECK_EQ(c->stack_depth + merge->arity, stack_.size());
2687 780518 : }
2688 :
2689 522436 : Value* PushReturns(FunctionSig* sig) {
2690 : size_t return_count = sig->return_count();
2691 273876 : if (return_count == 0) return nullptr;
2692 245595 : size_t old_size = stack_.size();
2693 494155 : for (size_t i = 0; i < return_count; ++i) {
2694 : Push(sig->GetReturn(i));
2695 : }
2696 245595 : return stack_.data() + old_size;
2697 : }
2698 :
2699 : V8_INLINE bool IsSubType(ValueType expected, ValueType actual) {
2700 : return (expected == actual) ||
2701 : (expected == kWasmAnyRef && actual == kWasmNullRef) ||
2702 : (expected == kWasmAnyRef && actual == kWasmAnyFunc) ||
2703 7276117 : (expected == kWasmAnyFunc && actual == kWasmNullRef);
2704 : }
2705 :
2706 : V8_INLINE Value Pop(int index, ValueType expected) {
2707 : auto val = Pop();
2708 8312350 : if (!VALIDATE(IsSubType(expected, val.type) || val.type == kWasmVar ||
2709 : expected == kWasmVar)) {
2710 33340 : this->errorf(val.pc, "%s[%d] expected type %s, found %s of type %s",
2711 : SafeOpcodeNameAt(this->pc_), index,
2712 : ValueTypes::TypeName(expected), SafeOpcodeNameAt(val.pc),
2713 : ValueTypes::TypeName(val.type));
2714 : }
2715 : return val;
2716 : }
2717 :
2718 : V8_INLINE Value Pop() {
2719 : DCHECK(!control_.empty());
2720 6371636 : uint32_t limit = control_.back().stack_depth;
2721 6371651 : if (stack_.size() <= limit) {
2722 : // Popping past the current control start in reachable code.
2723 12930 : if (!VALIDATE(control_.back().unreachable())) {
2724 4752 : this->errorf(this->pc_, "%s found empty stack",
2725 : SafeOpcodeNameAt(this->pc_));
2726 : }
2727 12931 : return UnreachableValue(this->pc_);
2728 : }
2729 6358734 : auto val = stack_.back();
2730 6358685 : stack_.pop_back();
2731 2124161 : return val;
2732 : }
2733 :
2734 4665 : int startrel(const byte* ptr) { return static_cast<int>(ptr - this->start_); }
2735 :
2736 542 : void FallThruTo(Control* c) {
2737 : DCHECK_EQ(c, &control_.back());
2738 530 : if (!TypeCheckFallThru(c)) return;
2739 532 : if (!c->reachable()) return;
2740 :
2741 320 : if (!c->is_loop()) CALL_INTERFACE(FallThruTo, c);
2742 332 : c->end_merge.reached = true;
2743 : }
2744 :
2745 997021 : bool TypeCheckMergeValues(Control* c, Merge<Value>* merge) {
2746 : DCHECK(merge == &c->start_merge || merge == &c->end_merge);
2747 : DCHECK_GE(stack_.size(), c->stack_depth + merge->arity);
2748 : // The computation of {stack_values} is only valid if {merge->arity} is >0.
2749 : DCHECK_LT(0, merge->arity);
2750 997021 : Value* stack_values = &*(stack_.end() - merge->arity);
2751 : // Typecheck the topmost {merge->arity} values on the stack.
2752 1030555 : for (uint32_t i = 0; i < merge->arity; ++i) {
2753 999661 : Value& val = stack_values[i];
2754 : Value& old = (*merge)[i];
2755 1999322 : if (IsSubType(old.type, val.type)) continue;
2756 : // If {val.type} is polymorphic, which results from unreachable, make
2757 : // it more specific by using the merge value's expected type.
2758 : // If it is not polymorphic, this is a type error.
2759 28455 : if (!VALIDATE(val.type == kWasmVar)) {
2760 4238 : this->errorf(this->pc_, "type error in merge[%u] (expected %s, got %s)",
2761 : i, ValueTypes::TypeName(old.type),
2762 : ValueTypes::TypeName(val.type));
2763 2498 : return false;
2764 : }
2765 24217 : val.type = old.type;
2766 : }
2767 :
2768 : return true;
2769 : }
2770 :
2771 1613294 : bool TypeCheckFallThru(Control* c) {
2772 : DCHECK_EQ(c, &control_.back());
2773 : if (!validate) return true;
2774 1609769 : uint32_t expected = c->end_merge.arity;
2775 : DCHECK_GE(stack_.size(), c->stack_depth);
2776 3219538 : uint32_t actual = static_cast<uint32_t>(stack_.size()) - c->stack_depth;
2777 : // Fallthrus must match the arity of the control exactly.
2778 1609769 : if (!InsertUnreachablesIfNecessary(expected, actual) || actual > expected) {
2779 7050 : this->errorf(
2780 : this->pc_,
2781 : "expected %u elements on the stack for fallthru to @%d, found %u",
2782 : expected, startrel(c->pc), actual);
2783 3525 : return false;
2784 : }
2785 1606498 : if (expected == 0) return true; // Fast path.
2786 :
2787 985737 : return TypeCheckMergeValues(c, &c->end_merge);
2788 : }
2789 :
2790 300223 : bool TypeCheckBranch(Control* c) {
2791 : // Branches must have at least the number of values expected; can have more.
2792 299083 : uint32_t expected = c->br_merge()->arity;
2793 299083 : if (expected == 0) return true; // Fast path.
2794 : DCHECK_GE(stack_.size(), control_.back().stack_depth);
2795 : uint32_t actual =
2796 37497 : static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth;
2797 12499 : if (!InsertUnreachablesIfNecessary(expected, actual)) {
2798 2280 : this->errorf(this->pc_,
2799 : "expected %u elements on the stack for br to @%d, found %u",
2800 : expected, startrel(c->pc), actual);
2801 1140 : return false;
2802 : }
2803 11359 : return TypeCheckMergeValues(c, c->br_merge());
2804 : }
2805 :
2806 321014 : bool TypeCheckReturn() {
2807 : // Returns must have at least the number of values expected; can have more.
2808 411229 : uint32_t num_returns = static_cast<uint32_t>(this->sig_->return_count());
2809 : DCHECK_GE(stack_.size(), control_.back().stack_depth);
2810 : uint32_t actual =
2811 963042 : static_cast<uint32_t>(stack_.size()) - control_.back().stack_depth;
2812 321014 : if (!InsertUnreachablesIfNecessary(num_returns, actual)) {
2813 285 : this->errorf(this->pc_,
2814 : "expected %u elements on the stack for return, found %u",
2815 : num_returns, actual);
2816 285 : return false;
2817 : }
2818 :
2819 : // Typecheck the topmost {num_returns} values on the stack.
2820 320746 : if (num_returns == 0) return true;
2821 : // This line requires num_returns > 0.
2822 : Value* stack_values = &*(stack_.end() - num_returns);
2823 180265 : for (uint32_t i = 0; i < num_returns; ++i) {
2824 90215 : auto& val = stack_values[i];
2825 90215 : ValueType expected_type = this->sig_->GetReturn(i);
2826 180430 : if (IsSubType(expected_type, val.type)) continue;
2827 : // If {val.type} is polymorphic, which results from unreachable,
2828 : // make it more specific by using the return's expected type.
2829 : // If it is not polymorphic, this is a type error.
2830 237 : if (!VALIDATE(val.type == kWasmVar)) {
2831 141 : this->errorf(this->pc_,
2832 : "type error in return[%u] (expected %s, got %s)", i,
2833 : ValueTypes::TypeName(expected_type),
2834 : ValueTypes::TypeName(val.type));
2835 145 : return false;
2836 : }
2837 96 : val.type = expected_type;
2838 : }
2839 : return true;
2840 : }
2841 :
2842 1943297 : inline bool InsertUnreachablesIfNecessary(uint32_t expected,
2843 : uint32_t actual) {
2844 1943297 : if (V8_LIKELY(actual >= expected)) {
2845 : return true; // enough actual values are there.
2846 : }
2847 26368 : if (!VALIDATE(control_.back().unreachable())) {
2848 : // There aren't enough values on the stack.
2849 : return false;
2850 : }
2851 : // A slow path. When the actual number of values on the stack is less
2852 : // than the expected number of values and the current control is
2853 : // unreachable, insert unreachable values below the actual values.
2854 : // This simplifies {TypeCheckMergeValues}.
2855 46868 : auto pos = stack_.begin() + (stack_.size() - actual);
2856 66179 : stack_.insert(pos, expected - actual, UnreachableValue(this->pc_));
2857 23441 : return true;
2858 : }
2859 :
2860 55900 : void onFirstError() override {
2861 55900 : this->end_ = this->pc_; // Terminate decoding loop.
2862 : TRACE(" !%s\n", this->error_.message().c_str());
2863 : CALL_INTERFACE(OnFirstError);
2864 55900 : }
2865 :
2866 88 : void BuildSimplePrototypeOperator(WasmOpcode opcode) {
2867 88 : if (WasmOpcodes::IsSignExtensionOpcode(opcode)) {
2868 56 : RET_ON_PROTOTYPE_OPCODE(se);
2869 : }
2870 88 : if (WasmOpcodes::IsAnyRefOpcode(opcode)) {
2871 32 : RET_ON_PROTOTYPE_OPCODE(anyref);
2872 : }
2873 88 : FunctionSig* sig = WasmOpcodes::Signature(opcode);
2874 88 : BuildSimpleOperator(opcode, sig);
2875 88 : }
2876 :
2877 444157 : void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
2878 100344 : switch (sig->parameter_count()) {
2879 : case 1: {
2880 : auto val = Pop(0, sig->GetParam(0));
2881 : auto* ret =
2882 114555 : sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
2883 114176 : CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, val, ret);
2884 : break;
2885 : }
2886 : case 2: {
2887 : auto rval = Pop(1, sig->GetParam(1));
2888 : auto lval = Pop(0, sig->GetParam(0));
2889 : auto* ret =
2890 83962 : sig->return_count() == 0 ? nullptr : Push(sig->GetReturn(0));
2891 82562 : CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, lval, rval, ret);
2892 : break;
2893 : }
2894 : default:
2895 0 : UNREACHABLE();
2896 : }
2897 100344 : }
2898 :
2899 490829 : void BuildSimpleOperator(WasmOpcode opcode, ValueType return_type,
2900 : ValueType arg_type) {
2901 : auto val = Pop(0, arg_type);
2902 543958 : auto* ret = return_type == kWasmStmt ? nullptr : Push(return_type);
2903 557226 : CALL_INTERFACE_IF_REACHABLE(UnOp, opcode, val, ret);
2904 490806 : }
2905 :
2906 1619660 : void BuildSimpleOperator(WasmOpcode opcode, ValueType return_type,
2907 : ValueType lhs_type, ValueType rhs_type) {
2908 : auto rval = Pop(1, rhs_type);
2909 : auto lval = Pop(0, lhs_type);
2910 2330682 : auto* ret = return_type == kWasmStmt ? nullptr : Push(return_type);
2911 2950999 : CALL_INTERFACE_IF_REACHABLE(BinOp, opcode, lval, rval, ret);
2912 1619623 : }
2913 :
2914 : #define DEFINE_SIMPLE_SIG_OPERATOR(sig, ...) \
2915 : void BuildSimpleOperator_##sig(WasmOpcode opcode) { \
2916 : BuildSimpleOperator(opcode, __VA_ARGS__); \
2917 : }
2918 221021 : FOREACH_SIGNATURE(DEFINE_SIMPLE_SIG_OPERATOR)
2919 : #undef DEFINE_SIMPLE_SIG_OPERATOR
2920 : };
2921 :
2922 : #undef CALL_INTERFACE
2923 : #undef CALL_INTERFACE_IF_REACHABLE
2924 : #undef CALL_INTERFACE_IF_PARENT_REACHABLE
2925 :
2926 : class EmptyInterface {
2927 : public:
2928 : static constexpr Decoder::ValidateFlag validate = Decoder::kValidate;
2929 : using Value = ValueBase;
2930 : using Control = ControlBase<Value>;
2931 : using FullDecoder = WasmFullDecoder<validate, EmptyInterface>;
2932 :
2933 : #define DEFINE_EMPTY_CALLBACK(name, ...) \
2934 : void name(FullDecoder* decoder, ##__VA_ARGS__) {}
2935 : INTERFACE_FUNCTIONS(DEFINE_EMPTY_CALLBACK)
2936 : #undef DEFINE_EMPTY_CALLBACK
2937 : };
2938 :
2939 : #undef TRACE
2940 : #undef TRACE_INST_FORMAT
2941 : #undef VALIDATE
2942 : #undef CHECK_PROTOTYPE_OPCODE
2943 : #undef OPCODE_ERROR
2944 :
2945 : } // namespace wasm
2946 : } // namespace internal
2947 : } // namespace v8
2948 :
2949 : #endif // V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
|