1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-15 04:24:59 +00:00

LibJS: Stop converting between Object <-> IteratorRecord all the time

This patch makes IteratorRecord an Object. Although it's not exposed to
author code, this does allow us to store it in a VM register.

Now that we can store it in a VM register, we don't need to convert it
back and forth between IteratorRecord and Object when accessing it from
bytecode.

The big win here is avoiding 3 [[Get]] accesses on every iteration step
of for..of loops. There are also a bunch of smaller efficiencies gained.

20% speed-up on this microbenchmark:

    function go(a) {
        for (const p of a) {
        }
    }
    const a = [];
    a.length = 1_000_000;
    go(a);
This commit is contained in:
Andreas Kling 2023-12-07 10:44:41 +01:00
parent 4966c083df
commit 4699c81fc1
23 changed files with 226 additions and 144 deletions

View file

@ -1225,8 +1225,21 @@ ThrowCompletionOr<void> DeleteByValueWithThis::execute_impl(Bytecode::Interprete
ThrowCompletionOr<void> GetIterator::execute_impl(Bytecode::Interpreter& interpreter) const
{
auto& vm = interpreter.vm();
auto iterator = TRY(get_iterator(vm, interpreter.accumulator(), m_hint));
interpreter.accumulator() = iterator_to_object(vm, iterator);
interpreter.accumulator() = TRY(get_iterator(vm, interpreter.accumulator(), m_hint));
return {};
}
ThrowCompletionOr<void> GetObjectFromIteratorRecord::execute_impl(Bytecode::Interpreter& interpreter) const
{
auto& iterator_record = verify_cast<IteratorRecord>(interpreter.reg(m_iterator_record).as_object());
interpreter.reg(m_object) = iterator_record.iterator;
return {};
}
ThrowCompletionOr<void> GetNextMethodFromIteratorRecord::execute_impl(Bytecode::Interpreter& interpreter) const
{
auto& iterator_record = verify_cast<IteratorRecord>(interpreter.reg(m_iterator_record).as_object());
interpreter.reg(m_next_method) = iterator_record.next_method;
return {};
}
@ -1248,8 +1261,7 @@ ThrowCompletionOr<void> GetObjectPropertyIterator::execute_impl(Bytecode::Interp
ThrowCompletionOr<void> IteratorClose::execute_impl(Bytecode::Interpreter& interpreter) const
{
auto& vm = interpreter.vm();
auto iterator_object = TRY(interpreter.accumulator().to_object(vm));
auto iterator = object_to_iterator(vm, iterator_object);
auto& iterator = verify_cast<IteratorRecord>(interpreter.accumulator().as_object());
// FIXME: Return the value of the resulting completion. (Note that m_completion_value can be empty!)
TRY(iterator_close(vm, iterator, Completion { m_completion_type, m_completion_value, {} }));
@ -1259,8 +1271,7 @@ ThrowCompletionOr<void> IteratorClose::execute_impl(Bytecode::Interpreter& inter
ThrowCompletionOr<void> AsyncIteratorClose::execute_impl(Bytecode::Interpreter& interpreter) const
{
auto& vm = interpreter.vm();
auto iterator_object = TRY(interpreter.accumulator().to_object(vm));
auto iterator = object_to_iterator(vm, iterator_object);
auto& iterator = verify_cast<IteratorRecord>(interpreter.accumulator().as_object());
// FIXME: Return the value of the resulting completion. (Note that m_completion_value can be empty!)
TRY(async_iterator_close(vm, iterator, Completion { m_completion_type, m_completion_value, {} }));
@ -1270,8 +1281,7 @@ ThrowCompletionOr<void> AsyncIteratorClose::execute_impl(Bytecode::Interpreter&
ThrowCompletionOr<void> IteratorNext::execute_impl(Bytecode::Interpreter& interpreter) const
{
auto& vm = interpreter.vm();
auto iterator_object = TRY(interpreter.accumulator().to_object(vm));
auto iterator = object_to_iterator(vm, iterator_object);
auto& iterator = verify_cast<IteratorRecord>(interpreter.accumulator().as_object());
interpreter.accumulator() = TRY(iterator_next(vm, iterator));
return {};
@ -1818,4 +1828,14 @@ DeprecatedString Catch::to_deprecated_string_impl(Bytecode::Executable const&) c
return "Catch"sv;
}
DeprecatedString GetObjectFromIteratorRecord::to_deprecated_string_impl(Bytecode::Executable const&) const
{
return DeprecatedString::formatted("GetObjectFromIteratorRecord object:{} <- iterator_record:{}", m_object, m_iterator_record);
}
DeprecatedString GetNextMethodFromIteratorRecord::to_deprecated_string_impl(Bytecode::Executable const&) const
{
return DeprecatedString::formatted("GetNextMethodFromIteratorRecord next_method:{} <- iterator_record:{}", m_next_method, m_iterator_record);
}
}