Selaa lähdekoodia

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.
Andreas Kling 2 vuotta sitten
vanhempi
commit
620c495d31

+ 9 - 5
Userland/Libraries/LibJS/Runtime/Object.cpp

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

+ 3 - 0
Userland/Libraries/LibJS/Runtime/Object.h

@@ -212,6 +212,9 @@ private:
     Object* prototype() { 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;
     Vector<Value> m_storage;
     IndexedProperties m_indexed_properties;