Changeset 130102 in webkit
- Timestamp:
- Oct 1, 2012, 5:14:33 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r130100 r130102 1 2012-10-01 Filip Pizlo <fpizlo@apple.com> 2 3 Address a FIXME in JSArray::sort 4 https://bugs.webkit.org/show_bug.cgi?id=98080 5 <rdar://problem/12407844> 6 7 Reviewed by Oliver Hunt. 8 9 * fast/js/jsc-test-list: 10 * fast/js/script-tests/sort-with-side-effecting-comparisons.js: Added. 11 * fast/js/sort-with-side-effecting-comparisons-expected.txt: Added. 12 * fast/js/sort-with-side-effecting-comparisons.html: Added. 13 1 14 2012-10-01 Roger Fong <roger_fong@apple.com> 2 15 -
trunk/LayoutTests/fast/js/jsc-test-list
r129948 r130102 298 298 fast/js/sort-randomly 299 299 fast/js/sort-stability 300 fast/js/sort-with-side-effecting-comparisons 300 301 fast/js/sparse-array 301 302 fast/js/stack-overflow-arrity-catch -
trunk/Source/JavaScriptCore/ChangeLog
r130014 r130102 1 2012-10-01 Filip Pizlo <fpizlo@apple.com> 2 3 Address a FIXME in JSArray::sort 4 https://bugs.webkit.org/show_bug.cgi?id=98080 5 <rdar://problem/12407844> 6 7 Reviewed by Oliver Hunt. 8 9 Get rid of fast sorting of sparse maps. I don't know that it's broken but I do know that we don't 10 have coverage for it. Then also address the FIXME in JSArray::sort regarding side-effecting 11 compare functions. 12 13 * runtime/ArrayPrototype.cpp: 14 (JSC::arrayProtoFuncSort): 15 * runtime/JSArray.cpp: 16 (JSC::JSArray::sortNumeric): 17 (JSC::JSArray::sort): 18 (JSC::JSArray::compactForSorting): 19 * runtime/JSArray.h: 20 (JSArray): 21 * runtime/JSObject.h: 22 (JSC::JSObject::hasSparseMap): 23 (JSObject): 24 1 25 2012-10-01 Jonathan Liu <net147@gmail.com> 2 26 -
trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
r129676 r130102 656 656 CallType callType = getCallData(function, callData); 657 657 658 if (thisObj->classInfo() == &JSArray::s_info && !asArray(thisObj)-> inSparseIndexingMode() && !shouldUseSlowPut(thisObj->structure()->indexingType())) {658 if (thisObj->classInfo() == &JSArray::s_info && !asArray(thisObj)->hasSparseMap() && !shouldUseSlowPut(thisObj->structure()->indexingType())) { 659 659 if (isNumericCompareFunction(exec, callType, callData)) 660 660 asArray(thisObj)->sortNumeric(exec, function, callType, callData); -
trunk/Source/JavaScriptCore/runtime/JSArray.cpp
r129676 r130102 602 602 603 603 case ArrayWithArrayStorage: { 604 unsigned lengthNotIncludingUndefined = compactForSorting( exec->globalData());604 unsigned lengthNotIncludingUndefined = compactForSorting(); 605 605 ArrayStorage* storage = m_butterfly->arrayStorage(); 606 607 if (storage->m_sparseMap.get()) { 608 throwOutOfMemoryError(exec); 609 return; 610 } 606 607 ASSERT(!storage->m_sparseMap); 611 608 612 609 if (!lengthNotIncludingUndefined) … … 647 644 648 645 case ArrayWithArrayStorage: { 649 unsigned lengthNotIncludingUndefined = compactForSorting( exec->globalData());646 unsigned lengthNotIncludingUndefined = compactForSorting(); 650 647 ArrayStorage* storage = m_butterfly->arrayStorage(); 651 if (storage->m_sparseMap.get()) { 652 throwOutOfMemoryError(exec); 653 return; 654 } 648 ASSERT(!storage->m_sparseMap); 655 649 656 650 if (!lengthNotIncludingUndefined) … … 812 806 813 807 case ArrayWithArrayStorage: { 814 ArrayStorage* storage = m_butterfly->arrayStorage();815 816 808 // FIXME: This ignores exceptions raised in the compare function or in toNumber. 817 809 818 810 // The maximum tree depth is compiled in - but the caller is clearly up to no good 819 811 // if a larger array is passed. 820 ASSERT( storage->length() <= static_cast<unsigned>(std::numeric_limits<int>::max()));821 if ( storage->length() > static_cast<unsigned>(std::numeric_limits<int>::max()))812 ASSERT(arrayStorage()->length() <= static_cast<unsigned>(std::numeric_limits<int>::max())); 813 if (arrayStorage()->length() > static_cast<unsigned>(std::numeric_limits<int>::max())) 822 814 return; 823 815 824 unsigned usedVectorLength = min(storage->length(), storage->vectorLength()); 825 unsigned nodeCount = usedVectorLength + (storage->m_sparseMap ? storage->m_sparseMap->size() : 0); 816 unsigned usedVectorLength = min(arrayStorage()->length(), arrayStorage()->vectorLength()); 817 ASSERT(!arrayStorage()->m_sparseMap); 818 unsigned nodeCount = usedVectorLength; 826 819 827 820 if (!nodeCount) … … 851 844 // Iterate over the array, ignoring missing values, counting undefined ones, and inserting all other ones into the tree. 852 845 for (; numDefined < usedVectorLength; ++numDefined) { 853 JSValue v = storage->m_vector[numDefined].get(); 846 if (numDefined > arrayStorage()->vectorLength()) 847 break; 848 JSValue v = arrayStorage()->m_vector[numDefined].get(); 854 849 if (!v || v.isUndefined()) 855 850 break; … … 858 853 } 859 854 for (unsigned i = numDefined; i < usedVectorLength; ++i) { 860 JSValue v = storage->m_vector[i].get(); 855 if (i > arrayStorage()->vectorLength()) 856 break; 857 JSValue v = arrayStorage()->m_vector[i].get(); 861 858 if (v) { 862 859 if (v.isUndefined()) … … 872 869 unsigned newUsedVectorLength = numDefined + numUndefined; 873 870 874 if (SparseArrayValueMap* map = storage->m_sparseMap.get()) { 875 newUsedVectorLength += map->size(); 876 if (newUsedVectorLength > storage->vectorLength()) { 877 // Check that it is possible to allocate an array large enough to hold all the entries. 878 if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(exec->globalData(), newUsedVectorLength)) { 879 throwOutOfMemoryError(exec); 880 return; 881 } 882 storage = m_butterfly->arrayStorage(); 883 } 884 885 SparseArrayValueMap::const_iterator end = map->end(); 886 for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) { 887 tree.abstractor().m_nodes[numDefined].value = it->second.getNonSparseMode(); 888 tree.insert(numDefined); 889 ++numDefined; 890 } 891 892 deallocateSparseIndexMap(); 893 } 894 895 ASSERT(tree.abstractor().m_nodes.size() >= numDefined); 896 897 // FIXME: If the compare function changed the length of the array, the following might be 898 // modifying the vector incorrectly. 871 ASSERT(!arrayStorage()->m_sparseMap); 872 873 // The array size may have changed. Figure out the new bounds. 874 unsigned newestUsedVectorLength = min(arrayStorage()->length(), arrayStorage()->vectorLength()); 875 876 unsigned elementsToExtractThreshold = min(min(newestUsedVectorLength, numDefined), static_cast<unsigned>(tree.abstractor().m_nodes.size())); 877 unsigned undefinedElementsThreshold = min(newestUsedVectorLength, newUsedVectorLength); 878 unsigned clearElementsThreshold = min(newestUsedVectorLength, usedVectorLength); 899 879 900 880 // Copy the values back into m_storage. … … 902 882 iter.start_iter_least(tree); 903 883 JSGlobalData& globalData = exec->globalData(); 904 for (unsigned i = 0; i < numDefined; ++i) {905 storage->m_vector[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value);884 for (unsigned i = 0; i < elementsToExtractThreshold; ++i) { 885 arrayStorage()->m_vector[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value); 906 886 ++iter; 907 887 } 908 888 909 889 // Put undefined values back in. 910 for (unsigned i = numDefined; i < newUsedVectorLength; ++i)911 storage->m_vector[i].setUndefined();912 890 for (unsigned i = elementsToExtractThreshold; i < undefinedElementsThreshold; ++i) 891 arrayStorage()->m_vector[i].setUndefined(); 892 913 893 // Ensure that unused values in the vector are zeroed out. 914 for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)915 storage->m_vector[i].clear();916 917 storage->m_numValuesInVector = newUsedVectorLength;918 894 for (unsigned i = undefinedElementsThreshold; i < clearElementsThreshold; ++i) 895 arrayStorage()->m_vector[i].clear(); 896 897 arrayStorage()->m_numValuesInVector = undefinedElementsThreshold; 898 919 899 return; 920 900 } … … 983 963 } 984 964 985 unsigned JSArray::compactForSorting( JSGlobalData& globalData)965 unsigned JSArray::compactForSorting() 986 966 { 987 967 ASSERT(!inSparseIndexingMode()); … … 1017 997 unsigned newUsedVectorLength = numDefined + numUndefined; 1018 998 1019 if (SparseArrayValueMap* map = storage->m_sparseMap.get()) { 1020 newUsedVectorLength += map->size(); 1021 if (newUsedVectorLength > storage->vectorLength()) { 1022 // Check that it is possible to allocate an array large enough to hold all the entries - if not, 1023 // exception is thrown by caller. 1024 if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(globalData, newUsedVectorLength)) 1025 return 0; 1026 1027 storage = m_butterfly->arrayStorage(); 1028 } 1029 1030 SparseArrayValueMap::const_iterator end = map->end(); 1031 for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) 1032 storage->m_vector[numDefined++].setWithoutWriteBarrier(it->second.getNonSparseMode()); 1033 1034 deallocateSparseIndexMap(); 1035 } 999 ASSERT(!storage->m_sparseMap); 1036 1000 1037 1001 for (unsigned i = numDefined; i < newUsedVectorLength; ++i) -
trunk/Source/JavaScriptCore/runtime/JSArray.h
r129676 r130102 104 104 bool unshiftCountSlowCase(JSGlobalData&, bool, unsigned); 105 105 106 unsigned compactForSorting( JSGlobalData&);106 unsigned compactForSorting(); 107 107 }; 108 108 -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r129691 r130102 328 328 } 329 329 330 bool hasSparseMap() 331 { 332 switch (structure()->indexingType()) { 333 case ALL_BLANK_INDEXING_TYPES: 334 return false; 335 case ALL_ARRAY_STORAGE_INDEXING_TYPES: 336 return m_butterfly->arrayStorage()->m_sparseMap; 337 default: 338 ASSERT_NOT_REACHED(); 339 return false; 340 } 341 } 342 330 343 bool inSparseIndexingMode() 331 344 {
Note:
See TracChangeset
for help on using the changeset viewer.