LibJS/Bytecode: Add dedicated instruction for getting length property

By doing this, we can remove all the special-case checks for `length`
from the generic GetById and GetByIdWithThis code paths, making every
other property lookup a bit faster.

Small progressions on most benchmarks, and some larger progressions:

- 12% on Octane/crypto.js
- 6% on Kraken/ai-astar.js
This commit is contained in:
Andreas Kling 2024-05-20 11:53:28 +02:00
commit 448b7ca87b
Notes: sideshowbarker 2024-07-18 02:47:59 +09:00
5 changed files with 124 additions and 7 deletions

View file

@ -597,6 +597,8 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
HANDLE_INSTRUCTION(GetGlobal);
HANDLE_INSTRUCTION_WITHOUT_EXCEPTION_CHECK(GetImportMeta);
HANDLE_INSTRUCTION(GetIterator);
HANDLE_INSTRUCTION(GetLength);
HANDLE_INSTRUCTION(GetLengthWithThis);
HANDLE_INSTRUCTION(GetMethod);
HANDLE_INSTRUCTION_WITHOUT_EXCEPTION_CHECK(GetNewTarget);
HANDLE_INSTRUCTION(GetNextMethodFromIteratorRecord);
@ -1456,6 +1458,26 @@ ThrowCompletionOr<void> GetByIdWithThis::execute_impl(Bytecode::Interpreter& int
return {};
}
ThrowCompletionOr<void> GetLength::execute_impl(Bytecode::Interpreter& interpreter) const
{
auto base_identifier = interpreter.current_executable().get_identifier(m_base_identifier);
auto base_value = interpreter.get(base());
auto& cache = interpreter.current_executable().property_lookup_caches[m_cache_index];
interpreter.set(dst(), TRY(get_by_id<GetByIdMode::Length>(interpreter.vm(), base_identifier, interpreter.vm().names.length.as_string(), base_value, base_value, cache)));
return {};
}
ThrowCompletionOr<void> GetLengthWithThis::execute_impl(Bytecode::Interpreter& interpreter) const
{
auto base_value = interpreter.get(m_base);
auto this_value = interpreter.get(m_this_value);
auto& cache = interpreter.current_executable().property_lookup_caches[m_cache_index];
interpreter.set(dst(), TRY(get_by_id<GetByIdMode::Length>(interpreter.vm(), {}, interpreter.vm().names.length.as_string(), base_value, this_value, cache)));
return {};
}
ThrowCompletionOr<void> GetPrivateById::execute_impl(Bytecode::Interpreter& interpreter) const
{
auto& vm = interpreter.vm();
@ -2205,6 +2227,21 @@ ByteString GetByIdWithThis::to_byte_string_impl(Bytecode::Executable const& exec
format_operand("this"sv, m_this_value, executable));
}
ByteString GetLength::to_byte_string_impl(Bytecode::Executable const& executable) const
{
return ByteString::formatted("GetLength {}, {}",
format_operand("dst"sv, m_dst, executable),
format_operand("base"sv, m_base, executable));
}
ByteString GetLengthWithThis::to_byte_string_impl(Bytecode::Executable const& executable) const
{
return ByteString::formatted("GetLengthWithThis {}, {}, {}",
format_operand("dst"sv, m_dst, executable),
format_operand("base"sv, m_base, executable),
format_operand("this"sv, m_this_value, executable));
}
ByteString GetPrivateById::to_byte_string_impl(Bytecode::Executable const& executable) const
{
return ByteString::formatted("GetPrivateById {}, {}, {}",