LibJS+LibWeb: Return Vector<PropertyKey> from internal_own_property_keys

By doing that we avoid lots of `PropertyKey` -> `Value` -> `PropertyKey`
transforms, which are quite expensive because of underlying
`FlyString` -> `PrimitiveString` -> `FlyString` conversions.

10% improvement on MicroBench/object-keys.js
This commit is contained in:
Aliaksandr Kalenik 2025-05-14 15:39:48 +03:00 committed by Alexander Kalenik
parent 47569c1714
commit 5ee810f772
Notes: github-actions[bot] 2025-05-15 18:13:23 +00:00
24 changed files with 134 additions and 155 deletions

View file

@ -1863,8 +1863,8 @@ inline ThrowCompletionOr<Value> get_object_property_iterator(Interpreter& interp
seen_objects.set(*object_to_check);
auto keys = TRY(object_to_check->internal_own_property_keys());
properties.ensure_capacity(properties.size() + keys.size());
for (auto& key : keys) {
if (key.is_symbol())
for (auto& property_key : keys) {
if (property_key.is_symbol())
continue;
// NOTE: If there is a non-enumerable property higher up the prototype chain with the same key,
@ -1872,7 +1872,7 @@ inline ThrowCompletionOr<Value> get_object_property_iterator(Interpreter& interp
// This is achieved with the PropertyKeyAndEnumerableFlag struct, which doesn't consider
// the enumerable flag when comparing keys.
PropertyKeyAndEnumerableFlag new_entry {
.key = TRY(PropertyKey::from_value(vm, key)),
.key = property_key,
.enumerable = false,
};
@ -1884,7 +1884,7 @@ inline ThrowCompletionOr<Value> get_object_property_iterator(Interpreter& interp
continue;
new_entry.enumerable = *descriptor->enumerable;
properties.set(move(new_entry), key, AK::HashSetExistingEntryBehavior::Keep);
properties.set(move(new_entry), property_key.to_value(vm), AK::HashSetExistingEntryBehavior::Keep);
}
}