Reviewed by John.
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 12 Apr 2005 22:18:35 +0000 (22:18 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 12 Apr 2005 22:18:35 +0000 (22:18 +0000)
<rdar://problem/4086819> Avoid using protect count hash table so much for 5.6% JS iBench speedup

- Avoid using protected values hash for the two most common cases
- Bump up ListImp high water mark, new testing shows 508 ListImps are
created during JS iBench.

Net result is a 5.6% speedup on JavaScript iBench

        * kjs/collector.cpp:
        (KJS::Collector::collect): mark protected lists as appropriate.
        * kjs/context.h:
        * kjs/list.cpp:
        (KJS::ListImp::markValues): Moved implementation from List::markValues
        (KJS::List::markProtectedLists): Implemented - scan pool and overflow
list.
        (KJS::allocateListImp): link lists outside the pool into a separate
doubly linked list to be able to mark protected lists
        (KJS::deallocateListImp): do the corresponding delinking
        (KJS::List::derefValues): do nothing in conservative GC mode
        (KJS::List::refValues): do nothing in conservative GC mode
        (KJS::List::markValues): call ListImp version
        (KJS::List::append):
        * kjs/list.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@9003 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/kjs/collector.cpp
JavaScriptCore/kjs/context.h
JavaScriptCore/kjs/list.cpp
JavaScriptCore/kjs/list.h

index 0addb168d60475d50b71bf99c4dbc289659ff589..4bdb15ab357236f366f89d17f7fb2858fa74ba71 100644 (file)
@@ -1,3 +1,31 @@
+2005-04-11  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by John.
+
+       <rdar://problem/4086819> Avoid using protect count hash table so much for 5.6% JS iBench speedup
+
+       - Avoid using protected values hash for the two most common cases
+       - Bump up ListImp high water mark, new testing shows 508 ListImps are
+       created during JS iBench.
+
+       Net result is a 5.6% speedup on JavaScript iBench
+       
+        * kjs/collector.cpp:
+        (KJS::Collector::collect): mark protected lists as appropriate.
+        * kjs/context.h:
+        * kjs/list.cpp:
+        (KJS::ListImp::markValues): Moved implementation from List::markValues
+        (KJS::List::markProtectedLists): Implemented - scan pool and overflow
+       list.
+        (KJS::allocateListImp): link lists outside the pool into a separate
+       doubly linked list to be able to mark protected lists
+        (KJS::deallocateListImp): do the corresponding delinking
+        (KJS::List::derefValues): do nothing in conservative GC mode
+        (KJS::List::refValues): do nothing in conservative GC mode
+        (KJS::List::markValues): call ListImp version
+        (KJS::List::append):
+        * kjs/list.h:
+
 === Safari-412 ===
 
 === Safari-411 ===
index 2c7113ebe4c3ca914132f289825db2af3819480a..5b89fe052dac4eedf3ef0790c8a69466c109e8cd 100644 (file)
 
 #include "value.h"
 #include "internal.h"
+#include "list.h"
 
 #if APPLE_CHANGES
 #include <CoreFoundation/CoreFoundation.h>
 #include <cxxabi.h>
-#endif
-
-#include <collector.h>
-#include <value.h>
-#include <internal.h>
-
-#if APPLE_CHANGES
 #include <pthread.h>
 #include <mach/mach_port.h>
 #include <mach/task.h>
@@ -372,6 +366,7 @@ bool Collector::collect()
 
   markStackObjectsConservatively();
   markProtectedObjects();
+  List::markProtectedLists();
 #endif
 
 #if TEST_CONSERVATIVE_GC
index 5b29d2167952b95bc424ef8e3549d8d3a7150c40..3ad2a1064d925e9652e26eb1420092c76a7802a7 100644 (file)
@@ -59,11 +59,14 @@ namespace KJS  {
     ContextImp *_callingContext;
     FunctionImp *_function;
     const List *_arguments;
-    ProtectedObject activation;
+    // because ContextImp is always allocated on the stack,
+    // there is no need to protect various pointers from conservative
+    // GC since they will be caught by the conservative sweep anyway!
+    Object activation;
     
     ScopeChain scope;
-    ProtectedObject variable;
-    ProtectedObject thisVal;
+    Object variable;
+    Object thisVal;
 
     LabelStack ls;
     CodeType codeType;
index faa0bcefa04e3f84f8f5c9b941fe4a0304b285ee..d77844328275f11ad89cb4f75ce47aec7b8b5794 100644 (file)
@@ -28,7 +28,7 @@
 namespace KJS {
 
 // tunable parameters
-const int poolSize = 384;
+const int poolSize = 512;
 const int inlineValuesSize = 4;
 
 
@@ -42,14 +42,19 @@ struct ListImp : ListImpBase
     ValueImp **overflow;
 
     ListImp *nextInFreeList;
+    ListImp *nextInOutsideList;
+    ListImp *prevInOutsideList;
 
 #if DUMP_STATISTICS
     int sizeHighWaterMark;
 #endif
+
+    void markValues();
 };
 
 static ListImp pool[poolSize];
 static ListImp *poolFreeList;
+static ListImp *outsidePoolList;
 static int poolUsed;
 
 #if DUMP_STATISTICS
@@ -86,6 +91,49 @@ ListStatisticsExitLogger::~ListStatisticsExitLogger()
 
 #endif
 
+
+inline void ListImp::markValues()
+{
+    int inlineSize = MIN(size, inlineValuesSize);
+    for (int i = 0; i != inlineSize; ++i) {
+       if (!values[i]->marked()) {
+           values[i]->mark();
+       }
+    }
+
+    int overflowSize = size - inlineSize;
+    for (int i = 0; i != overflowSize; ++i) {
+       if (!overflow[i]->marked()) {
+           overflow[i]->mark();
+       }
+    }
+}
+
+void List::markProtectedLists()
+{
+#if TEST_CONSERVATIVE_GC || USE_CONSERVATIVE_GC
+    int seen = 0;
+    for (int i = 0; i < poolSize; i++) {
+        if (seen >= poolUsed)
+            break;
+
+        if (pool[i].state == usedInPool) {
+            seen++;
+            if (pool[i].valueRefCount > 0) {
+                pool[i].markValues();
+            }
+        }
+    }
+
+    for (ListImp *l = outsidePoolList; l; l = l->nextInOutsideList) {
+        if (l->valueRefCount > 0) {
+            l->markValues();
+        }
+    }
+#endif
+}
+
+
 static inline ListImp *allocateListImp()
 {
     // Find a free one in the pool.
@@ -99,6 +147,14 @@ static inline ListImp *allocateListImp()
     
     ListImp *imp = new ListImp;
     imp->state = usedOnHeap;
+    // link into outside pool list
+    if (outsidePoolList) {
+        outsidePoolList->prevInOutsideList = imp;
+    }
+    imp->nextInOutsideList = outsidePoolList;
+    imp->prevInOutsideList = NULL;
+    outsidePoolList = imp;
+
     return imp;
 }
 
@@ -110,6 +166,19 @@ static inline void deallocateListImp(ListImp *imp)
        poolFreeList = imp;
        poolUsed--;
     } else {
+        // unlink from outside pool list
+        if (!imp->prevInOutsideList) {
+            outsidePoolList = imp->nextInOutsideList;
+            if (outsidePoolList) {
+                outsidePoolList->prevInOutsideList = NULL;
+            }
+        } else {
+            imp->prevInOutsideList->nextInOutsideList = imp->nextInOutsideList;
+            if (imp->nextInOutsideList) {
+                imp->nextInOutsideList->prevInOutsideList = imp->prevInOutsideList;
+            }
+        }
+
         delete imp;
     }
 }
@@ -153,82 +222,44 @@ List::List(bool needsMarking) : _impBase(allocateListImp()), _needsMarking(needs
 
 void List::derefValues()
 {
+#if !USE_CONSERVATIVE_GC
     ListImp *imp = static_cast<ListImp *>(_impBase);
     
     int size = imp->size;
     
     int inlineSize = MIN(size, inlineValuesSize);
-#if !USE_CONSERVATIVE_GC
     for (int i = 0; i != inlineSize; ++i)
         imp->values[i]->deref();
-#endif
 
-#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
-    for (int i = 0; i != inlineSize; ++i)
-        gcUnprotect(imp->values[i]);
-#endif
-    
     int overflowSize = size - inlineSize;
     ValueImp **overflow = imp->overflow;
-#if !USE_CONSERVATIVE_GC
-    for (int i = 0; i != overflowSize; ++i)
-        overflow[i]->deref();
-#endif
 
-#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
     for (int i = 0; i != overflowSize; ++i)
-        gcUnprotect(overflow[i]);
+        overflow[i]->deref();
 #endif
 }
 
 void List::refValues()
 {
+#if !USE_CONSERVATIVE_GC
     ListImp *imp = static_cast<ListImp *>(_impBase);
     
     int size = imp->size;
     
     int inlineSize = MIN(size, inlineValuesSize);
-#if !USE_CONSERVATIVE_GC
     for (int i = 0; i != inlineSize; ++i)
         imp->values[i]->ref();
-#endif
-#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
-    for (int i = 0; i != inlineSize; ++i)
-        gcProtect(imp->values[i]);
-#endif
     
     int overflowSize = size - inlineSize;
     ValueImp **overflow = imp->overflow;
-#if !USE_CONSERVATIVE_GC
     for (int i = 0; i != overflowSize; ++i)
         overflow[i]->ref();
 #endif
-#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
-    for (int i = 0; i != overflowSize; ++i)
-        gcProtect(overflow[i]);
-#endif
 }
 
 void List::markValues()
 {
-    ListImp *imp = static_cast<ListImp *>(_impBase);
-    
-    int size = imp->size;
-    
-    int inlineSize = MIN(size, inlineValuesSize);
-    for (int i = 0; i != inlineSize; ++i) {
-       if (!imp->values[i]->marked()) {
-           imp->values[i]->mark();
-       }
-    }
-
-    int overflowSize = size - inlineSize;
-    ValueImp **overflow = imp->overflow;
-    for (int i = 0; i != overflowSize; ++i) {
-       if (!overflow[i]->marked()) {
-           overflow[i]->mark();
-       }
-    }
+    static_cast<ListImp *>(_impBase)->markValues();
 }
 
 void List::release()
@@ -279,9 +310,6 @@ void List::append(ValueImp *v)
     if (imp->valueRefCount > 0) {
 #if !USE_CONSERVATIVE_GC
        v->ref();
-#endif
-#if USE_CONSERVATIVE_GC | TEST_CONSERVATIVE_GC
-       gcProtect(v);
 #endif
     }
     
index 38ef813391bf8ffccac574278b767239f9e9d8ee..130d6a7398568e1658271bbf592b6e46da3a119f 100644 (file)
@@ -120,6 +120,8 @@ namespace KJS {
         static const List &empty();
         
        void mark() { if (_impBase->valueRefCount == 0) markValues(); }
+
+        static void markProtectedLists();
     private:
         ListImpBase *_impBase;
        bool _needsMarking;