Skip to content

Commit

Permalink
AK/LEB128: Speed up reading unsigned LEB128 values
Browse files Browse the repository at this point in the history
Unroll the first byte as a fast path, and remove a branch. This speeds
up the instantiation of spidermonkey by 10ms.
  • Loading branch information
dzfrias authored and awesomekling committed Jul 27, 2024
1 parent fc57f51 commit a6ebd10
Showing 1 changed file with 15 additions and 19 deletions.
34 changes: 15 additions & 19 deletions AK/LEB128.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,30 +27,26 @@ class [[gnu::packed]] LEB128 {
static ErrorOr<LEB128<ValueType>> read_from_stream(Stream& stream)
requires(Unsigned<ValueType>)
{
ValueType result {};
size_t num_bytes = 0;
while (true) {
if (stream.is_eof())
return Error::from_string_literal("Stream reached end-of-file while reading LEB128 value");
// First byte is unrolled for speed
auto byte = TRY(stream.read_value<u8>());
if ((byte & 0x80) == 0)
return LEB128<ValueType> { byte };

ValueType result = byte & 0x7F;
size_t num_bytes = 1;
while (true) {
auto byte = TRY(stream.read_value<u8>());

ValueType masked_byte = byte & ~(1 << 7);
bool const shift_too_large_for_result = num_bytes * 7 > sizeof(ValueType) * 8;
if (shift_too_large_for_result)
return Error::from_string_literal("Read value contains more bits than fit the chosen ValueType");

bool const shift_too_large_for_byte = ((masked_byte << (num_bytes * 7)) >> (num_bytes * 7)) != masked_byte;
if (shift_too_large_for_byte)
ValueType masked = byte & 0x7F;
result |= masked << (num_bytes * 7);
if (num_bytes * 7 >= sizeof(ValueType) * 8 - 7 && (byte >> (sizeof(ValueType) * 8 - (num_bytes * 7))) != 0) {
if ((byte & 0x80) != 0)
return Error::from_string_literal("Read value contains more bits than fit the chosen ValueType");
return Error::from_string_literal("Read byte is too large to fit the chosen ValueType");

result = (result) | (masked_byte << (num_bytes * 7));
if (!(byte & (1 << 7)))
break;
}
++num_bytes;
if ((byte & 0x80) == 0)
return LEB128<ValueType> { result };
}

return LEB128<ValueType> { result };
}

static ErrorOr<LEB128<ValueType>> read_from_stream(Stream& stream)
Expand Down

0 comments on commit a6ebd10

Please sign in to comment.