1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-06-22 04:12:06 +00:00

LibJS: Skip lazy intrinsic allocation check for objects without them

Most JS::Objects don't have lazily-allocated intrinsic properties,
so let's avoid doing hash lookups by putting a flag on JS::Object that
tells us whether it's present in s_intrinsics.

Takes CPU time spent in those hash lookups from 1-2.5% to nothing on
various JS heavy pages.
This commit is contained in:
Andreas Kling 2023-06-11 19:46:52 +02:00
parent 5925e6f196
commit 620c495d31
2 changed files with 12 additions and 5 deletions

View file

@ -70,7 +70,8 @@ Object::Object(Shape& shape)
Object::~Object() Object::~Object()
{ {
s_intrinsics.remove(this); if (m_has_intrinsic_accessors)
s_intrinsics.remove(this);
} }
ThrowCompletionOr<void> Object::initialize(Realm&) ThrowCompletionOr<void> Object::initialize(Realm&)
@ -1086,8 +1087,10 @@ Optional<ValueAndAttributes> Object::storage_get(PropertyKey const& property_key
if (!metadata.has_value()) if (!metadata.has_value())
return {}; return {};
if (auto accessor = find_intrinsic_accessor(this, property_key); accessor.has_value()) if (m_has_intrinsic_accessors) {
const_cast<Object&>(*this).m_storage[metadata->offset] = (*accessor)(shape().realm()); if (auto accessor = find_intrinsic_accessor(this, property_key); accessor.has_value())
const_cast<Object&>(*this).m_storage[metadata->offset] = (*accessor)(shape().realm());
}
value = m_storage[metadata->offset]; value = m_storage[metadata->offset];
attributes = metadata->attributes; attributes = metadata->attributes;
@ -1116,7 +1119,7 @@ void Object::storage_set(PropertyKey const& property_key, ValueAndAttributes con
return; return;
} }
if (property_key.is_string()) { if (m_has_intrinsic_accessors && property_key.is_string()) {
if (auto intrinsics = s_intrinsics.find(this); intrinsics != s_intrinsics.end()) if (auto intrinsics = s_intrinsics.find(this); intrinsics != s_intrinsics.end())
intrinsics->value.remove(property_key.as_string()); intrinsics->value.remove(property_key.as_string());
} }
@ -1158,7 +1161,7 @@ void Object::storage_delete(PropertyKey const& property_key)
if (property_key.is_number()) if (property_key.is_number())
return m_indexed_properties.remove(property_key.as_number()); return m_indexed_properties.remove(property_key.as_number());
if (property_key.is_string()) { if (m_has_intrinsic_accessors && property_key.is_string()) {
if (auto intrinsics = s_intrinsics.find(this); intrinsics != s_intrinsics.end()) if (auto intrinsics = s_intrinsics.find(this); intrinsics != s_intrinsics.end())
intrinsics->value.remove(property_key.as_string()); intrinsics->value.remove(property_key.as_string());
} }
@ -1217,6 +1220,7 @@ void Object::define_intrinsic_accessor(PropertyKey const& property_key, Property
storage_set(property_key, { {}, attributes }); storage_set(property_key, { {}, attributes });
m_has_intrinsic_accessors = true;
auto& intrinsics = s_intrinsics.ensure(this); auto& intrinsics = s_intrinsics.ensure(this);
intrinsics.set(property_key.as_string(), move(accessor)); intrinsics.set(property_key.as_string(), move(accessor));
} }

View file

@ -212,6 +212,9 @@ private:
Object* prototype() { return shape().prototype(); } Object* prototype() { return shape().prototype(); }
Object const* prototype() const { return shape().prototype(); } Object const* prototype() const { return shape().prototype(); }
// True if this object has lazily allocated intrinsic properties.
bool m_has_intrinsic_accessors { false };
GCPtr<Shape> m_shape; GCPtr<Shape> m_shape;
Vector<Value> m_storage; Vector<Value> m_storage;
IndexedProperties m_indexed_properties; IndexedProperties m_indexed_properties;