From: Apple Date: Tue, 23 Oct 2012 00:18:28 +0000 (+0000) Subject: JavaScriptCore-1097.3.3.tar.gz X-Git-Tag: ios-601^0 X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/commitdiff_plain/1981f5dfe8d77d97469d20652f712a09400c48ed JavaScriptCore-1097.3.3.tar.gz --- diff --git a/runtime/ArrayPrototype.cpp b/runtime/ArrayPrototype.cpp index 6df58b7..62f845d 100644 --- a/runtime/ArrayPrototype.cpp +++ b/runtime/ArrayPrototype.cpp @@ -190,8 +190,11 @@ static inline void shift(ExecState* exec, JSObject* thisObj, unsigned header, un ASSERT(header <= length); ASSERT(currentCount <= (length - header)); - if (!header && isJSArray(thisObj) && asArray(thisObj)->shiftCount(exec, count)) - return; + if (!header && isJSArray(thisObj)) { + JSArray* array = asArray(thisObj); + if (array->length() == length && asArray(thisObj)->shiftCount(exec, count)) + return; + } for (unsigned k = header; k < length - currentCount; ++k) { unsigned from = k + currentCount; @@ -230,8 +233,11 @@ static inline void unshift(ExecState* exec, JSObject* thisObj, unsigned header, return; } - if (!header && isJSArray(thisObj) && asArray(thisObj)->unshiftCount(exec, count)) - return; + if (!header && isJSArray(thisObj)) { + JSArray* array = asArray(thisObj); + if (array->length() == length && array->unshiftCount(exec, count)) + return; + } for (unsigned k = length - currentCount; k > header; --k) { unsigned from = k + currentCount - 1; @@ -628,7 +634,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) CallData callData; CallType callType = getCallData(function, callData); - if (thisObj->classInfo() == &JSArray::s_info && !asArray(thisObj)->inSparseMode()) { + if (thisObj->classInfo() == &JSArray::s_info && !asArray(thisObj)->hasSparseMap()) { if (isNumericCompareFunction(exec, callType, callData)) asArray(thisObj)->sortNumeric(exec, function, callType, callData); else if (callType != CallTypeNone) diff --git a/runtime/JSArray.cpp b/runtime/JSArray.cpp index aa1b8b7..adcb8fc 100644 --- a/runtime/JSArray.cpp +++ b/runtime/JSArray.cpp @@ -1412,11 +1412,8 @@ void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType cal ArrayStorage* storage = m_storage; - unsigned lengthNotIncludingUndefined = compactForSorting(exec->globalData()); - if (m_sparseValueMap) { - throwOutOfMemoryError(exec); - return; - } + unsigned lengthNotIncludingUndefined = compactForSorting(); + ASSERT(!m_sparseValueMap); if (!lengthNotIncludingUndefined) return; @@ -1445,11 +1442,8 @@ void JSArray::sort(ExecState* exec) { ASSERT(!inSparseMode()); - unsigned lengthNotIncludingUndefined = compactForSorting(exec->globalData()); - if (m_sparseValueMap) { - throwOutOfMemoryError(exec); - return; - } + unsigned lengthNotIncludingUndefined = compactForSorting(); + ASSERT(!m_sparseValueMap); if (!lengthNotIncludingUndefined) return; @@ -1608,7 +1602,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, return; unsigned usedVectorLength = min(m_storage->m_length, m_vectorLength); - unsigned nodeCount = usedVectorLength + (m_sparseValueMap ? m_sparseValueMap->size() : 0); + unsigned nodeCount = usedVectorLength; if (!nodeCount) return; @@ -1636,6 +1630,8 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, // 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 = m_storage->m_vector[numDefined].get(); if (!v || v.isUndefined()) break; @@ -1643,6 +1639,8 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, tree.insert(numDefined); } for (unsigned i = numDefined; i < usedVectorLength; ++i) { + if (i > m_vectorLength) + break; JSValue v = m_storage->m_vector[i].get(); if (v) { if (v.isUndefined()) @@ -1657,49 +1655,33 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, unsigned newUsedVectorLength = numDefined + numUndefined; - if (SparseArrayValueMap* map = 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(exec->globalData(), newUsedVectorLength)) { - throwOutOfMemoryError(exec); - return; - } - } + ASSERT(!m_sparseValueMap); - SparseArrayValueMap::const_iterator end = map->end(); - for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) { - tree.abstractor().m_nodes[numDefined].value = it->second.getNonSparseMode(); - tree.insert(numDefined); - ++numDefined; - } - - deallocateSparseMap(); - } - - 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. + // 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(tree.abstractor().m_nodes.size())); + unsigned undefinedElementsThreshold = min(newestUsedVectorLength, newUsedVectorLength); + unsigned clearElementsThreshold = min(newestUsedVectorLength, usedVectorLength); // Copy the values back into m_storage. AVLTree::Iterator iter; iter.start_iter_least(tree); JSGlobalData& globalData = exec->globalData(); - for (unsigned i = 0; i < numDefined; ++i) { + for (unsigned i = 0; i < elementsToExtractThreshold; ++i) { m_storage->m_vector[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value); ++iter; } // Put undefined values back in. - for (unsigned i = numDefined; i < newUsedVectorLength; ++i) + for (unsigned i = elementsToExtractThreshold; i < undefinedElementsThreshold; ++i) m_storage->m_vector[i].setUndefined(); // Ensure that unused values in the vector are zeroed out. - for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i) + for (unsigned i = undefinedElementsThreshold; i < clearElementsThreshold; ++i) m_storage->m_vector[i].clear(); - m_storage->m_numValuesInVector = newUsedVectorLength; + m_storage->m_numValuesInVector = undefinedElementsThreshold; checkConsistency(SortConsistencyCheck); } @@ -1740,7 +1722,7 @@ void JSArray::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t le callFrame->setArgument(i, get(exec, i)); } -unsigned JSArray::compactForSorting(JSGlobalData& globalData) +unsigned JSArray::compactForSorting() { ASSERT(!inSparseMode()); @@ -1771,23 +1753,7 @@ unsigned JSArray::compactForSorting(JSGlobalData& globalData) unsigned newUsedVectorLength = numDefined + numUndefined; - if (SparseArrayValueMap* map = 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(globalData, newUsedVectorLength)) - return 0; - - storage = m_storage; - } - - SparseArrayValueMap::const_iterator end = map->end(); - for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) - storage->m_vector[numDefined++].setWithoutWriteBarrier(it->second.getNonSparseMode()); - - deallocateSparseMap(); - } + ASSERT(!m_sparseValueMap); for (unsigned i = numDefined; i < newUsedVectorLength; ++i) storage->m_vector[i].setUndefined(); diff --git a/runtime/JSArray.h b/runtime/JSArray.h index 17c7f3e..06675a0 100644 --- a/runtime/JSArray.h +++ b/runtime/JSArray.h @@ -250,6 +250,11 @@ namespace JSC { m_storage->m_inCompactInitialization = false; #endif } + + bool hasSparseMap() + { + return m_sparseValueMap; + } bool inSparseMode() { @@ -312,7 +317,7 @@ namespace JSC { bool increaseVectorLength(JSGlobalData&, unsigned newLength); bool unshiftCountSlowCase(JSGlobalData&, unsigned count); - unsigned compactForSorting(JSGlobalData&); + unsigned compactForSorting(); enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck }; void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);