Modified: branches/safari-534.59-branch/Source/_javascript_Core/ChangeLog (155375 => 155376)
--- branches/safari-534.59-branch/Source/_javascript_Core/ChangeLog 2013-09-09 19:58:35 UTC (rev 155375)
+++ branches/safari-534.59-branch/Source/_javascript_Core/ChangeLog 2013-09-09 20:21:27 UTC (rev 155376)
@@ -1,18 +1,3 @@
-2013-09-09 Lucas Forschler <[email protected]>
-
- Merge fix for <rdar:/problem/14909253>
-
- 2013-09-09 Filip Pizlo <[email protected]>
-
- * runtime/ArrayPrototype.cpp:
- (JSC::arrayProtoFuncSort):
- * runtime/JSArray.cpp:
- (JSC::JSArray::sortNumeric):
- (JSC::JSArray::sort):
- (JSC::JSArray::compactForSorting):
- * runtime/JSArray.h:
- (JSC::JSArray::hasSparseMap):
-
2013-03-14 Lucas Forschler <[email protected]>
Merge r138606
Modified: branches/safari-534.59-branch/Source/_javascript_Core/runtime/ArrayPrototype.cpp (155375 => 155376)
--- branches/safari-534.59-branch/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2013-09-09 19:58:35 UTC (rev 155375)
+++ branches/safari-534.59-branch/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2013-09-09 20:21:27 UTC (rev 155376)
@@ -538,7 +538,7 @@
CallData callData;
CallType callType = getCallData(function, callData);
- if (thisObj->classInfo() == &JSArray::s_info && !asArray(thisObj)->hasSparseMap()) {
+ if (thisObj->classInfo() == &JSArray::s_info) {
if (isNumericCompareFunction(exec, callType, callData))
asArray(thisObj)->sortNumeric(exec, function, callType, callData);
else if (callType != CallTypeNone)
Modified: branches/safari-534.59-branch/Source/_javascript_Core/runtime/JSArray.cpp (155375 => 155376)
--- branches/safari-534.59-branch/Source/_javascript_Core/runtime/JSArray.cpp 2013-09-09 19:58:35 UTC (rev 155375)
+++ branches/safari-534.59-branch/Source/_javascript_Core/runtime/JSArray.cpp 2013-09-09 20:21:27 UTC (rev 155376)
@@ -964,8 +964,10 @@
ArrayStorage* storage = m_storage;
unsigned lengthNotIncludingUndefined = compactForSorting();
-
- ASSERT(!storage->m_sparseValueMap);
+ if (storage->m_sparseValueMap) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
if (!lengthNotIncludingUndefined)
return;
@@ -995,7 +997,10 @@
ArrayStorage* storage = m_storage;
unsigned lengthNotIncludingUndefined = compactForSorting();
- ASSERT(!storage->m_sparseValueMap);
+ if (storage->m_sparseValueMap) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
if (!lengthNotIncludingUndefined)
return;
@@ -1149,7 +1154,7 @@
return;
unsigned usedVectorLength = min(storage->m_length, m_vectorLength);
- unsigned nodeCount = usedVectorLength;
+ unsigned nodeCount = usedVectorLength + (storage->m_sparseValueMap ? storage->m_sparseValueMap->size() : 0);
if (!nodeCount)
return;
@@ -1177,8 +1182,6 @@
// Iterate over the array, ignoring missing values, counting undefined ones, and inserting all other ones into the tree.
for (; numDefined < usedVectorLength; ++numDefined) {
- if (numDefined >= m_vectorLength)
- break;
JSValue v = storage->m_vector[numDefined].get();
if (!v || v.isUndefined())
break;
@@ -1186,8 +1189,6 @@
tree.insert(numDefined);
}
for (unsigned i = numDefined; i < usedVectorLength; ++i) {
- if (i >= m_vectorLength)
- break;
JSValue v = storage->m_vector[i].get();
if (v) {
if (v.isUndefined())
@@ -1202,30 +1203,49 @@
unsigned newUsedVectorLength = numDefined + numUndefined;
- ASSERT(!storage->m_sparseValueMap);
-
- // The array size may have changed. Figure out the new bounds.
- unsigned newestUsedVectorLength = min(m_storage->m_length, m_vectorLength);
-
- unsigned elementsToExtractThreshold = min(min(newestUsedVectorLength, numDefined), static_cast<unsigned>(tree.abstractor().m_nodes.size()));
- unsigned undefinedElementsThreshold = min(newestUsedVectorLength, newUsedVectorLength);
- unsigned clearElementsThreshold = min(newestUsedVectorLength, usedVectorLength);
-
+ if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ newUsedVectorLength += map->size();
+ if (newUsedVectorLength > m_vectorLength) {
+ // Check that it is possible to allocate an array large enough to hold all the entries.
+ if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength)) {
+ throwOutOfMemoryError(exec);
+ return;
+ }
+ }
+
+ storage = m_storage;
+
+ SparseArrayValueMap::iterator end = map->end();
+ for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) {
+ tree.abstractor().m_nodes[numDefined].value = it->second.get();
+ tree.insert(numDefined);
+ ++numDefined;
+ }
+
+ delete map;
+ storage->m_sparseValueMap = 0;
+ }
+
+ ASSERT(tree.abstractor().m_nodes.size() >= numDefined);
+
+ // FIXME: If the compare function changed the length of the array, the following might be
+ // modifying the vector incorrectly.
+
// Copy the values back into m_storage.
AVLTree<AVLTreeAbstractorForArrayCompare, 44>::Iterator iter;
iter.start_iter_least(tree);
JSGlobalData& globalData = exec->globalData();
- for (unsigned i = 0; i < elementsToExtractThreshold; ++i) {
+ for (unsigned i = 0; i < numDefined; ++i) {
storage->m_vector[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value);
++iter;
}
// Put undefined values back in.
- for (unsigned i = elementsToExtractThreshold; i < undefinedElementsThreshold; ++i)
+ for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
storage->m_vector[i].setUndefined();
// Ensure that unused values in the vector are zeroed out.
- for (unsigned i = undefinedElementsThreshold; i < clearElementsThreshold; ++i)
+ for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
storage->m_vector[i].clear();
storage->m_numValuesInVector = newUsedVectorLength;
@@ -1298,8 +1318,25 @@
unsigned newUsedVectorLength = numDefined + numUndefined;
- ASSERT(!storage->m_sparseValueMap);
+ if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ newUsedVectorLength += map->size();
+ if (newUsedVectorLength > m_vectorLength) {
+ // Check that it is possible to allocate an array large enough to hold all the entries - if not,
+ // exception is thrown by caller.
+ if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength))
+ return 0;
+ storage = m_storage;
+ }
+
+ SparseArrayValueMap::iterator end = map->end();
+ for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
+ storage->m_vector[numDefined++].setWithoutWriteBarrier(it->second.get());
+
+ delete map;
+ storage->m_sparseValueMap = 0;
+ }
+
for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
storage->m_vector[i].setUndefined();
for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
Modified: branches/safari-534.59-branch/Source/_javascript_Core/runtime/JSArray.h (155375 => 155376)
--- branches/safari-534.59-branch/Source/_javascript_Core/runtime/JSArray.h 2013-09-09 19:58:35 UTC (rev 155375)
+++ branches/safari-534.59-branch/Source/_javascript_Core/runtime/JSArray.h 2013-09-09 20:21:27 UTC (rev 155376)
@@ -173,11 +173,6 @@
}
static void visitChildren(JSCell*, SlotVisitor&);
-
- bool hasSparseMap()
- {
- return !!m_storage->m_sparseValueMap;
- }
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;