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