LibJS: Move bytecode executable cache to SharedFunctionInstanceData

This shrinks every Statement and ECMAScriptFunctionObject by one
pointer, and puts the bytecode cache in the only place that actually
makes use of it anyway: functions.
This commit is contained in:
Andreas Kling 2025-10-26 11:23:28 +01:00 committed by Andreas Kling
parent 3a38040c82
commit b712caf855
Notes: github-actions[bot] 2025-10-27 20:15:48 +00:00
3 changed files with 14 additions and 22 deletions

View file

@ -176,12 +176,6 @@ public:
: ASTNode(move(source_range))
{
}
Bytecode::Executable* bytecode_executable() const { return m_bytecode_executable; }
void set_bytecode_executable(Bytecode::Executable* bytecode_executable) { m_bytecode_executable = make_root(bytecode_executable); }
private:
GC::Root<Bytecode::Executable> m_bytecode_executable;
};
// 14.13 Labelled Statements, https://tc39.es/ecma262/#sec-labelled-statements

View file

@ -426,6 +426,7 @@ GC_DEFINE_ALLOCATOR(SharedFunctionInstanceData);
void SharedFunctionInstanceData::visit_edges(Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_executable);
}
SharedFunctionInstanceData::~SharedFunctionInstanceData() = default;
@ -498,17 +499,15 @@ void ECMAScriptFunctionObject::initialize(Realm& realm)
ThrowCompletionOr<void> ECMAScriptFunctionObject::get_stack_frame_size(size_t& registers_and_constants_and_locals_count, size_t& argument_count)
{
if (!m_bytecode_executable) {
if (!ecmascript_code().bytecode_executable()) {
if (is_module_wrapper()) {
const_cast<Statement&>(ecmascript_code()).set_bytecode_executable(TRY(Bytecode::compile(vm(), ecmascript_code(), kind(), name())));
} else {
const_cast<Statement&>(ecmascript_code()).set_bytecode_executable(TRY(Bytecode::compile(vm(), *this)));
}
auto& executable = shared_data().m_executable;
if (!executable) {
if (is_module_wrapper()) {
executable = TRY(Bytecode::compile(vm(), ecmascript_code(), kind(), name()));
} else {
executable = TRY(Bytecode::compile(vm(), *this));
}
m_bytecode_executable = ecmascript_code().bytecode_executable();
}
registers_and_constants_and_locals_count = m_bytecode_executable->number_of_registers + m_bytecode_executable->constants.size() + m_bytecode_executable->local_variable_names.size();
registers_and_constants_and_locals_count = executable->number_of_registers + executable->constants.size() + executable->local_variable_names.size();
argument_count = max(argument_count, formal_parameters().size());
return {};
}
@ -518,7 +517,7 @@ FLATTEN ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Executi
{
auto& vm = this->vm();
ASSERT(m_bytecode_executable);
ASSERT(bytecode_executable());
// 1. Let callerContext be the running execution context.
// NOTE: No-op, kept by the VM in its execution context stack.
@ -563,7 +562,7 @@ FLATTEN ThrowCompletionOr<GC::Ref<Object>> ECMAScriptFunctionObject::internal_co
{
auto& vm = this->vm();
ASSERT(m_bytecode_executable);
ASSERT(bytecode_executable());
// 1. Let callerContext be the running execution context.
// NOTE: No-op, kept by the VM in its execution context stack.
@ -652,7 +651,6 @@ void ECMAScriptFunctionObject::visit_edges(Visitor& visitor)
visitor.visit(m_home_object);
visitor.visit(m_name_string);
visitor.visit(m_shared_data);
visitor.visit(m_bytecode_executable);
if (m_class_data) {
for (auto& field : m_class_data->fields) {
@ -892,7 +890,7 @@ template void async_function_start(VM&, PromiseCapability const&, GC::Function<C
// 15.8.4 Runtime Semantics: EvaluateAsyncFunctionBody, https://tc39.es/ecma262/#sec-runtime-semantics-evaluatefunctionbody
ThrowCompletionOr<Value> ECMAScriptFunctionObject::ordinary_call_evaluate_body(VM& vm)
{
auto result_and_frame = vm.bytecode_interpreter().run_executable(*m_bytecode_executable, {});
auto result_and_frame = vm.bytecode_interpreter().run_executable(*bytecode_executable(), {});
if (result_and_frame.value.is_error()) [[unlikely]] {
return result_and_frame.value.release_error();

View file

@ -54,6 +54,8 @@ public:
FunctionParsingInsights const&,
Vector<LocalVariable> local_variables_names);
mutable GC::Ptr<Bytecode::Executable> m_executable;
RefPtr<FunctionParameters const> m_formal_parameters; // [[FormalParameters]]
RefPtr<Statement const> m_ecmascript_code; // [[ECMAScriptCode]]
@ -142,7 +144,7 @@ public:
void set_is_class_constructor() { const_cast<SharedFunctionInstanceData&>(shared_data()).m_is_class_constructor = true; }
auto& bytecode_executable() const { return m_bytecode_executable; }
auto& bytecode_executable() const { return shared_data().m_executable; }
Environment* environment() { return m_environment; }
virtual Realm* realm() const override { return &shape().realm(); }
@ -214,8 +216,6 @@ private:
GC::Ptr<PrimitiveString> m_name_string;
GC::Ptr<Bytecode::Executable> m_bytecode_executable;
// Internal Slots of ECMAScript Function Objects, https://tc39.es/ecma262/#table-internal-slots-of-ecmascript-function-objects
GC::Ptr<Environment> m_environment; // [[Environment]]
GC::Ptr<PrivateEnvironment> m_private_environment; // [[PrivateEnvironment]]