mirror of
https://github.com/fergalmoran/ladybird.git
synced 2025-12-26 03:09:08 +00:00
LibJS/Bytecode: Flatten bytecode to a contiguous representation
Instead of keeping bytecode as a set of disjoint basic blocks on the
malloc heap, bytecode is now a contiguous sequence of bytes(!)
The transformation happens at the end of Bytecode::Generator::generate()
and the only really hairy part is rerouting jump labels.
This required solving a few problems:
- The interpreter execution loop had to change quite a bit, since we
were storing BasicBlock pointers all over the place, and control
transfer was done by redirecting the interpreter's current block.
- Exception handlers & finalizers are now stored per-bytecode-range
in a side table in Executable.
- The interpreter now has a plain program counter instead of a stream
iterator. This actually makes error stack generation a bit nicer
since we just have to deal with a number instead of reaching into
the iterator.
This yields a 25% performance improvement on this microbenchmark:
for (let i = 0; i < 1_000_000; ++i) { }
But basically everything gets faster. :^)
This commit is contained in:
@@ -384,7 +384,7 @@ ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argu
|
||||
|
||||
// Non-standard
|
||||
callee_context->arguments.append(arguments_list.data(), arguments_list.size());
|
||||
callee_context->instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
|
||||
callee_context->program_counter = vm.bytecode_interpreter().program_counter();
|
||||
|
||||
// 2. Let calleeContext be PrepareForOrdinaryCall(F, undefined).
|
||||
// NOTE: We throw if the end of the native stack is reached, so unlike in the spec this _does_ need an exception check.
|
||||
@@ -455,7 +455,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> ECMAScriptFunctionObject::internal_const
|
||||
|
||||
// Non-standard
|
||||
callee_context->arguments.append(arguments_list.data(), arguments_list.size());
|
||||
callee_context->instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
|
||||
callee_context->program_counter = vm.bytecode_interpreter().program_counter();
|
||||
|
||||
// 4. Let calleeContext be PrepareForOrdinaryCall(F, newTarget).
|
||||
// NOTE: We throw if the end of the native stack is reached, so unlike in the spec this _does_ need an exception check.
|
||||
@@ -726,7 +726,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
|
||||
for (size_t register_index = 0; register_index < saved_registers.size(); ++register_index)
|
||||
saved_registers[register_index] = {};
|
||||
|
||||
auto result_and_return_register = vm.bytecode_interpreter().run_executable(*m_default_parameter_bytecode_executables[default_parameter_index - 1], nullptr);
|
||||
auto result_and_return_register = vm.bytecode_interpreter().run_executable(*m_default_parameter_bytecode_executables[default_parameter_index - 1], {});
|
||||
|
||||
for (size_t register_index = 0; register_index < saved_registers.size(); ++register_index)
|
||||
running_execution_context.registers[register_index] = saved_registers[register_index];
|
||||
@@ -1124,7 +1124,7 @@ void async_block_start(VM& vm, T const& async_body, PromiseCapability const& pro
|
||||
if (maybe_executable.is_error())
|
||||
result = maybe_executable.release_error();
|
||||
else
|
||||
result = vm.bytecode_interpreter().run_executable(*maybe_executable.value(), nullptr).value;
|
||||
result = vm.bytecode_interpreter().run_executable(*maybe_executable.value(), {}).value;
|
||||
}
|
||||
// b. Else,
|
||||
else {
|
||||
@@ -1251,7 +1251,7 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
|
||||
}
|
||||
}
|
||||
|
||||
auto result_and_frame = vm.bytecode_interpreter().run_executable(*m_bytecode_executable, nullptr);
|
||||
auto result_and_frame = vm.bytecode_interpreter().run_executable(*m_bytecode_executable, {});
|
||||
|
||||
if (result_and_frame.value.is_error())
|
||||
return result_and_frame.value.release_error();
|
||||
|
||||
Reference in New Issue
Block a user