mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-26 01:35:08 +02:00
LibJS: Don't make extra copies of every JS function's source code
Instead, let functions have a view into the AST's SourceCode object's underlying string data. The source string is kept alive by the AST, so it's fine to have views into it as long as the AST exists. Reduces memory footprint on my x.com home feed by 65 MiB.
This commit is contained in:
committed by
Andreas Kling
parent
9c8322d1b3
commit
63eccc5640
Notes:
github-actions[bot]
2025-12-21 16:07:21 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/63eccc56407 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/7209
@@ -34,23 +34,53 @@ namespace JS {
|
||||
|
||||
GC_DEFINE_ALLOCATOR(ECMAScriptFunctionObject);
|
||||
|
||||
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, Utf16FlyString name, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, Vector<LocalVariable> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
||||
static GC::Ref<Object> prototype_for_function_kind(Realm& realm, FunctionKind kind)
|
||||
{
|
||||
Object* prototype = nullptr;
|
||||
switch (kind) {
|
||||
case FunctionKind::Normal:
|
||||
prototype = realm.intrinsics().function_prototype();
|
||||
break;
|
||||
return realm.intrinsics().function_prototype();
|
||||
case FunctionKind::Generator:
|
||||
prototype = realm.intrinsics().generator_function_prototype();
|
||||
break;
|
||||
return realm.intrinsics().generator_function_prototype();
|
||||
case FunctionKind::Async:
|
||||
prototype = realm.intrinsics().async_function_prototype();
|
||||
break;
|
||||
return realm.intrinsics().async_function_prototype();
|
||||
case FunctionKind::AsyncGenerator:
|
||||
prototype = realm.intrinsics().async_generator_function_prototype();
|
||||
break;
|
||||
return realm.intrinsics().async_generator_function_prototype();
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, Utf16FlyString name, Utf16String source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, Vector<LocalVariable> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
||||
{
|
||||
auto prototype = prototype_for_function_kind(realm, kind);
|
||||
|
||||
auto shared_data = realm.heap().allocate<SharedFunctionInstanceData>(
|
||||
realm.vm(),
|
||||
kind,
|
||||
move(name),
|
||||
function_length,
|
||||
*parameters,
|
||||
ecmascript_code,
|
||||
Utf16View {},
|
||||
is_strict,
|
||||
is_arrow_function,
|
||||
parsing_insights,
|
||||
move(local_variables_names));
|
||||
|
||||
shared_data->m_class_field_initializer_name = move(class_field_initializer_name);
|
||||
|
||||
shared_data->m_source_text_owner = move(source_text);
|
||||
shared_data->m_source_text = shared_data->m_source_text_owner.utf16_view();
|
||||
|
||||
return realm.create<ECMAScriptFunctionObject>(
|
||||
move(shared_data),
|
||||
parent_environment,
|
||||
private_environment,
|
||||
*prototype);
|
||||
}
|
||||
|
||||
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, Utf16FlyString name, Utf16View source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, Vector<LocalVariable> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
||||
{
|
||||
auto prototype = prototype_for_function_kind(realm, kind);
|
||||
|
||||
auto shared_data = realm.heap().allocate<SharedFunctionInstanceData>(
|
||||
realm.vm(),
|
||||
@@ -74,7 +104,7 @@ GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm,
|
||||
*prototype);
|
||||
}
|
||||
|
||||
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, Utf16FlyString name, Object& prototype, ByteString source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, Vector<LocalVariable> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
||||
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm, Utf16FlyString name, Object& prototype, Utf16View source_text, Statement const& ecmascript_code, NonnullRefPtr<FunctionParameters const> parameters, i32 function_length, Vector<LocalVariable> local_variables_names, Environment* parent_environment, PrivateEnvironment* private_environment, FunctionKind kind, bool is_strict, FunctionParsingInsights parsing_insights, bool is_arrow_function, Variant<PropertyKey, PrivateName, Empty> class_field_initializer_name)
|
||||
{
|
||||
auto shared_data = realm.heap().allocate<SharedFunctionInstanceData>(
|
||||
realm.vm(),
|
||||
@@ -96,6 +126,20 @@ GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create(Realm& realm,
|
||||
prototype);
|
||||
}
|
||||
|
||||
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create_from_function_data(
|
||||
GC::Ref<Realm> realm,
|
||||
GC::Ref<SharedFunctionInstanceData> shared_data,
|
||||
GC::Ptr<Environment> parent_environment,
|
||||
GC::Ptr<PrivateEnvironment> private_environment,
|
||||
Object& prototype)
|
||||
{
|
||||
return realm->create<ECMAScriptFunctionObject>(
|
||||
*shared_data,
|
||||
parent_environment,
|
||||
private_environment,
|
||||
prototype);
|
||||
}
|
||||
|
||||
GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create_from_function_node(
|
||||
FunctionNode const& function_node,
|
||||
Utf16FlyString name,
|
||||
@@ -137,7 +181,8 @@ GC::Ref<ECMAScriptFunctionObject> ECMAScriptFunctionObject::create_from_function
|
||||
function_node.set_shared_data(shared_data);
|
||||
}
|
||||
|
||||
return realm->create<ECMAScriptFunctionObject>(
|
||||
return create_from_function_data(
|
||||
realm,
|
||||
*shared_data,
|
||||
parent_environment,
|
||||
private_environment,
|
||||
|
||||
Reference in New Issue
Block a user