mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-22 04:25:13 +00:00
LibJS: Make class-specific members of ESFO lazily allocated
We don't need the [[Fields]] and [[PrivateMethods]] slots for most ESFO instances, so let's reduce their impact on class size! This shrinks ESFO from 200 bytes to 160 bytes, allowing more allocations before we have to collect garbage.
This commit is contained in:
parent
3ceea6c903
commit
5edf88f9c2
3 changed files with 40 additions and 20 deletions
|
@ -649,21 +649,23 @@ void ECMAScriptFunctionObject::visit_edges(Visitor& visitor)
|
|||
|
||||
visitor.visit(m_bytecode_executable);
|
||||
|
||||
for (auto& field : m_fields) {
|
||||
field.initializer.visit(
|
||||
[&visitor](GC::Ref<ECMAScriptFunctionObject>& initializer) {
|
||||
visitor.visit(initializer);
|
||||
},
|
||||
[&visitor](Value initializer) {
|
||||
visitor.visit(initializer);
|
||||
},
|
||||
[](Empty) {});
|
||||
if (auto* property_key_ptr = field.name.get_pointer<PropertyKey>(); property_key_ptr && property_key_ptr->is_symbol())
|
||||
visitor.visit(property_key_ptr->as_symbol());
|
||||
}
|
||||
if (m_class_data) {
|
||||
for (auto& field : m_class_data->fields) {
|
||||
field.initializer.visit(
|
||||
[&visitor](GC::Ref<ECMAScriptFunctionObject>& initializer) {
|
||||
visitor.visit(initializer);
|
||||
},
|
||||
[&visitor](Value initializer) {
|
||||
visitor.visit(initializer);
|
||||
},
|
||||
[](Empty) {});
|
||||
if (auto* property_key_ptr = field.name.get_pointer<PropertyKey>(); property_key_ptr && property_key_ptr->is_symbol())
|
||||
visitor.visit(property_key_ptr->as_symbol());
|
||||
}
|
||||
|
||||
for (auto& private_element : m_private_methods)
|
||||
visitor.visit(private_element.value);
|
||||
for (auto& private_element : m_class_data->private_methods)
|
||||
visitor.visit(private_element.value);
|
||||
}
|
||||
|
||||
m_script_or_module.visit(
|
||||
[](Empty) {},
|
||||
|
@ -960,4 +962,12 @@ void ECMAScriptFunctionObject::set_name(FlyString const& name)
|
|||
m_name_string = PrimitiveString::create(vm, name);
|
||||
MUST(define_property_or_throw(vm.names.name, { .value = m_name_string, .writable = false, .enumerable = false, .configurable = true }));
|
||||
}
|
||||
|
||||
ECMAScriptFunctionObject::ClassData& ECMAScriptFunctionObject::ensure_class_data() const
|
||||
{
|
||||
if (!m_class_data)
|
||||
m_class_data = make<ClassData>();
|
||||
return *m_class_data;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -152,11 +152,13 @@ public:
|
|||
[[nodiscard]] ByteString const& source_text() const { return shared_data().m_source_text; }
|
||||
void set_source_text(ByteString source_text) { const_cast<SharedFunctionInstanceData&>(shared_data()).m_source_text = move(source_text); }
|
||||
|
||||
Vector<ClassFieldDefinition> const& fields() const { return m_fields; }
|
||||
void add_field(ClassFieldDefinition field) { m_fields.append(move(field)); }
|
||||
Vector<ClassFieldDefinition> const& fields() const { return ensure_class_data().fields; }
|
||||
void add_field(ClassFieldDefinition field) { ensure_class_data().fields.append(move(field)); }
|
||||
|
||||
Vector<PrivateElement> const& private_methods() const { return m_private_methods; }
|
||||
void add_private_method(PrivateElement method) { m_private_methods.append(move(method)); }
|
||||
Vector<PrivateElement> const& private_methods() const { return ensure_class_data().private_methods; }
|
||||
void add_private_method(PrivateElement method) { ensure_class_data().private_methods.append(move(method)); }
|
||||
|
||||
[[nodiscard]] bool has_class_data() const { return m_class_data; }
|
||||
|
||||
// This is for IsSimpleParameterList (static semantics)
|
||||
bool has_simple_parameter_list() const { return shared_data().m_has_simple_parameter_list; }
|
||||
|
@ -211,8 +213,12 @@ private:
|
|||
GC::Ptr<Realm> m_realm; // [[Realm]]
|
||||
ScriptOrModule m_script_or_module; // [[ScriptOrModule]]
|
||||
GC::Ptr<Object> m_home_object; // [[HomeObject]]
|
||||
Vector<ClassFieldDefinition> m_fields; // [[Fields]]
|
||||
Vector<PrivateElement> m_private_methods; // [[PrivateMethods]]
|
||||
struct ClassData {
|
||||
Vector<ClassFieldDefinition> fields; // [[Fields]]
|
||||
Vector<PrivateElement> private_methods; // [[PrivateMethods]]
|
||||
};
|
||||
ClassData& ensure_class_data() const;
|
||||
mutable OwnPtr<ClassData> m_class_data;
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
|
@ -699,6 +699,10 @@ ThrowCompletionOr<void> Object::define_field(ClassFieldDefinition const& field)
|
|||
// 7.3.34 InitializeInstanceElements ( O, constructor ), https://tc39.es/ecma262/#sec-initializeinstanceelements
|
||||
ThrowCompletionOr<void> Object::initialize_instance_elements(ECMAScriptFunctionObject& constructor)
|
||||
{
|
||||
// AD-HOC: Avoid lazy instantiation of ECMAScriptFunctionObject::ClassData.
|
||||
if (!constructor.has_class_data())
|
||||
return {};
|
||||
|
||||
// 1. Let methods be the value of constructor.[[PrivateMethods]].
|
||||
// 2. For each PrivateElement method of methods, do
|
||||
for (auto const& method : constructor.private_methods()) {
|
||||
|
|
Loading…
Add table
Reference in a new issue