mirror of
https://github.com/RGBCube/serenity
synced 2025-07-10 04:17:34 +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:
parent
4966c083df
commit
4699c81fc1
23 changed files with 226 additions and 144 deletions
|
@ -3059,8 +3059,7 @@ void Compiler::compile_super_call_with_argument_array(Bytecode::Op::SuperCallWit
|
|||
|
||||
static Value cxx_get_iterator(VM& vm, Value value, IteratorHint hint)
|
||||
{
|
||||
auto iterator = TRY_OR_SET_EXCEPTION(get_iterator(vm, value, hint));
|
||||
return Bytecode::iterator_to_object(vm, iterator);
|
||||
return TRY_OR_SET_EXCEPTION(get_iterator(vm, value, hint));
|
||||
}
|
||||
|
||||
void Compiler::compile_get_iterator(Bytecode::Op::GetIterator const& op)
|
||||
|
@ -3074,10 +3073,33 @@ void Compiler::compile_get_iterator(Bytecode::Op::GetIterator const& op)
|
|||
check_exception();
|
||||
}
|
||||
|
||||
static Value cxx_get_object_from_iterator_record(VM&, Value value)
|
||||
{
|
||||
return verify_cast<IteratorRecord>(value.as_object()).iterator;
|
||||
}
|
||||
|
||||
void Compiler::compile_get_object_from_iterator_record(Bytecode::Op::GetObjectFromIteratorRecord const& op)
|
||||
{
|
||||
load_vm_register(ARG1, op.iterator_record());
|
||||
native_call((void*)cxx_get_object_from_iterator_record);
|
||||
store_vm_register(op.object(), RET);
|
||||
}
|
||||
|
||||
static Value cxx_next_method_from_iterator_record(VM&, Value value)
|
||||
{
|
||||
return verify_cast<IteratorRecord>(value.as_object()).next_method;
|
||||
}
|
||||
|
||||
void Compiler::compile_get_next_method_from_iterator_record(Bytecode::Op::GetNextMethodFromIteratorRecord const& op)
|
||||
{
|
||||
load_vm_register(ARG1, op.iterator_record());
|
||||
native_call((void*)cxx_next_method_from_iterator_record);
|
||||
store_vm_register(op.next_method(), RET);
|
||||
}
|
||||
|
||||
static Value cxx_iterator_next(VM& vm, Value iterator)
|
||||
{
|
||||
auto iterator_object = TRY_OR_SET_EXCEPTION(iterator.to_object(vm));
|
||||
auto iterator_record = Bytecode::object_to_iterator(vm, iterator_object);
|
||||
auto& iterator_record = verify_cast<IteratorRecord>(iterator.as_object());
|
||||
return TRY_OR_SET_EXCEPTION(iterator_next(vm, iterator_record));
|
||||
}
|
||||
|
||||
|
@ -3147,8 +3169,7 @@ void Compiler::compile_iterator_result_value(Bytecode::Op::IteratorResultValue c
|
|||
|
||||
static Value cxx_iterator_close(VM& vm, Value iterator, Completion::Type completion_type, Optional<Value> const& completion_value)
|
||||
{
|
||||
auto iterator_object = TRY_OR_SET_EXCEPTION(iterator.to_object(vm));
|
||||
auto iterator_record = Bytecode::object_to_iterator(vm, iterator_object);
|
||||
auto& iterator_record = verify_cast<IteratorRecord>(iterator.as_object());
|
||||
|
||||
// FIXME: Return the value of the resulting completion. (Note that m_completion_value can be empty!)
|
||||
TRY_OR_SET_EXCEPTION(iterator_close(vm, iterator_record, Completion { completion_type, completion_value, {} }));
|
||||
|
@ -3565,8 +3586,7 @@ void Compiler::compile_copy_object_excluding_properties(Bytecode::Op::CopyObject
|
|||
|
||||
static Value cxx_async_iterator_close(VM& vm, Value iterator, Completion::Type completion_type, Optional<Value> const& completion_value)
|
||||
{
|
||||
auto iterator_object = TRY_OR_SET_EXCEPTION(iterator.to_object(vm));
|
||||
auto iterator_record = Bytecode::object_to_iterator(vm, iterator_object);
|
||||
auto& iterator_record = verify_cast<IteratorRecord>(iterator.as_object());
|
||||
|
||||
// FIXME: Return the value of the resulting completion. (Note that completion_value can be empty!)
|
||||
TRY_OR_SET_EXCEPTION(async_iterator_close(vm, iterator_record, Completion { completion_type, completion_value, {} }));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue