[wasm] Add a fast path for MemoryAccessImmediate

The memory access immediate consists of two LEB-encoded integers. Both
are mostly single-byte values. Hence add a fast path that checks for
that, and avoids the general LEB-decoding logic otherwise.
This saves a few dynamic branches, in particular it is independent of
the {memory64} flag.

R=dlehmann@chromium.org

Bug: v8:13565, v8:13673
Change-Id: Iee981dd451f8acb001aa36f1dd3c8103839d01aa
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4198137
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: Daniel Lehmann <dlehmann@chromium.org>
Cr-Commit-Position: refs/heads/main@{#85538}
This commit is contained in:
Clemens Backes 2023-01-27 17:39:35 +01:00 committed by V8 LUCI CQ
parent ed8cd96a9d
commit 171587e66b

View File

@ -705,12 +705,19 @@ struct MemoryAccessImmediate {
uint32_t length = 0; uint32_t length = 0;
template <typename ValidationTag> template <typename ValidationTag>
MemoryAccessImmediate(Decoder* decoder, const byte* pc, V8_INLINE MemoryAccessImmediate(Decoder* decoder, const byte* pc,
uint32_t max_alignment, bool is_memory64, uint32_t max_alignment, bool is_memory64,
ValidationTag = {}) { ValidationTag = {}) {
uint32_t alignment_length; // Check for the fast path (two single-byte LEBs).
alignment = const bool two_bytes = !ValidationTag::validate || decoder->end() - pc >= 2;
decoder->read_u32v<ValidationTag>(pc, &alignment_length, "alignment"); const bool use_fast_path = two_bytes && !((pc[0] | pc[1]) & 0x80);
if (V8_LIKELY(use_fast_path)) {
alignment = pc[0];
offset = pc[1];
length = 2;
} else {
ConstructSlow<ValidationTag>(decoder, pc, max_alignment, is_memory64);
}
if (!VALIDATE(alignment <= max_alignment)) { if (!VALIDATE(alignment <= max_alignment)) {
DecodeError<ValidationTag>( DecodeError<ValidationTag>(
decoder, pc, decoder, pc,
@ -718,6 +725,17 @@ struct MemoryAccessImmediate {
"actual alignment is %u", "actual alignment is %u",
max_alignment, alignment); max_alignment, alignment);
} }
}
private:
template <typename ValidationTag>
V8_NOINLINE V8_PRESERVE_MOST void ConstructSlow(Decoder* decoder,
const byte* pc,
uint32_t max_alignment,
bool is_memory64) {
uint32_t alignment_length;
alignment =
decoder->read_u32v<ValidationTag>(pc, &alignment_length, "alignment");
uint32_t offset_length; uint32_t offset_length;
offset = is_memory64 ? decoder->read_u64v<ValidationTag>( offset = is_memory64 ? decoder->read_u64v<ValidationTag>(
pc + alignment_length, &offset_length, "offset") pc + alignment_length, &offset_length, "offset")
@ -2933,8 +2951,8 @@ class WasmFullDecoder : public WasmDecoder<ValidationTag, decoding_mode> {
return true; return true;
} }
MemoryAccessImmediate MakeMemoryAccessImmediate(uint32_t pc_offset, V8_INLINE MemoryAccessImmediate
uint32_t max_alignment) { MakeMemoryAccessImmediate(uint32_t pc_offset, uint32_t max_alignment) {
return MemoryAccessImmediate(this, this->pc_ + pc_offset, max_alignment, return MemoryAccessImmediate(this, this->pc_ + pc_offset, max_alignment,
this->module_->is_memory64, validate); this->module_->is_memory64, validate);
} }