Title: [169816] trunk/Source/_javascript_Core
Revision
169816
Author
rn...@webkit.org
Date
2014-06-11 12:29:51 -0700 (Wed, 11 Jun 2014)

Log Message

Structure::get should instantiate DeferGC only when materializing property map
https://bugs.webkit.org/show_bug.cgi?id=133727

Reviewed by Geoffrey Garen.

DeferGC instances in Structure::get was added in http://trac.webkit.org/r157539 in order to avoid
collecting the property table newly created by materializePropertyMapIfNecessary since GC can happen
when GCSafeConcurrentJITLocker goes out of scope.

However, always instantiating DeferGC inside Structure::get introduced a new performance bottleneck
in JSObject::getPropertySlot because frequently incrementing and decrementing a counter in vm.m_heap
and running a release assertion inside Heap::incrementDeferralDepth() is expensive.

Work around this by instantiating DeferGC only when we're actually calling materializePropertyMap,
and immediately storing a pointer to the newly created property table in the stack before DeferGC
goes out of scope so that the property table will be marked.

This shows 13-16% improvement on the microbenchmark attached in the bug.

* runtime/JSCJSValue.cpp:
* runtime/JSObject.h:
(JSC::JSObject::fastGetOwnPropertySlot):
* runtime/Structure.h:
(JSC::Structure::materializePropertyMapIfNecessary):
* runtime/StructureInlines.h:
(JSC::Structure::get):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (169815 => 169816)


--- trunk/Source/_javascript_Core/ChangeLog	2014-06-11 18:40:13 UTC (rev 169815)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-06-11 19:29:51 UTC (rev 169816)
@@ -1,3 +1,32 @@
+2014-06-11  Ryosuke Niwa  <rn...@webkit.org>
+
+        Structure::get should instantiate DeferGC only when materializing property map
+        https://bugs.webkit.org/show_bug.cgi?id=133727
+
+        Reviewed by Geoffrey Garen.
+
+        DeferGC instances in Structure::get was added in http://trac.webkit.org/r157539 in order to avoid
+        collecting the property table newly created by materializePropertyMapIfNecessary since GC can happen
+        when GCSafeConcurrentJITLocker goes out of scope.
+
+        However, always instantiating DeferGC inside Structure::get introduced a new performance bottleneck
+        in JSObject::getPropertySlot because frequently incrementing and decrementing a counter in vm.m_heap
+        and running a release assertion inside Heap::incrementDeferralDepth() is expensive.
+
+        Work around this by instantiating DeferGC only when we're actually calling materializePropertyMap,
+        and immediately storing a pointer to the newly created property table in the stack before DeferGC
+        goes out of scope so that the property table will be marked.
+
+        This shows 13-16% improvement on the microbenchmark attached in the bug.
+
+        * runtime/JSCJSValue.cpp:
+        * runtime/JSObject.h:
+        (JSC::JSObject::fastGetOwnPropertySlot):
+        * runtime/Structure.h:
+        (JSC::Structure::materializePropertyMapIfNecessary):
+        * runtime/StructureInlines.h:
+        (JSC::Structure::get):
+
 2014-06-11  Andreas Kling  <akl...@apple.com>
 
         Some JSValue::get() micro-optimzations.

Modified: trunk/Source/_javascript_Core/runtime/JSCJSValue.cpp (169815 => 169816)


--- trunk/Source/_javascript_Core/runtime/JSCJSValue.cpp	2014-06-11 18:40:13 UTC (rev 169815)
+++ trunk/Source/_javascript_Core/runtime/JSCJSValue.cpp	2014-06-11 19:29:51 UTC (rev 169816)
@@ -34,6 +34,7 @@
 #include "JSGlobalObject.h"
 #include "JSNotAnObject.h"
 #include "NumberObject.h"
+#include "StructureInlines.h"
 #include <wtf/MathExtras.h>
 #include <wtf/StringExtras.h>
 

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (169815 => 169816)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2014-06-11 18:40:13 UTC (rev 169815)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2014-06-11 19:29:51 UTC (rev 169816)
@@ -1256,7 +1256,7 @@
 
 ALWAYS_INLINE bool JSObject::fastGetOwnPropertySlot(ExecState* exec, VM& vm, Structure& structure, PropertyName propertyName, PropertySlot& slot)
 {
-    if (!TypeInfo::overridesGetOwnPropertySlot(inlineTypeFlags()))
+    if (LIKELY(!TypeInfo::overridesGetOwnPropertySlot(inlineTypeFlags())))
         return asObject(this)->inlineGetOwnPropertySlot(vm, structure, propertyName, slot);
     return structure.classInfo()->methodTable.getOwnPropertySlot(this, exec, propertyName, slot);
 }

Modified: trunk/Source/_javascript_Core/runtime/Structure.h (169815 => 169816)


--- trunk/Source/_javascript_Core/runtime/Structure.h	2014-06-11 18:40:13 UTC (rev 169815)
+++ trunk/Source/_javascript_Core/runtime/Structure.h	2014-06-11 19:29:51 UTC (rev 169816)
@@ -434,6 +434,18 @@
         if (!propertyTable() && previousID())
             materializePropertyMap(vm);
     }
+    void materializePropertyMapIfNecessary(VM& vm, PropertyTable*& table)
+    {
+        ASSERT(!isCompilationThread());
+        ASSERT(structure()->classInfo() == info());
+        ASSERT(checkOffsetConsistency());
+        table = propertyTable().get();
+        if (!table && previousID()) {
+            DeferGC deferGC(vm.heap);
+            materializePropertyMap(vm);
+            table = propertyTable().get();
+        }
+    }
     void materializePropertyMapIfNecessaryForPinning(VM& vm, DeferGC&)
     {
         ASSERT(structure()->classInfo() == info());

Modified: trunk/Source/_javascript_Core/runtime/StructureInlines.h (169815 => 169816)


--- trunk/Source/_javascript_Core/runtime/StructureInlines.h	2014-06-11 18:40:13 UTC (rev 169815)
+++ trunk/Source/_javascript_Core/runtime/StructureInlines.h	2014-06-11 19:29:51 UTC (rev 169816)
@@ -77,12 +77,12 @@
 {
     ASSERT(!isCompilationThread());
     ASSERT(structure()->classInfo() == info());
-    DeferGC deferGC(vm.heap);
-    materializePropertyMapIfNecessary(vm, deferGC);
-    if (!propertyTable())
+    PropertyTable* propertyTable;
+    materializePropertyMapIfNecessary(vm, propertyTable);
+    if (!propertyTable)
         return invalidOffset;
 
-    PropertyMapEntry* entry = propertyTable()->get(propertyName.uid());
+    PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
     return entry ? entry->offset : invalidOffset;
 }
 
@@ -90,12 +90,12 @@
 {
     ASSERT(!isCompilationThread());
     ASSERT(structure()->classInfo() == info());
-    DeferGC deferGC(vm.heap);
-    materializePropertyMapIfNecessary(vm, deferGC);
-    if (!propertyTable())
+    PropertyTable* propertyTable;
+    materializePropertyMapIfNecessary(vm, propertyTable);
+    if (!propertyTable)
         return invalidOffset;
 
-    PropertyMapEntry* entry = propertyTable()->findWithString(name.impl()).first;
+    PropertyMapEntry* entry = propertyTable->findWithString(name.impl()).first;
     return entry ? entry->offset : invalidOffset;
 }
     
@@ -104,12 +104,12 @@
     ASSERT(!isCompilationThread());
     ASSERT(structure()->classInfo() == info());
 
-    DeferGC deferGC(vm.heap);
-    materializePropertyMapIfNecessary(vm, deferGC);
-    if (!propertyTable())
+    PropertyTable* propertyTable;
+    materializePropertyMapIfNecessary(vm, propertyTable);
+    if (!propertyTable)
         return invalidOffset;
 
-    PropertyMapEntry* entry = propertyTable()->get(propertyName.uid());
+    PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
     if (!entry)
         return invalidOffset;
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to