LibJS: Make array-like Put access on ordinary objects much faster

This patch adds a fast path to the PutByValue bytecode op that bypasses
a ton of things *if* a set of assumptions hold:

- The property key must be a non-negative Int32
- The base object must not interfere with indexed property access
- The base object must have simple indexed property storage
- The property key must already be present as an own property
- The existing value must not have any accessors defined

If this holds (which it should in many common cases), we can skip all
kinds of checks and poke directly at the property storage, saving time.

16% speed-up on the entire Kraken benchmark :^)
(including: 88% speed-up on Kraken/imaging-desaturate.js)
(including: 55% speed-up on Kraken/audio-fft.js)
(including: 54% speed-up on Kraken/audio-beat-detection.js)
This commit is contained in:
Andreas Kling 2023-10-05 09:07:43 +02:00
parent 27a83f7e5e
commit 021a141b53

View file

@ -1580,8 +1580,27 @@ ThrowCompletionOr<void> PutByValue::execute_impl(Bytecode::Interpreter& interpre
auto value = interpreter.accumulator();
auto base = interpreter.reg(m_base);
auto property_key_value = interpreter.reg(m_property);
auto property_key = m_kind != PropertyKind::Spread ? TRY(interpreter.reg(m_property).to_property_key(vm)) : PropertyKey {};
// OPTIMIZATION: Fast path for simple Int32 indexes in array-like objects.
if (base.is_object() && property_key_value.is_int32() && property_key_value.as_i32() >= 0) {
auto& object = base.as_object();
auto* storage = object.indexed_properties().storage();
auto index = static_cast<u32>(property_key_value.as_i32());
if (storage
&& storage->is_simple_storage()
&& !object.may_interfere_with_indexed_property_access()
&& storage->has_index(index)) {
auto existing_value = storage->get(index)->value;
if (!existing_value.is_accessor()) {
storage->put(index, value);
interpreter.accumulator() = value;
return {};
}
}
}
auto property_key = m_kind != PropertyKind::Spread ? TRY(property_key_value.to_property_key(vm)) : PropertyKey {};
TRY(put_by_property_key(vm, base, base, value, property_key, m_kind));
interpreter.accumulator() = value;
return {};