v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
decoder.h
Go to the documentation of this file.
1// Copyright 2015 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_DECODER_H_
6#define V8_WASM_DECODER_H_
7
8#if !V8_ENABLE_WEBASSEMBLY
9#error This header should only be included if WebAssembly is enabled.
10#endif // !V8_ENABLE_WEBASSEMBLY
11
12#include <cinttypes>
13#include <cstdarg>
14#include <memory>
15
17#include "src/base/memory.h"
18#include "src/base/strings.h"
19#include "src/base/vector.h"
20#include "src/flags/flags.h"
21#include "src/utils/utils.h"
24
25namespace v8 {
26namespace internal {
27namespace wasm {
28
29#define TRACE(...) \
30 do { \
31 if (v8_flags.trace_wasm_decoder) PrintF(__VA_ARGS__); \
32 } while (false)
33#define TRACE_IF(cond, ...) \
34 do { \
35 if (v8_flags.trace_wasm_decoder && (cond)) PrintF(__VA_ARGS__); \
36 } while (false)
37
38// A {DecodeResult} only stores the failure / success status, but no data.
40
41struct WasmFunction;
42
43class ITracer {
44 public:
45 static constexpr ITracer* NoTrace = nullptr;
46
47 // Hooks for extracting byte offsets of things.
48 virtual void TypeOffset(uint32_t offset) = 0;
49 virtual void ImportOffset(uint32_t offset) = 0;
50 virtual void ImportsDone(const WasmModule* module) = 0;
51 virtual void TableOffset(uint32_t offset) = 0;
52 virtual void MemoryOffset(uint32_t offset) = 0;
53 virtual void TagOffset(uint32_t offset) = 0;
54 virtual void GlobalOffset(uint32_t offset) = 0;
55 virtual void StartOffset(uint32_t offset) = 0;
56 virtual void ElementOffset(uint32_t offset) = 0;
57 virtual void DataOffset(uint32_t offset) = 0;
58 virtual void StringOffset(uint32_t offset) = 0;
59 virtual void RecGroupOffset(uint32_t offset, uint32_t group_size) = 0;
60
61 // Hooks for annotated hex dumps.
62 virtual void Bytes(const uint8_t* start, uint32_t count) = 0;
63
64 virtual void Description(const char* desc) = 0;
65 virtual void Description(const char* desc, size_t length) = 0;
66 virtual void Description(uint32_t number) = 0;
67 virtual void Description(uint64_t number) = 0;
68 virtual void Description(ValueType type) = 0;
69 virtual void Description(HeapType type) = 0;
70 virtual void Description(const FunctionSig* sig) = 0;
71
72 virtual void NextLine() = 0;
73 virtual void NextLineIfFull() = 0;
74 virtual void NextLineIfNonEmpty() = 0;
75
76 virtual void InitializerExpression(const uint8_t* start, const uint8_t* end,
77 ValueType expected_type) = 0;
78 virtual void FunctionBody(const WasmFunction* func, const uint8_t* start) = 0;
79 virtual void FunctionName(uint32_t func_index) = 0;
80 virtual void NameSection(const uint8_t* start, const uint8_t* end,
81 uint32_t offset) = 0;
82
83 virtual ~ITracer() = default;
84};
85
86// A helper utility to decode bytes, integers, fields, varints, etc, from
87// a buffer of bytes.
88class Decoder {
89 public:
90 // Don't run validation, assume valid input.
91 static constexpr struct NoValidationTag {
92 static constexpr bool validate = false;
94 // Run full validation with error message and location.
95 static constexpr struct FullValidationTag {
96 static constexpr bool validate = true;
98
99 struct NoName {
100 constexpr NoName(const char*) {} // NOLINT(runtime/explicit)
101 operator const char*() const { UNREACHABLE(); }
102 };
103 // Pass a {NoName} if we know statically that we do not use it anyway (we are
104 // not tracing (in release mode) and not running full validation).
105#ifdef DEBUG
106 template <typename ValidationTag>
107 using Name = const char*;
108#else
109 template <typename ValidationTag>
110 using Name = std::conditional_t<ValidationTag::validate, const char*, NoName>;
111#endif
112
113 enum TraceFlag : bool { kTrace = true, kNoTrace = false };
114
115 Decoder(const uint8_t* start, const uint8_t* end, uint32_t buffer_offset = 0)
118 uint32_t buffer_offset = 0)
119 : Decoder(bytes.begin(), bytes.begin() + bytes.length(), buffer_offset) {}
120 Decoder(const uint8_t* start, const uint8_t* pc, const uint8_t* end,
121 uint32_t buffer_offset = 0)
124 DCHECK_LE(pc, end);
125 DCHECK_EQ(static_cast<uint32_t>(end - start), end - start);
126 }
127
128 virtual ~Decoder() = default;
129
130 // Reads an 8-bit unsigned integer.
131 template <typename ValidationTag>
132 uint8_t read_u8(const uint8_t* pc,
133 Name<ValidationTag> msg = "expected 1 byte") {
135 }
136
137 // Reads a 16-bit unsigned integer (little endian).
138 template <typename ValidationTag>
139 uint16_t read_u16(const uint8_t* pc,
140 Name<ValidationTag> msg = "expected 2 bytes") {
142 }
143
144 // Reads a 32-bit unsigned integer (little endian).
145 template <typename ValidationTag>
146 uint32_t read_u32(const uint8_t* pc,
147 Name<ValidationTag> msg = "expected 4 bytes") {
149 }
150
151 // Reads a 64-bit unsigned integer (little endian).
152 template <typename ValidationTag>
153 uint64_t read_u64(const uint8_t* pc,
154 Name<ValidationTag> msg = "expected 8 bytes") {
156 }
157
158 // Reads a variable-length unsigned integer (little endian). Returns the read
159 // value and the number of bytes read.
160 template <typename ValidationTag>
161 std::pair<uint32_t, uint32_t> read_u32v(const uint8_t* pc,
162 Name<ValidationTag> name = "LEB32") {
164 }
165
166 // Reads a variable-length signed integer (little endian). Returns the read
167 // value and the number of bytes read.
168 template <typename ValidationTag>
169 std::pair<int32_t, uint32_t> read_i32v(
170 const uint8_t* pc, Name<ValidationTag> name = "signed LEB32") {
172 }
173
174 // Reads a variable-length unsigned integer (little endian). Returns the read
175 // value and the number of bytes read.
176 template <typename ValidationTag>
177 std::pair<uint64_t, uint32_t> read_u64v(const uint8_t* pc,
178 Name<ValidationTag> name = "LEB64") {
180 }
181
182 // Reads a variable-length signed integer (little endian). Returns the read
183 // value and the number of bytes read.
184 template <typename ValidationTag>
185 std::pair<int64_t, uint32_t> read_i64v(
186 const uint8_t* pc, Name<ValidationTag> name = "signed LEB64") {
188 }
189
190 // Reads a variable-length 33-bit signed integer (little endian). Returns the
191 // read value and the number of bytes read.
192 template <typename ValidationTag>
193 std::pair<int64_t, uint32_t> read_i33v(
194 const uint8_t* pc, Name<ValidationTag> name = "signed LEB33") {
196 }
197
198 // Reads a prefixed-opcode, possibly with variable-length index.
199 // Returns the read opcode and the number of bytes that make up this opcode,
200 // *including* the prefix byte. For most opcodes, it will be 2.
201 template <typename ValidationTag>
202 std::pair<WasmOpcode, uint32_t> read_prefixed_opcode(
203 const uint8_t* pc, Name<ValidationTag> name = "prefixed opcode") {
204 // Prefixed opcodes all use LEB128 encoding.
205 auto [index, index_length] =
206 read_u32v<ValidationTag>(pc + 1, "prefixed opcode index");
207 uint32_t length = index_length + 1; // 1 for prefix byte.
208 // Only support opcodes that go up to 0xFFF (when decoded). Anything
209 // bigger will need more than 2 bytes, and the '<< 12' below will be wrong.
210 if (ValidationTag::validate && V8_UNLIKELY(index > 0xfff)) {
211 errorf(pc, "Invalid prefixed opcode %d", index);
212 // On validation failure we return "unreachable" (opcode 0).
213 static_assert(kExprUnreachable == 0);
214 return {kExprUnreachable, 0};
215 }
216
217 if (index > 0xff) {
218 return {static_cast<WasmOpcode>((*pc) << 12 | index), length};
219 }
220
221 return {static_cast<WasmOpcode>((*pc) << 8 | index), length};
222 }
223
224 // Reads a 8-bit unsigned integer (byte) and advances {pc_}.
225 uint8_t consume_u8(const char* name = "uint8_t") {
227 }
228 uint8_t consume_u8(const char* name, ITracer* tracer) {
229 if (tracer) {
230 tracer->Bytes(pc_, sizeof(uint8_t));
231 tracer->Description(name);
232 }
234 }
235
236 // Reads a 16-bit unsigned integer (little endian) and advances {pc_}.
237 uint16_t consume_u16(const char* name = "uint16_t") {
239 }
240
241 // Reads a single 32-bit unsigned integer (little endian) and advances {pc_}.
242 uint32_t consume_u32(const char* name, ITracer* tracer) {
243 if (tracer) {
244 tracer->Bytes(pc_, sizeof(uint32_t));
245 tracer->Description(name);
246 }
248 }
249
250 // Reads a LEB128 variable-length unsigned 32-bit integer and advances {pc_}.
251 uint32_t consume_u32v(const char* name = "var_uint32") {
252 auto [result, length] =
254 pc_ += length;
255 return result;
256 }
257 uint32_t consume_u32v(const char* name, ITracer* tracer) {
258 auto [result, length] =
260 if (tracer) {
261 tracer->Bytes(pc_, length);
262 tracer->Description(name);
263 }
264 pc_ += length;
265 return result;
266 }
267
268 // Reads a LEB128 variable-length signed 32-bit integer and advances {pc_}.
269 int32_t consume_i32v(const char* name = "var_int32") {
270 auto [result, length] =
272 pc_ += length;
273 return result;
274 }
275
276 // Reads a LEB128 variable-length unsigned 64-bit integer and advances {pc_}.
277 uint64_t consume_u64v(const char* name, ITracer* tracer) {
278 auto [result, length] =
280 if (tracer) {
281 tracer->Bytes(pc_, length);
282 tracer->Description(name);
283 }
284 pc_ += length;
285 return result;
286 }
287
288 // Reads a LEB128 variable-length signed 64-bit integer and advances {pc_}.
289 int64_t consume_i64v(const char* name = "var_int64") {
290 auto [result, length] =
292 pc_ += length;
293 return result;
294 }
295
296 // Consume {size} bytes and send them to the bit bucket, advancing {pc_}.
297 void consume_bytes(uint32_t size, const char* name = "skip") {
298 // Only trace if the name is not null.
299 TRACE_IF(name, " +%u %-20s: %u bytes\n", pc_offset(), name, size);
300 if (checkAvailable(size)) {
301 pc_ += size;
302 } else {
303 pc_ = end_;
304 }
305 }
306 void consume_bytes(uint32_t size, const char* name, ITracer* tracer) {
307 if (tracer) {
308 tracer->Bytes(pc_, size);
309 tracer->Description(name);
310 }
311 consume_bytes(size, nullptr);
312 }
313
314 uint32_t available_bytes() const {
317 return static_cast<uint32_t>(end_ - pc_);
318 }
319
320 // Check that at least {size} bytes exist between {pc_} and {end_}.
321 bool checkAvailable(uint32_t size) {
322 if (V8_UNLIKELY(size > available_bytes())) {
323 errorf(pc_, "expected %u bytes, fell off end", size);
324 return false;
325 }
326 return true;
327 }
328
329 // Do not inline error methods. This has measurable impact on validation time,
330 // see https://crbug.com/910432.
331 void V8_NOINLINE V8_PRESERVE_MOST error(const char* msg) {
332 errorf(pc_offset(), "%s", msg);
333 }
334 void V8_NOINLINE V8_PRESERVE_MOST error(const uint8_t* pc, const char* msg) {
335 errorf(pc_offset(pc), "%s", msg);
336 }
337 void V8_NOINLINE V8_PRESERVE_MOST error(uint32_t offset, const char* msg) {
338 errorf(offset, "%s", msg);
339 }
340
341 template <typename... Args>
342 void V8_NOINLINE V8_PRESERVE_MOST errorf(const char* format, Args... args) {
343 errorf(pc_offset(), format, args...);
344 }
345
346 template <typename... Args>
348 const char* format, Args... args) {
349 errorf(pc_offset(pc), format, args...);
350 }
351
352 template <typename... Args>
353 void V8_NOINLINE V8_PRESERVE_MOST errorf(uint32_t offset, const char* format,
354 Args... args) {
355 static_assert(
356 sizeof...(Args) > 0,
357 "Use error instead of errorf if the format string has no placeholders");
358 verrorf(offset, format, args...);
359 }
360
361 // Behavior triggered on first error, overridden in subclasses.
362 virtual void onFirstError() {}
363
364 // Debugging helper to print a bytes range as hex bytes.
365 void traceByteRange(const uint8_t* start, const uint8_t* end) {
367 for (const uint8_t* p = start; p < end; ++p) TRACE("%02x ", *p);
368 }
369
370 // Debugging helper to print bytes up to the end.
371 void traceOffEnd() {
373 TRACE("<end>\n");
374 }
375
376 // Converts the given value to a {Result}, copying the error if necessary.
377 template <typename T, typename R = std::decay_t<T>>
379 if (failed()) {
380 TRACE("Result error: %s\n", error_.message().c_str());
381 return Result<R>{error_};
382 }
383 return Result<R>{std::forward<T>(val)};
384 }
385
386 // Resets the boundaries of this decoder.
387 void Reset(const uint8_t* start, const uint8_t* end,
388 uint32_t buffer_offset = 0) {
390 DCHECK_EQ(static_cast<uint32_t>(end - start), end - start);
391 start_ = start;
392 pc_ = start;
393 end_ = end;
395 error_ = {};
396 }
397
399 Reset(bytes.begin(), bytes.end(), buffer_offset);
400 }
401
402 bool ok() const { return !failed(); }
403 bool failed() const { return error_.has_error(); }
404 bool more() const { return pc_ < end_; }
405 const WasmError& error() const { return error_; }
406
407 const uint8_t* start() const { return start_; }
408 const uint8_t* pc() const { return pc_; }
409 uint32_t V8_INLINE position() const {
410 return static_cast<uint32_t>(pc_ - start_);
411 }
412 // This needs to be inlined for performance (see https://crbug.com/910432).
413 uint32_t V8_INLINE pc_offset(const uint8_t* pc) const {
416 return static_cast<uint32_t>(pc - start_) + buffer_offset_;
417 }
418 uint32_t pc_offset() const { return pc_offset(pc_); }
419 uint32_t buffer_offset() const { return buffer_offset_; }
420 // Takes an offset relative to the module start and returns an offset relative
421 // to the current buffer of the decoder.
422 uint32_t GetBufferRelativeOffset(uint32_t offset) const {
424 return offset - buffer_offset_;
425 }
426 const uint8_t* end() const { return end_; }
427 void set_end(const uint8_t* end) { end_ = end; }
428
429 // Check if the uint8_t at {offset} from the current pc equals {expected}.
430 bool lookahead(int offset, uint8_t expected) {
432 return end_ - pc_ > offset && pc_[offset] == expected;
433 }
434
435 protected:
436 const uint8_t* start_;
437 const uint8_t* pc_;
438 const uint8_t* end_;
439 // The offset of the current buffer in the module. Needed for streaming.
442
443 private:
445 verrorf(uint32_t offset, const char* format, ...) {
446 // Only report the first error.
447 if (!ok()) return;
448 constexpr int kMaxErrorMsg = 256;
450 va_list args;
451 va_start(args, format);
455 error_ = {offset, {buffer.begin(), static_cast<size_t>(len)}};
457 }
458
459 template <typename IntType, typename ValidationTag>
460 IntType read_little_endian(const uint8_t* pc, Name<ValidationTag> msg) {
462
463 if (!ValidationTag::validate) {
464 DCHECK_LE(pc, end_);
465 DCHECK_LE(sizeof(IntType), end_ - pc);
466 } else if (V8_UNLIKELY(ptrdiff_t{sizeof(IntType)} > end_ - pc)) {
467 error(pc, msg);
468 return 0;
469 }
470 return base::ReadLittleEndianValue<IntType>(reinterpret_cast<Address>(pc));
471 }
472
473 template <typename IntType, TraceFlag trace>
474 IntType consume_little_endian(const char* name) {
475 TRACE_IF(trace, " +%u %-20s: ", pc_offset(), name);
476 if (!checkAvailable(sizeof(IntType))) {
477 traceOffEnd();
478 pc_ = end_;
479 return IntType{0};
480 }
482 traceByteRange(pc_, pc_ + sizeof(IntType));
483 TRACE_IF(trace, "= %d\n", val);
484 pc_ += sizeof(IntType);
485 return val;
486 }
487
488 // The implementation of LEB-decoding; returns the value and the number of
489 // bytes read.
490 template <typename IntType, typename ValidationTag, TraceFlag trace,
491 size_t size_in_bits = 8 * sizeof(IntType)>
492 V8_INLINE std::pair<IntType, uint32_t> read_leb(
493 const uint8_t* pc, Name<ValidationTag> name = "varint") {
494 static_assert(size_in_bits <= 8 * sizeof(IntType),
495 "leb does not fit in type");
496 TRACE_IF(trace, " +%u %-20s: ", pc_offset(),
498 // Fast path for single-byte integers.
499 if (V8_LIKELY((!ValidationTag::validate || pc < end_) && !(*pc & 0x80))) {
500 TRACE_IF(trace, "%02x ", *pc);
501 IntType result = *pc;
502 if (std::is_signed<IntType>::value) {
503 // Perform sign extension.
504 constexpr int sign_ext_shift = int{8 * sizeof(IntType)} - 7;
505 result = (result << sign_ext_shift) >> sign_ext_shift;
506 TRACE_IF(trace, "= %" PRIi64 "\n", static_cast<int64_t>(result));
507 } else {
508 TRACE_IF(trace, "= %" PRIu64 "\n", static_cast<uint64_t>(result));
509 }
510 return {result, 1};
511 }
512 auto [result, length] =
514 name);
515 V8_ASSUME(length >= 0 && length <= (size_in_bits + 6) / 7);
516 V8_ASSUME(ValidationTag::validate || length >= 1);
517 return {result, length};
518 }
519
520 template <typename IntType, typename ValidationTag, TraceFlag trace,
521 size_t size_in_bits = 8 * sizeof(IntType)>
522 V8_NOINLINE V8_PRESERVE_MOST std::pair<IntType, uint32_t> read_leb_slowpath(
523 const uint8_t* pc, Name<ValidationTag> name) {
524 // Create an unrolled LEB decoding function per integer type.
526 pc, name, 0);
527 }
528
529 template <typename IntType, typename ValidationTag, TraceFlag trace,
530 size_t size_in_bits, int byte_index>
531 V8_INLINE std::pair<IntType, uint32_t> read_leb_tail(
532 const uint8_t* pc, Name<ValidationTag> name,
533 IntType intermediate_result) {
534 constexpr bool is_signed = std::is_signed<IntType>::value;
535 constexpr int kMaxLength = (size_in_bits + 6) / 7;
536 static_assert(byte_index < kMaxLength, "invalid template instantiation");
537 constexpr int shift = byte_index * 7;
538 constexpr bool is_last_byte = byte_index == kMaxLength - 1;
539 const bool at_end = ValidationTag::validate && pc >= end_;
540 uint8_t b = 0;
541 if (V8_LIKELY(!at_end)) {
542 DCHECK_LT(pc, end_);
543 b = *pc;
544 TRACE_IF(trace, "%02x ", b);
545 using Unsigned = typename std::make_unsigned<IntType>::type;
546 intermediate_result |=
547 (static_cast<Unsigned>(static_cast<IntType>(b) & 0x7f) << shift);
548 }
549 if (!is_last_byte && (b & 0x80)) {
550 // Make sure that we only instantiate the template for valid byte indexes.
551 // Compilers are not smart enough to figure out statically that the
552 // following call is unreachable if is_last_byte is false.
553 constexpr int next_byte_index = byte_index + (is_last_byte ? 0 : 1);
554 return read_leb_tail<IntType, ValidationTag, trace, size_in_bits,
555 next_byte_index>(pc + 1, name, intermediate_result);
556 }
557 if (ValidationTag::validate && V8_UNLIKELY(at_end || (b & 0x80))) {
558 TRACE_IF(trace, at_end ? "<end> " : "<length overflow> ");
559 errorf(pc, "%s while decoding %s",
560 at_end ? "reached end" : "length overflow", name);
561 return {0, 0};
562 }
563 if constexpr (is_last_byte) {
564 // A signed-LEB128 must sign-extend the final byte, excluding its
565 // most-significant bit; e.g. for a 32-bit LEB128:
566 // kExtraBits = 4 (== 32 - (5-1) * 7)
567 // For unsigned values, the extra bits must be all zero.
568 // For signed values, the extra bits *plus* the most significant bit must
569 // either be 0, or all ones.
570 constexpr int kExtraBits = size_in_bits - ((kMaxLength - 1) * 7);
571 constexpr int kSignExtBits = kExtraBits - (is_signed ? 1 : 0);
572 const uint8_t checked_bits = b & (0xFF << kSignExtBits);
573 constexpr uint8_t kSignExtendedExtraBits = 0x7f & (0xFF << kSignExtBits);
574 const bool valid_extra_bits =
575 checked_bits == 0 ||
576 (is_signed && checked_bits == kSignExtendedExtraBits);
577 if (!ValidationTag::validate) {
578 DCHECK(valid_extra_bits);
579 } else if (V8_UNLIKELY(!valid_extra_bits)) {
580 error(pc, "extra bits in varint");
581 return {0, 0};
582 }
583 }
584 constexpr int sign_ext_shift =
585 is_signed ? std::max(0, int{8 * sizeof(IntType)} - shift - 7) : 0;
586 // Perform sign extension.
587 intermediate_result =
588 (intermediate_result << sign_ext_shift) >> sign_ext_shift;
589 if (trace && is_signed) {
590 TRACE("= %" PRIi64 "\n", static_cast<int64_t>(intermediate_result));
591 } else if (trace) {
592 TRACE("= %" PRIu64 "\n", static_cast<uint64_t>(intermediate_result));
593 }
594 const uint32_t length = byte_index + 1;
595 return {intermediate_result, length};
596 }
597};
598
599#undef TRACE
600} // namespace wasm
601} // namespace internal
602} // namespace v8
603
604#endif // V8_WASM_DECODER_H_
constexpr T * begin() const
Definition vector.h:96
uint64_t read_u64(const uint8_t *pc, Name< ValidationTag > msg="expected 8 bytes")
Definition decoder.h:153
const uint8_t * start_
Definition decoder.h:436
void V8_NOINLINE V8_PRESERVE_MOST errorf(const uint8_t *pc, const char *format, Args... args)
Definition decoder.h:347
void V8_NOINLINE PRINTF_FORMAT(3, 4) verrorf(uint32_t offset
const uint8_t * start() const
Definition decoder.h:407
Result< R > toResult(T &&val)
Definition decoder.h:378
std::pair< int64_t, uint32_t > read_i64v(const uint8_t *pc, Name< ValidationTag > name="signed LEB64")
Definition decoder.h:185
uint32_t read_u32(const uint8_t *pc, Name< ValidationTag > msg="expected 4 bytes")
Definition decoder.h:146
int32_t consume_i32v(const char *name="var_int32")
Definition decoder.h:269
std::pair< int64_t, uint32_t > read_i33v(const uint8_t *pc, Name< ValidationTag > name="signed LEB33")
Definition decoder.h:193
uint32_t consume_u32(const char *name, ITracer *tracer)
Definition decoder.h:242
uint16_t read_u16(const uint8_t *pc, Name< ValidationTag > msg="expected 2 bytes")
Definition decoder.h:139
uint32_t available_bytes() const
Definition decoder.h:314
std::conditional_t< ValidationTag::validate, const char *, NoName > Name
Definition decoder.h:110
std::pair< uint64_t, uint32_t > read_u64v(const uint8_t *pc, Name< ValidationTag > name="LEB64")
Definition decoder.h:177
void V8_NOINLINE V8_PRESERVE_MOST errorf(const char *format, Args... args)
Definition decoder.h:342
const WasmError & error() const
Definition decoder.h:405
V8_INLINE std::pair< IntType, uint32_t > read_leb(const uint8_t *pc, Name< ValidationTag > name="varint")
Definition decoder.h:492
uint8_t consume_u8(const char *name, ITracer *tracer)
Definition decoder.h:228
IntType read_little_endian(const uint8_t *pc, Name< ValidationTag > msg)
Definition decoder.h:460
Decoder(const uint8_t *start, const uint8_t *end, uint32_t buffer_offset=0)
Definition decoder.h:115
const uint8_t * pc() const
Definition decoder.h:408
V8_INLINE std::pair< IntType, uint32_t > read_leb_tail(const uint8_t *pc, Name< ValidationTag > name, IntType intermediate_result)
Definition decoder.h:531
Decoder(const uint8_t *start, const uint8_t *pc, const uint8_t *end, uint32_t buffer_offset=0)
Definition decoder.h:120
void Reset(base::Vector< const uint8_t > bytes, uint32_t buffer_offset=0)
Definition decoder.h:398
void Reset(const uint8_t *start, const uint8_t *end, uint32_t buffer_offset=0)
Definition decoder.h:387
void V8_NOINLINE const char constexpr int kMaxErrorMsg
Definition decoder.h:448
IntType consume_little_endian(const char *name)
Definition decoder.h:474
void set_end(const uint8_t *end)
Definition decoder.h:427
uint16_t consume_u16(const char *name="uint16_t")
Definition decoder.h:237
void V8_NOINLINE V8_PRESERVE_MOST errorf(uint32_t offset, const char *format, Args... args)
Definition decoder.h:353
base::EmbeddedVector< char, kMaxErrorMsg > buffer
Definition decoder.h:449
bool checkAvailable(uint32_t size)
Definition decoder.h:321
bool lookahead(int offset, uint8_t expected)
Definition decoder.h:430
uint32_t GetBufferRelativeOffset(uint32_t offset) const
Definition decoder.h:422
uint8_t read_u8(const uint8_t *pc, Name< ValidationTag > msg="expected 1 byte")
Definition decoder.h:132
uint64_t consume_u64v(const char *name, ITracer *tracer)
Definition decoder.h:277
uint32_t consume_u32v(const char *name, ITracer *tracer)
Definition decoder.h:257
void consume_bytes(uint32_t size, const char *name, ITracer *tracer)
Definition decoder.h:306
virtual ~Decoder()=default
void V8_NOINLINE V8_PRESERVE_MOST error(uint32_t offset, const char *msg)
Definition decoder.h:337
std::pair< uint32_t, uint32_t > read_u32v(const uint8_t *pc, Name< ValidationTag > name="LEB32")
Definition decoder.h:161
void consume_bytes(uint32_t size, const char *name="skip")
Definition decoder.h:297
uint32_t pc_offset() const
Definition decoder.h:418
uint32_t consume_u32v(const char *name="var_uint32")
Definition decoder.h:251
Decoder(const base::Vector< const uint8_t > bytes, uint32_t buffer_offset=0)
Definition decoder.h:117
std::pair< int32_t, uint32_t > read_i32v(const uint8_t *pc, Name< ValidationTag > name="signed LEB32")
Definition decoder.h:169
uint32_t V8_INLINE pc_offset(const uint8_t *pc) const
Definition decoder.h:413
void V8_NOINLINE V8_PRESERVE_MOST error(const uint8_t *pc, const char *msg)
Definition decoder.h:334
uint8_t consume_u8(const char *name="uint8_t")
Definition decoder.h:225
const uint8_t * end() const
Definition decoder.h:426
std::pair< WasmOpcode, uint32_t > read_prefixed_opcode(const uint8_t *pc, Name< ValidationTag > name="prefixed opcode")
Definition decoder.h:202
uint32_t V8_INLINE position() const
Definition decoder.h:409
void traceByteRange(const uint8_t *start, const uint8_t *end)
Definition decoder.h:365
void V8_NOINLINE V8_PRESERVE_MOST error(const char *msg)
Definition decoder.h:331
V8_NOINLINE V8_PRESERVE_MOST std::pair< IntType, uint32_t > read_leb_slowpath(const uint8_t *pc, Name< ValidationTag > name)
Definition decoder.h:522
static constexpr struct v8::internal::wasm::Decoder::NoValidationTag kNoValidation
const uint8_t * pc_
Definition decoder.h:437
virtual void onFirstError()
Definition decoder.h:362
static constexpr struct v8::internal::wasm::Decoder::FullValidationTag kFullValidation
uint32_t buffer_offset() const
Definition decoder.h:419
const uint8_t * end_
Definition decoder.h:438
int64_t consume_i64v(const char *name="var_int64")
Definition decoder.h:289
virtual void StringOffset(uint32_t offset)=0
virtual void InitializerExpression(const uint8_t *start, const uint8_t *end, ValueType expected_type)=0
virtual void Description(HeapType type)=0
virtual void NextLineIfNonEmpty()=0
static constexpr ITracer * NoTrace
Definition decoder.h:45
virtual void RecGroupOffset(uint32_t offset, uint32_t group_size)=0
virtual void GlobalOffset(uint32_t offset)=0
virtual ~ITracer()=default
virtual void TypeOffset(uint32_t offset)=0
virtual void Description(uint32_t number)=0
virtual void ImportOffset(uint32_t offset)=0
virtual void Bytes(const uint8_t *start, uint32_t count)=0
virtual void Description(uint64_t number)=0
virtual void Description(const char *desc, size_t length)=0
virtual void FunctionBody(const WasmFunction *func, const uint8_t *start)=0
virtual void ImportsDone(const WasmModule *module)=0
virtual void ElementOffset(uint32_t offset)=0
virtual void Description(const FunctionSig *sig)=0
virtual void Description(const char *desc)=0
virtual void TableOffset(uint32_t offset)=0
virtual void MemoryOffset(uint32_t offset)=0
virtual void FunctionName(uint32_t func_index)=0
virtual void DataOffset(uint32_t offset)=0
virtual void TagOffset(uint32_t offset)=0
virtual void StartOffset(uint32_t offset)=0
virtual void NextLine()=0
virtual void NameSection(const uint8_t *start, const uint8_t *end, uint32_t offset)=0
virtual void NextLineIfFull()=0
virtual void Description(ValueType type)=0
const std::string & message() const &
Definition wasm-result.h:54
int start
int end
#define TRACE_IF(cond,...)
Definition decoder.h:33
int32_t offset
ZoneVector< RpoNumber > & result
#define TRACE(...)
static V ReadLittleEndianValue(Address p)
Definition memory.h:52
int VSNPrintF(Vector< char > str, const char *format, va_list args)
Definition strings.cc:16
Result< std::nullptr_t > VoidResult
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
Definition flags.cc:2086
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
constexpr uint32_t kMaxUInt32
Definition globals.h:387
bool is_signed(Condition cond)
Definition c-api.cc:87
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
V8_INLINE A implicit_cast(A x)
Definition macros.h:306
constexpr NoName(const char *)
Definition decoder.h:100
#define V8_INLINE
Definition v8config.h:500
#define V8_ASSUME
Definition v8config.h:533
#define V8_LIKELY(condition)
Definition v8config.h:661
#define V8_UNLIKELY(condition)
Definition v8config.h:660
#define V8_NOINLINE
Definition v8config.h:586
#define V8_PRESERVE_MOST
Definition v8config.h:598