]> git.saurik.com Git - apple/javascriptcore.git/commitdiff
JavaScriptCore-1097.3.3.tar.gz ios-601 v1097.3.3
authorApple <opensource@apple.com>
Tue, 23 Oct 2012 00:18:28 +0000 (00:18 +0000)
committerApple <opensource@apple.com>
Tue, 23 Oct 2012 00:18:28 +0000 (00:18 +0000)
runtime/ArrayPrototype.cpp
runtime/JSArray.cpp
runtime/JSArray.h

index 6df58b773e90a478accd50e754aede1ced258650..62f845d34ff1fcd8ee658501cec5447070d90930 100644 (file)
@@ -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)
index aa1b8b7d981cfc652f6921cd47982848b83f99a0..adcb8fc33c54ecf6387e211caa8186a52dc34a18 100644 (file)
@@ -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<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);
 }
@@ -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();
index 17c7f3ed719ff13d4b6e7bf74beb119d71c01b41..06675a075ae7a02f61e55ec8d297983f4101f573 100644 (file)
@@ -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);