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;
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;
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)
ArrayStorage* storage = m_storage;
- unsigned lengthNotIncludingUndefined = compactForSorting(exec->globalData());
- if (m_sparseValueMap) {
- throwOutOfMemoryError(exec);
- return;
- }
+ unsigned lengthNotIncludingUndefined = compactForSorting();
+ ASSERT(!m_sparseValueMap);
if (!lengthNotIncludingUndefined)
return;
{
ASSERT(!inSparseMode());
- unsigned lengthNotIncludingUndefined = compactForSorting(exec->globalData());
- if (m_sparseValueMap) {
- throwOutOfMemoryError(exec);
- return;
- }
+ unsigned lengthNotIncludingUndefined = compactForSorting();
+ ASSERT(!m_sparseValueMap);
if (!lengthNotIncludingUndefined)
return;
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;
// 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;
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())
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<unsigned>(tree.abstractor().m_nodes.size()));
+ unsigned undefinedElementsThreshold = min(newestUsedVectorLength, newUsedVectorLength);
+ unsigned clearElementsThreshold = min(newestUsedVectorLength, usedVectorLength);
// 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 < 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);
}
callFrame->setArgument(i, get(exec, i));
}
-unsigned JSArray::compactForSorting(JSGlobalData& globalData)
+unsigned JSArray::compactForSorting()
{
ASSERT(!inSparseMode());
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();