LibJS: Cache typed array data pointers for indexed access

Cache raw data pointers on fixed-length typed array views so asm
GetByValue and PutByValue can use them directly for indexed
element access.

Replace the asm typed-array hot-path
ArrayBuffer/DataBlock/ByteBuffer walk with one cached_data_ptr load.
Remove six unconditional loads, four branches, and the byte_offset
add before the element access, trading them for one
cached_data_ptr null check.

Keep direct C++ typed-array access on IsValidIntegerIndex-based
checks, invalidate cached pointers eagerly when a backing
ArrayBuffer is detached, and add regression coverage for shrink,
regrow, and detach on number and BigInt typed arrays.
This commit is contained in:
Andreas Kling
2026-03-18 09:27:37 -05:00
committed by Andreas Kling
parent cf050288fa
commit 9299d430c8
Notes: github-actions[bot] 2026-03-18 19:02:40 +00:00
7 changed files with 202 additions and 114 deletions

View File

@@ -1011,12 +1011,7 @@ i64 asm_try_get_by_value_typed_array(Interpreter* interp, u32 pc)
auto& typed_array = static_cast<TypedArrayBase&>(object);
auto index = static_cast<u32>(property.as_i32());
// Check not detached
auto* buffer = typed_array.viewed_array_buffer();
if (buffer->is_detached()) [[unlikely]]
return 1;
// Fast path: fixed-length typed array
// Fast path: fixed-length typed array with cached data pointer
auto const& array_length = typed_array.array_length();
if (array_length.is_auto()) [[unlikely]]
return 1;
@@ -1027,8 +1022,13 @@ i64 asm_try_get_by_value_typed_array(Interpreter* interp, u32 pc)
return 0;
}
auto byte_offset = typed_array.byte_offset();
auto const* data = buffer->buffer().data() + byte_offset;
if (!is_valid_integer_index(typed_array, CanonicalIndex { CanonicalIndex::Type::Index, index })) [[unlikely]] {
interp->set(insn.dst(), js_undefined());
return 0;
}
auto* buffer = typed_array.viewed_array_buffer();
auto const* data = buffer->buffer().data() + typed_array.byte_offset();
Value result;
switch (typed_array.kind()) {
@@ -1087,10 +1087,6 @@ i64 asm_try_put_by_value_typed_array(Interpreter* interp, u32 pc)
auto& typed_array = static_cast<TypedArrayBase&>(object);
auto index = static_cast<u32>(property.as_i32());
auto* buffer = typed_array.viewed_array_buffer();
if (buffer->is_detached()) [[unlikely]]
return 1;
auto const& array_length = typed_array.array_length();
if (array_length.is_auto()) [[unlikely]]
return 1;
@@ -1098,8 +1094,11 @@ i64 asm_try_put_by_value_typed_array(Interpreter* interp, u32 pc)
if (index >= array_length.length()) [[unlikely]]
return 0;
auto byte_offset = typed_array.byte_offset();
auto* data = buffer->buffer().data() + byte_offset;
if (!is_valid_integer_index(typed_array, CanonicalIndex { CanonicalIndex::Type::Index, index })) [[unlikely]]
return 0;
auto* buffer = typed_array.viewed_array_buffer();
auto* data = buffer->buffer().data() + typed_array.byte_offset();
auto value = interp->get(insn.src());
if (value.is_int32()) {