LibJS: Add fast path internal_has_property() for Array

If array has packed index property storage without holes, we could check
if indexed property is present simple by checking if it's less than
array's length.

Makes the following program go 1.1x faster:
```js
function f() {
    let array = [];
    for (let i = 0; i < 3_000; i++) {
        array.push(i);
    }

    for (let i = 0; i < 10_000; i++) {
        array.map(x => x * 2);
    }
}

f();
```
This commit is contained in:
Aliaksandr Kalenik 2025-06-03 19:09:33 +02:00 committed by Alexander Kalenik
commit 93cd17db74
Notes: github-actions[bot] 2025-06-03 21:19:39 +00:00
2 changed files with 14 additions and 0 deletions

View file

@ -393,6 +393,19 @@ ThrowCompletionOr<bool> Array::internal_define_own_property(PropertyKey const& p
return Object::internal_define_own_property(property_key, property_descriptor, precomputed_get_own_property);
}
// NON-STANDARD: Fast path to quickly check if an indexed property exists in array without holes
ThrowCompletionOr<bool> Array::internal_has_property(PropertyKey const& property_key) const
{
auto const* storage = indexed_properties().storage();
if (property_key.is_number() && !m_is_proxy_target && storage && storage->is_simple_storage()) {
auto const& simple_storage = static_cast<SimpleIndexedPropertyStorage const&>(*storage);
if (!simple_storage.has_empty_elements() && property_key.as_number() < simple_storage.array_like_size()) {
return true;
}
}
return Object::internal_has_property(property_key);
}
// NON-STANDARD: Used to reject deletes to ephemeral (non-configurable) length property
ThrowCompletionOr<bool> Array::internal_delete(PropertyKey const& property_key)
{