Commit ebcff9e1 authored by Ng Zhi An's avatar Ng Zhi An Committed by Commit Bot

[wasm] Read prefixed opcodes as u32v

Prefixed opcodes have a 1 byte prefix, followed by LEB-encoded u32. This
changes all prefixed opcodes (gc, numeric, atomic), to that. (Simd was
already so.)

We can clean up read_prefix_opcode to return the total number of bytes,
1 byte prefix + leb encoded, that will be in a future patch.

Bug: v8:10810,v8:10994
Change-Id: Ia74604acc059c1336b87e9f477598732de219ca9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2465057Reviewed-by: 's avatarManos Koukoutos <manoskouk@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70544}
parent 4dc2246b
......@@ -130,36 +130,32 @@ class Decoder {
return read_leb<int64_t, validate, kNoTrace, 33>(pc, length, name);
}
// Convenient overload for callers who don't care about length.
template <ValidateFlag validate>
WasmOpcode read_prefixed_opcode(const byte* pc) {
uint32_t len;
return read_prefixed_opcode<validate>(pc, &len);
}
// Reads a prefixed-opcode, possibly with variable-length index.
// The length param is set to the number of bytes this index is encoded with.
// For most cases (non variable-length), it will be 1.
template <ValidateFlag validate>
WasmOpcode read_prefixed_opcode(const byte* pc, uint32_t* length = nullptr,
WasmOpcode read_prefixed_opcode(const byte* pc, uint32_t* length,
const char* name = "prefixed opcode") {
uint32_t unused_length;
if (length == nullptr) {
length = &unused_length;
}
uint32_t index;
if (*pc == WasmOpcode::kSimdPrefix) {
// SIMD opcodes can be multiple bytes (when LEB128 encoded).
index = read_u32v<validate>(pc + 1, length, "prefixed opcode index");
// Only support SIMD opcodes that go up to 0xFF (when decoded). Anything
// bigger will need 1 more byte, and the '<< 8' below will be wrong.
if (validate && V8_UNLIKELY(index > 0xff)) {
errorf(pc, "Invalid SIMD opcode %d", index);
}
} else {
if (!validate || validate_size(pc, 2, "expected 2 bytes")) {
DCHECK(validate_size(pc, 2, "expected 2 bytes"));
index = *(pc + 1);
*length = 1;
} else {
// If size validation fails.
index = 0;
*length = 0;
}
// Prefixed opcodes all use LEB128 encoding.
index = read_u32v<validate>(pc + 1, length, "prefixed opcode index");
// Only support opcodes that go up to 0xFF (when decoded). Anything
// bigger will need 1 more byte, and the '<< 8' below will be wrong.
if (validate && V8_UNLIKELY(index > 0xff)) {
errorf(pc, "Invalid prefixed opcode %d", index);
// If size validation fails.
index = 0;
*length = 0;
}
return static_cast<WasmOpcode>((*pc) << 8 | index);
}
......
This diff is collapsed.
......@@ -4586,6 +4586,21 @@ TEST_F(WasmOpcodeLengthTest, IllegalRefIndices) {
ExpectFailure(kExprBlock, kOptRefCode, U32V_4(0x01000000));
}
TEST_F(WasmOpcodeLengthTest, PrefixedOpcodesLEB) {
// kExprI32New with a 4-byte LEB-encoded opcode.
ExpectLength(5, 0xfb, 0xa0, 0x80, 0x80, 0x00);
// kExprI8x16Splat with a 3-byte LEB-encoded opcode.
ExpectLength(4, 0xfd, 0x8f, 0x80, 0x00);
// kExprI32SConvertSatF32 with a 4-byte LEB-encoded opcode.
ExpectLength(5, 0xfc, 0x80, 0x80, 0x80, 0x00);
// kExprAtomicNotify with a 2-byte LEB-encoded opcode, and 2 i32 imm for
// memarg.
ExpectLength(5, 0xfe, 0x80, 0x00, 0x00, 0x00);
}
using TypesOfLocals = ZoneVector<ValueType>;
class LocalDeclDecoderTest : public TestWithZone {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment