mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-22 17:24:48 -05:00
LibJS: Cache the shape for normal ECMAScriptFunctionObject prototypes
Instead of creating a unique new prototype shape every time a function object is instantiated, we now keep one cached with the intrinsics. This avoids a whole lot of shape allocations, reducing GC pressure.
This commit is contained in:
parent
795471ce31
commit
749cf2d1b5
Notes:
github-actions[bot]
2024-09-26 18:24:37 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/749cf2d1b54 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1541
3 changed files with 15 additions and 2 deletions
|
@ -354,8 +354,8 @@ void ECMAScriptFunctionObject::initialize(Realm& realm)
|
|||
Object* prototype = nullptr;
|
||||
switch (m_kind) {
|
||||
case FunctionKind::Normal:
|
||||
prototype = Object::create_prototype(realm, realm.intrinsics().object_prototype());
|
||||
MUST(prototype->define_property_or_throw(vm.names.constructor, { .value = this, .writable = true, .enumerable = false, .configurable = true }));
|
||||
prototype = Object::create_with_premade_shape(realm.intrinsics().new_function_object_prototype_shape());
|
||||
prototype->put_direct(realm.intrinsics().new_function_object_prototype_constructor_offset(), this);
|
||||
break;
|
||||
case FunctionKind::Generator:
|
||||
// prototype is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
|
||||
|
|
|
@ -188,6 +188,12 @@ ThrowCompletionOr<void> Intrinsics::initialize_intrinsics(Realm& realm)
|
|||
m_new_object_shape = heap().allocate_without_realm<Shape>(realm);
|
||||
m_new_object_shape->set_prototype_without_transition(m_object_prototype);
|
||||
|
||||
m_new_function_object_prototype_shape = heap().allocate_without_realm<Shape>(realm);
|
||||
m_new_function_object_prototype_shape->set_prototype_shape();
|
||||
m_new_function_object_prototype_shape->set_prototype_without_transition(m_object_prototype);
|
||||
m_new_function_object_prototype_shape->add_property_without_transition(vm.names.constructor, Attribute::Writable | Attribute::Configurable | Attribute::Enumerable);
|
||||
m_new_function_object_prototype_constructor_offset = m_new_function_object_prototype_shape->lookup(vm.names.constructor.to_string_or_symbol()).value().offset;
|
||||
|
||||
// OPTIMIZATION: A lot of runtime algorithms create an "iterator result" object.
|
||||
// We pre-bake a shape for these objects and remember the property offsets.
|
||||
// This allows us to construct them very quickly.
|
||||
|
@ -367,6 +373,7 @@ void Intrinsics::visit_edges(Visitor& visitor)
|
|||
visitor.visit(m_realm);
|
||||
visitor.visit(m_empty_object_shape);
|
||||
visitor.visit(m_new_object_shape);
|
||||
visitor.visit(m_new_function_object_prototype_shape);
|
||||
visitor.visit(m_iterator_result_object_shape);
|
||||
visitor.visit(m_proxy_constructor);
|
||||
visitor.visit(m_async_from_sync_iterator_prototype);
|
||||
|
|
|
@ -22,6 +22,9 @@ public:
|
|||
|
||||
NonnullGCPtr<Shape> new_object_shape() { return *m_new_object_shape; }
|
||||
|
||||
[[nodiscard]] NonnullGCPtr<Shape> new_function_object_prototype_shape() { return *m_new_function_object_prototype_shape; }
|
||||
[[nodiscard]] u32 new_function_object_prototype_constructor_offset() { return m_new_function_object_prototype_constructor_offset; }
|
||||
|
||||
[[nodiscard]] NonnullGCPtr<Shape> iterator_result_object_shape() { return *m_iterator_result_object_shape; }
|
||||
[[nodiscard]] u32 iterator_result_object_value_offset() { return m_iterator_result_object_value_offset; }
|
||||
[[nodiscard]] u32 iterator_result_object_done_offset() { return m_iterator_result_object_done_offset; }
|
||||
|
@ -125,6 +128,9 @@ private:
|
|||
GCPtr<Shape> m_empty_object_shape;
|
||||
GCPtr<Shape> m_new_object_shape;
|
||||
|
||||
GCPtr<Shape> m_new_function_object_prototype_shape;
|
||||
u32 m_new_function_object_prototype_constructor_offset { 0 };
|
||||
|
||||
GCPtr<Shape> m_iterator_result_object_shape;
|
||||
u32 m_iterator_result_object_value_offset { 0 };
|
||||
u32 m_iterator_result_object_done_offset { 0 };
|
||||
|
|
Loading…
Reference in a new issue