From 021a141b53056e6805c3c7527cd97b120a7a872d Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 5 Oct 2023 09:07:43 +0200 Subject: [PATCH] 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) --- .../Libraries/LibJS/Bytecode/Interpreter.cpp | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index 4c875fe5fc..a8d0948969 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -1580,8 +1580,27 @@ ThrowCompletionOr 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(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 {};