Title: [104184] trunk/Source/_javascript_Core
Revision
104184
Author
[email protected]
Date
2012-01-05 11:32:42 -0800 (Thu, 05 Jan 2012)

Log Message

push/shift fifo may consume excessive memory
https://bugs.webkit.org/show_bug.cgi?id=75610

Reviewed by Sam Weinig.

Array object commonly store data in a vector, consisting of a portion that is
in use, a pre-capacity (m_indexBias) and a post-capacity (the delta between
m_length and m_vectorLength). Calls to shift with grow the pre-capacity, and
the current algorithm for increaseVectorLength (used by push, or [[Put]]) will
never shrink the pre-capacity, so a push/shift fifo may consume an inordinate
amount of memory, whilst having a relatively small active length.

* runtime/JSArray.cpp:
(JSC::JSArray::increaseVectorLength):
    - If m_indexBias is non-zero, decay it over time.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (104183 => 104184)


--- trunk/Source/_javascript_Core/ChangeLog	2012-01-05 19:24:49 UTC (rev 104183)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-01-05 19:32:42 UTC (rev 104184)
@@ -1,3 +1,21 @@
+2012-01-05  Gavin Barraclough  <[email protected]>
+
+        push/shift fifo may consume excessive memory
+        https://bugs.webkit.org/show_bug.cgi?id=75610
+
+        Reviewed by Sam Weinig.
+
+        Array object commonly store data in a vector, consisting of a portion that is
+        in use, a pre-capacity (m_indexBias) and a post-capacity (the delta between
+        m_length and m_vectorLength). Calls to shift with grow the pre-capacity, and
+        the current algorithm for increaseVectorLength (used by push, or [[Put]]) will
+        never shrink the pre-capacity, so a push/shift fifo may consume an inordinate
+        amount of memory, whilst having a relatively small active length.
+
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::increaseVectorLength):
+            - If m_indexBias is non-zero, decay it over time.
+
 2012-01-05  Csaba Osztrogonác  <[email protected]>
 
         unshift/pop fifo may consume excessive memory

Modified: trunk/Source/_javascript_Core/runtime/JSArray.cpp (104183 => 104184)


--- trunk/Source/_javascript_Core/runtime/JSArray.cpp	2012-01-05 19:24:49 UTC (rev 104183)
+++ trunk/Source/_javascript_Core/runtime/JSArray.cpp	2012-01-05 19:32:42 UTC (rev 104184)
@@ -554,20 +554,51 @@
     unsigned newVectorLength = getNewVectorLength(newLength);
     void* baseStorage = storage->m_allocBase;
 
-    if (!tryFastRealloc(baseStorage, storageSize(newVectorLength + m_indexBias)).getValue(baseStorage))
-        return false;
+    // Fast case - there is no precapacity. In these cases a realloc makes sense.
+    if (LIKELY(!m_indexBias)) {
+        if (!tryFastRealloc(baseStorage, storageSize(newVectorLength)).getValue(baseStorage))
+            return false;
 
-    storage = m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(baseStorage) + m_indexBias * sizeof(WriteBarrier<Unknown>));
-    m_storage->m_allocBase = baseStorage;
+        storage = m_storage = reinterpret_cast_ptr<ArrayStorage*>(baseStorage);
+        m_storage->m_allocBase = baseStorage;
 
-    WriteBarrier<Unknown>* vector = storage->m_vector;
-    for (unsigned i = vectorLength; i < newVectorLength; ++i)
-        vector[i].clear();
+        WriteBarrier<Unknown>* vector = storage->m_vector;
+        for (unsigned i = vectorLength; i < newVectorLength; ++i)
+            vector[i].clear();
 
+        m_vectorLength = newVectorLength;
+        
+        Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
+        return true;
+    }
+
+    // Remove some, but not all of the precapacity. Atomic decay, & capped to not overflow array length.
+    unsigned newIndexBias = min(m_indexBias >> 1, MAX_STORAGE_VECTOR_LENGTH - newVectorLength);
+    // Calculate new stoarge capcity, allowing room for the pre-capacity.
+    unsigned newStorageCapacity = newVectorLength + newIndexBias;
+    void* newAllocBase;
+    if (!tryFastMalloc(storageSize(newStorageCapacity)).getValue(newAllocBase))
+        return false;
+    // The sum of m_vectorLength and m_indexBias will never exceed MAX_STORAGE_VECTOR_LENGTH.
+    ASSERT(m_vectorLength <= MAX_STORAGE_VECTOR_LENGTH && (MAX_STORAGE_VECTOR_LENGTH - m_vectorLength) >= m_indexBias);
+    unsigned currentCapacity = m_vectorLength + m_indexBias;
+    // Currently there is no way to report to the heap that the extra capacity is shrinking!
+    if (newStorageCapacity > currentCapacity)
+        Heap::heap(this)->reportExtraMemoryCost((newStorageCapacity - currentCapacity) * sizeof(WriteBarrier<Unknown>));
+
     m_vectorLength = newVectorLength;
-    
-    Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
+    m_indexBias = newIndexBias;
+    m_storage = reinterpret_cast_ptr<ArrayStorage*>(reinterpret_cast<WriteBarrier<Unknown>*>(newAllocBase) + m_indexBias);
 
+    // Copy the ArrayStorage header & current contents of the vector, clear the new post-capacity.
+    memmove(m_storage, storage, storageSize(vectorLength));
+    for (unsigned i = vectorLength; i < m_vectorLength; ++i)
+        m_storage->m_vector[i].clear();
+
+    // Free the old allocation, update m_allocBase.
+    fastFree(m_storage->m_allocBase);
+    m_storage->m_allocBase = newAllocBase;
+
     return true;
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to