diff --git a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp index d4679288e4..1a5f94063c 100644 --- a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp +++ b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp @@ -60,4 +60,30 @@ ThrowCompletionOr get_by_id(Bytecode::Interpreter& interpreter, Identifie return value; } +ThrowCompletionOr get_by_value(Bytecode::Interpreter& interpreter, Value base_value, Value property_key_value) +{ + auto& vm = interpreter.vm(); + auto object = TRY(base_object_for_get(interpreter, base_value)); + + // OPTIMIZATION: Fast path for simple Int32 indexes in array-like objects. + if (property_key_value.is_int32() + && property_key_value.as_i32() >= 0 + && !object->may_interfere_with_indexed_property_access() + && object->indexed_properties().has_index(property_key_value.as_i32())) { + auto value = object->indexed_properties().get(property_key_value.as_i32())->value; + if (!value.is_accessor()) + return value; + } + + auto property_key = TRY(property_key_value.to_property_key(vm)); + + if (base_value.is_string()) { + auto string_value = TRY(base_value.as_string().get(vm, property_key)); + if (string_value.has_value()) + return *string_value; + } + + return TRY(object->internal_get(property_key, base_value)); +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h index 0171770210..baa72f5d41 100644 --- a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h +++ b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h @@ -13,5 +13,6 @@ namespace JS::Bytecode { ThrowCompletionOr> base_object_for_get(Bytecode::Interpreter&, Value base_value); ThrowCompletionOr get_by_id(Bytecode::Interpreter&, IdentifierTableIndex, Value base_value, Value this_value, u32 cache_index); +ThrowCompletionOr get_by_value(Bytecode::Interpreter&, Value base_value, Value property_key_value); } diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index bb94c023ae..28823598c2 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -1483,37 +1483,7 @@ ThrowCompletionOr Await::execute_impl(Bytecode::Interpreter& interpreter) ThrowCompletionOr GetByValue::execute_impl(Bytecode::Interpreter& interpreter) const { - auto& vm = interpreter.vm(); - - // NOTE: Get the property key from the accumulator before side effects have a chance to overwrite it. - auto property_key_value = interpreter.accumulator(); - - auto base_value = interpreter.reg(m_base); - auto object = TRY(base_object_for_get(interpreter, base_value)); - - // OPTIMIZATION: Fast path for simple Int32 indexes in array-like objects. - if (property_key_value.is_int32() - && property_key_value.as_i32() >= 0 - && !object->may_interfere_with_indexed_property_access() - && object->indexed_properties().has_index(property_key_value.as_i32())) { - auto value = object->indexed_properties().get(property_key_value.as_i32())->value; - if (!value.is_accessor()) { - interpreter.accumulator() = value; - return {}; - } - } - - auto property_key = TRY(property_key_value.to_property_key(vm)); - - if (base_value.is_string()) { - auto string_value = TRY(base_value.as_string().get(vm, property_key)); - if (string_value.has_value()) { - interpreter.accumulator() = *string_value; - return {}; - } - } - - interpreter.accumulator() = TRY(object->internal_get(property_key, base_value)); + interpreter.accumulator() = TRY(get_by_value(interpreter, interpreter.reg(m_base), interpreter.accumulator())); return {}; } diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index a8dfff7eff..1e4e38324d 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -727,6 +727,8 @@ public: ThrowCompletionOr execute_impl(Bytecode::Interpreter&) const; DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const; + Register base() const { return m_base; } + private: Register m_base; };