diff --git a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp index 960eac6c0a..9051e86130 100644 --- a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp +++ b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp @@ -285,4 +285,28 @@ Value new_function(VM& vm, FunctionExpression const& function_node, Optional put_by_value(VM& vm, Value base, Value property_key_value, Value value, Op::PropertyKind kind) +{ + // 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); + return {}; + } + } + } + + auto property_key = kind != Op::PropertyKind::Spread ? TRY(property_key_value.to_property_key(vm)) : PropertyKey {}; + TRY(put_by_property_key(vm, base, base, value, property_key, kind)); + return {}; +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h index 8a64905840..a78381611b 100644 --- a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h +++ b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h @@ -23,5 +23,6 @@ ThrowCompletionOr throw_if_needed_for_call(Interpreter&, InstructionType c ThrowCompletionOr typeof_variable(VM&, DeprecatedFlyString const&); ThrowCompletionOr set_variable(VM&, DeprecatedFlyString const&, Value, Op::EnvironmentMode, Op::SetVariable::InitializationMode); Value new_function(VM&, FunctionExpression const&, Optional const& lhs_name, Optional const& home_object); +ThrowCompletionOr put_by_value(VM&, Value base, Value property_key_value, Value value, Op::PropertyKind); } diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index 539f7f8e0e..61f385b9dc 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -1357,33 +1357,10 @@ ThrowCompletionOr PutByValue::execute_impl(Bytecode::Interpreter& interpre { auto& vm = interpreter.vm(); - // NOTE: Get the value from the accumulator before side effects have a chance to overwrite it. auto value = interpreter.accumulator(); - - auto base = interpreter.reg(m_base); - auto property_key_value = interpreter.reg(m_property); - - // 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)); + TRY(put_by_value(vm, interpreter.reg(m_base), interpreter.reg(m_property), interpreter.accumulator(), m_kind)); interpreter.accumulator() = value; + return {}; }