Reviewed by Darin.
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 23 Apr 2007 08:53:41 +0000 (08:53 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 23 Apr 2007 08:53:41 +0000 (08:53 +0000)
        - shrink ArrayInstance objects by 4 bytes
        http://bugs.webkit.org/show_bug.cgi?id=13386

        I did this by storing the capacity before the beginning of the storage array. It turns out
        it is rarely needed and is by definition 0 when the storage array is null.

        * kjs/array_instance.h:
        (KJS::ArrayInstance::capacity): Get it from the secret stash
        * kjs/array_object.cpp:
        (allocateStorage): New function to encapsulate allocating the storage with extra space ahead
        for the capacity.
        (reallocateStorage): ditto for realloc
        (ArrayInstance::ArrayInstance):
        (ArrayInstance::~ArrayInstance):
        (ArrayInstance::resizeStorage):

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

JavaScriptCore/ChangeLog
JavaScriptCore/kjs/array_instance.h
JavaScriptCore/kjs/array_object.cpp

index ece4d6d2a79024c1abcde7aae898471e707b3aa8..aab67bcdd441fcd047073c1477599c238dcb6276 100644 (file)
@@ -1,3 +1,23 @@
+2007-04-23  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+       
+        - shrink ArrayInstance objects by 4 bytes
+        http://bugs.webkit.org/show_bug.cgi?id=13386
+        
+        I did this by storing the capacity before the beginning of the storage array. It turns out
+        it is rarely needed and is by definition 0 when the storage array is null.
+        * kjs/array_instance.h:
+        (KJS::ArrayInstance::capacity): Get it from the secret stash
+        * kjs/array_object.cpp:
+        (allocateStorage): New function to encapsulate allocating the storage with extra space ahead
+        for the capacity.
+        (reallocateStorage): ditto for realloc
+        (ArrayInstance::ArrayInstance):
+        (ArrayInstance::~ArrayInstance):
+        (ArrayInstance::resizeStorage):
+
 2007-04-23  Darin Adler  <darin@apple.com>
 
         Reviewed by Maciej.
index 2fc5550bb8400255c2cde5337619dbfb77eb2d00..d7216a96ab2ab2436ad8d06553880a3431f3eafb 100644 (file)
@@ -61,9 +61,11 @@ namespace KJS {
     
     void resizeStorage(unsigned);
 
+    // store capacity in extra space at the beginning of the storage array to save space
+    size_t capacity() { return storage ? reinterpret_cast<size_t>(storage[-1]) : 0; }
+
     unsigned length;
     unsigned storageLength;
-    unsigned capacity;
     JSValue **storage;
   };
 
index fa30189fd8486ea2123974bbee2944e2dcb05ccd..624c29016d8079a499582b0787641cdfc46f4c7c 100644 (file)
@@ -42,12 +42,40 @@ const unsigned sparseArrayCutoff = 10000;
 
 const ClassInfo ArrayInstance::info = {"Array", 0, 0, 0};
 
+static inline JSValue** allocateStorage(size_t capacity)
+{
+  if (capacity == 0)
+      return 0;
+
+  // store capacity in extra space before the beginning of the storage array to save space
+  JSValue** storage = static_cast<JSValue**>(fastCalloc(capacity + 1, sizeof(JSValue *))) + 1;
+  storage[-1] = reinterpret_cast<JSValue*>(capacity);
+  return storage;
+}
+
+static inline void reallocateStorage(JSValue**& storage, size_t newCapacity)
+{
+  if (!storage) {
+    storage =  allocateStorage(newCapacity);
+    return;
+  }
+
+  // store capacity in extra space before the beginning of the storage array to save space
+  storage = static_cast<JSValue**>(fastRealloc(storage - 1, (newCapacity + 1) * sizeof (JSValue*))) + 1;
+  storage[-1] = reinterpret_cast<JSValue*>(newCapacity);
+}
+
+static inline void freeStorage(JSValue** storage)
+{
+  if (storage)
+    fastFree(storage - 1);
+}
+
 ArrayInstance::ArrayInstance(JSObject *proto, unsigned initialLength)
   : JSObject(proto)
   , length(initialLength)
   , storageLength(initialLength < sparseArrayCutoff ? initialLength : 0)
-  , capacity(storageLength)
-  , storage(capacity ? (JSValue **)fastCalloc(capacity, sizeof(JSValue *)) : 0)
+  , storage(allocateStorage(storageLength))
 {
 }
 
@@ -55,8 +83,7 @@ ArrayInstance::ArrayInstance(JSObject *proto, const List &list)
   : JSObject(proto)
   , length(list.size())
   , storageLength(length)
-  , capacity(storageLength)
-  , storage(capacity ? (JSValue **)fastMalloc(sizeof(JSValue *) * capacity) : 0)
+  , storage(allocateStorage(storageLength))
 {
   ListIterator it = list.begin();
   unsigned l = length;
@@ -67,7 +94,7 @@ ArrayInstance::ArrayInstance(JSObject *proto, const List &list)
 
 ArrayInstance::~ArrayInstance()
 {
-  fastFree(storage);
+  freeStorage(storage);
 }
 
 JSValue* ArrayInstance::getItem(unsigned i) const
@@ -231,7 +258,8 @@ void ArrayInstance::resizeStorage(unsigned newLength)
     if (newLength < storageLength) {
       memset(storage + newLength, 0, sizeof(JSValue *) * (storageLength - newLength));
     }
-    if (newLength > capacity) {
+    size_t cap = capacity();
+    if (newLength > cap) {
       unsigned newCapacity;
       if (newLength > sparseArrayCutoff) {
         newCapacity = newLength;
@@ -241,9 +269,9 @@ void ArrayInstance::resizeStorage(unsigned newLength)
           newCapacity = sparseArrayCutoff;
         }
       }
-      storage = (JSValue **)fastRealloc(storage, newCapacity * sizeof (JSValue *));
-      memset(storage + capacity, 0, sizeof(JSValue *) * (newCapacity - capacity));
-      capacity = newCapacity;
+      
+      reallocateStorage(storage, newCapacity);
+      memset(storage + cap, 0, sizeof(JSValue*) * (newCapacity - cap));
     }
     storageLength = newLength;
 }
@@ -314,10 +342,10 @@ void ArrayInstance::sort(ExecState* exec)
     // values to string once up front, and then use a radix sort. That would be O(N) rather than 
     // O(N log N).
     if (lengthNotIncludingUndefined < sparseArrayCutoff) {
-        JSValue** storageCopy = static_cast<JSValue**>(fastMalloc(capacity * sizeof(JSValue*)));
-        memcpy(storageCopy, storage, capacity * sizeof(JSValue*));
+        JSValue** storageCopy = allocateStorage(capacity());
+        memcpy(storageCopy, storage, capacity() * sizeof(JSValue*));
         mergesort(storageCopy, lengthNotIncludingUndefined, sizeof(JSValue *), compareByStringForQSort);
-        fastFree(storage);
+        freeStorage(storage);
         storage = storageCopy;
         execForCompareByStringForQSort = oldExec;
         return;
@@ -381,10 +409,10 @@ void ArrayInstance::sort(ExecState* exec, JSObject* compareFunction)
     // FIXME: a tree sort using a perfectly balanced tree (e.g. an AVL tree) could do an even
     // better job of minimizing compares
     if (lengthNotIncludingUndefined < sparseArrayCutoff) {
-        JSValue** storageCopy = static_cast<JSValue**>(fastMalloc(capacity * sizeof(JSValue*)));
-        memcpy(storageCopy, storage, capacity * sizeof(JSValue*));
+        JSValue** storageCopy = allocateStorage(capacity());
+        memcpy(storageCopy, storage, capacity() * sizeof(JSValue*));
         mergesort(storageCopy, lengthNotIncludingUndefined, sizeof(JSValue *), compareWithCompareFunctionForQSort);
-        fastFree(storage);
+        freeStorage(storage);
         storage = storageCopy;
         compareWithCompareFunctionArguments = oldArgs;
         return;