Commit 16fb5ccf authored by Clemens Backes's avatar Clemens Backes Committed by V8 LUCI CQ

[wasm] Add comment about WasmOpcode encoding

As a follow-up to https://crrev.com/c/3625835, document how we
internally encode Wasm opcodes in the WasmOpcode enum. In particular,
it's important for the mapping to be bijective.

R=thibaudm@chromium.org
CC=gdeepti@chromium.org

Bug: v8:12284
Change-Id: Ic4bcd70211e83b1eabb45204bdcce3209a4432b3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3647360Reviewed-by: 's avatarThibaud Michaud <thibaudm@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarDeepti Gandluri <gdeepti@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80635}
parent 63f42852
...@@ -598,20 +598,17 @@ constexpr bool WasmOpcodes::IsThrowingOpcode(WasmOpcode opcode) { ...@@ -598,20 +598,17 @@ constexpr bool WasmOpcodes::IsThrowingOpcode(WasmOpcode opcode) {
// static // static
constexpr bool WasmOpcodes::IsRelaxedSimdOpcode(WasmOpcode opcode) { constexpr bool WasmOpcodes::IsRelaxedSimdOpcode(WasmOpcode opcode) {
switch (opcode) { static_assert(kSimdPrefix == 0xfd);
#define CHECK_OPCODE(name, opcode, _) case kExpr##name: #define CHECK_OPCODE(name, opcode, _) \
FOREACH_RELAXED_SIMD_OPCODE(CHECK_OPCODE) static_assert((opcode & 0xfd100) == 0xfd100);
FOREACH_RELAXED_SIMD_OPCODE(CHECK_OPCODE)
#undef CHECK_OPCODE #undef CHECK_OPCODE
return true;
default: return (opcode & 0xfd100) == 0xfd100;
return false;
}
} }
constexpr byte WasmOpcodes::ExtractPrefix(WasmOpcode opcode) { constexpr byte WasmOpcodes::ExtractPrefix(WasmOpcode opcode) {
// If the decoded opcode exceeds two bytes, shift an additional // See comment on {WasmOpcode} for the encoding.
// byte. For decoded opcodes that exceed 3 bytes, this would
// need to be fixed.
return (opcode > 0xffff) ? opcode >> 12 : opcode >> 8; return (opcode > 0xffff) ? opcode >> 12 : opcode >> 8;
} }
......
...@@ -831,6 +831,23 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig, ...@@ -831,6 +831,23 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
V(Simd, 0xfd) \ V(Simd, 0xfd) \
V(Atomic, 0xfe) V(Atomic, 0xfe)
// Prefixed opcodes are encoded as 1 prefix byte, followed by LEB encoded
// opcode bytes. We internally encode them as {WasmOpcode} as follows:
// 1) non-prefixed opcodes use the opcode itself as {WasmOpcode} enum value;
// 2) prefixed opcodes in [0, 0xff] use {(prefix << 8) | opcode};
// 3) prefixed opcodes in [0x100, 0xfff] use {(prefix << 12) | opcode} (this is
// only used for relaxed simd so far).
//
// This encoding is bijective (i.e. a one-to-one mapping in both directions).
// The used opcode ranges are:
// 1) [0, 0xff] -> no prefix, 8 bits opcode
// 2) [0xfb00, 0xfe00] -> prefix shifted by 8 bits, and 8 bits opcode
// 3) [0xfd100, 0xfdfff] -> prefix shifted by 12 bits, and 12 bits opcode
// (only [0xfd100, 0xfd1ff] used so far)
//
// This allows to compute back the prefix and the non-prefixed opcode from each
// WasmOpcode, see {WasmOpcodes::ExtractPrefix} and
// {ExtractPrefixedOpcodeBytes} (for testing).
enum WasmOpcode { enum WasmOpcode {
// Declare expression opcodes. // Declare expression opcodes.
#define DECLARE_NAMED_ENUM(name, opcode, ...) kExpr##name = opcode, #define DECLARE_NAMED_ENUM(name, opcode, ...) kExpr##name = opcode,
...@@ -865,12 +882,8 @@ class V8_EXPORT_PRIVATE WasmOpcodes { ...@@ -865,12 +882,8 @@ class V8_EXPORT_PRIVATE WasmOpcodes {
static constexpr bool IsBreakable(WasmOpcode); static constexpr bool IsBreakable(WasmOpcode);
static constexpr MessageTemplate TrapReasonToMessageId(TrapReason); static constexpr MessageTemplate TrapReasonToMessageId(TrapReason);
// Prefixed opcodes are encoded as 1 prefix byte, followed by LEB encoded
// opcode bytes. With the addition of relaxed SIMD opcodes, the decoded // Extract the prefix byte (or 0x00) from a {WasmOpcode}.
// length of opcode bytes exceeds two bytes. This method, and other mehtods
// that operate on prefixed opcodes, handle upto 3 byte opcodes, when
// opcodes exceed a decoded length of 3 bytes, this code, and elsewhere
// that assumes 3-bytes to be the maximum opcode length should be updated.
static constexpr byte ExtractPrefix(WasmOpcode); static constexpr byte ExtractPrefix(WasmOpcode);
static inline const char* TrapReasonMessage(TrapReason); static inline const char* TrapReasonMessage(TrapReason);
}; };
......
...@@ -304,9 +304,9 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) { ...@@ -304,9 +304,9 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
} }
} }
// This method handles upcodes with decoded length of 3-bytes // See comment on {WasmOpcode} for the encoding.
// update is we exceed that opcode length. (More details in // This method handles opcodes with decoded length up to 3 bytes. Update if we
// wasm-opcodes.h) // exceed that opcode length.
inline uint16_t ExtractPrefixedOpcodeBytes(WasmOpcode opcode) { inline uint16_t ExtractPrefixedOpcodeBytes(WasmOpcode opcode) {
return (opcode > 0xffff) ? opcode & 0x0fff : opcode & 0xff; return (opcode > 0xffff) ? opcode & 0x0fff : opcode & 0xff;
} }
......
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