diff --git a/rhino/src/main/java/org/mozilla/javascript/NativeArray.java b/rhino/src/main/java/org/mozilla/javascript/NativeArray.java index 336ba1e4e5..0f03a2dce0 100644 --- a/rhino/src/main/java/org/mozilla/javascript/NativeArray.java +++ b/rhino/src/main/java/org/mozilla/javascript/NativeArray.java @@ -1349,7 +1349,8 @@ public int compare(final Object x, final Object y) { working[i] = getRawElem(o, i); } - Sorting.get().hybridSort(working, comparator); + // 'Arrays.sort' is guaranteed to be stable. + Arrays.sort(working, comparator); // copy the working array back into thisObj for (int i = 0; i < length; ++i) { diff --git a/rhino/src/main/java/org/mozilla/javascript/Sorting.java b/rhino/src/main/java/org/mozilla/javascript/Sorting.java deleted file mode 100644 index d63eaeb24c..0000000000 --- a/rhino/src/main/java/org/mozilla/javascript/Sorting.java +++ /dev/null @@ -1,129 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.javascript; - -import java.util.Comparator; - -public final class Sorting { - private static final int SMALLSORT = 16; - - private static final Sorting sorting = new Sorting(); - - private Sorting() {} - - public static Sorting get() { - return sorting; - } - - public void insertionSort(Object[] a, Comparator cmp) { - insertionSort(a, 0, a.length - 1, cmp); - } - - private static void insertionSort(Object[] a, int start, int end, Comparator cmp) { - int i = start; - while (i <= end) { - Object x = a[i]; - int j = i - 1; - while ((j >= start) && (cmp.compare(a[j], x) > 0)) { - a[j + 1] = a[j]; - j--; - } - a[j + 1] = x; - i++; - } - } - - /* - Hybrid sorting mechanism similar to Introsort by David Musser. Uses quicksort's - partitioning mechanism recursively until the resulting array is small or the - recursion is too deep, and then use insertion sort for the rest. - This is the same basic algorithm used by the GNU Standard C++ library. - */ - public void hybridSort(Object[] a, Comparator cmp) { - hybridSort(a, 0, a.length - 1, cmp, log2(a.length) * 2); - } - - private void hybridSort(Object[] a, int start, int end, Comparator cmp, int maxdepth) { - if (start < end) { - if ((maxdepth == 0) || ((end - start) <= SMALLSORT)) { - insertionSort(a, start, end, cmp); - } else { - int p = partition(a, start, end, cmp); - hybridSort(a, start, p, cmp, maxdepth - 1); - hybridSort(a, p + 1, end, cmp, maxdepth - 1); - } - } - } - - /* - Quicksort-style partitioning, using the Hoare partition scheme as coded by - Sedgewick at https://algs4.cs.princeton.edu/23quicksort/Quick.java.html. - Use the "median of three" method to determine which index to pivot on, and then - separate the array into two halves based on the pivot. - */ - private int partition(Object[] a, int start, int end, Comparator cmp) { - final int p = median(a, start, end, cmp); - final Object pivot = a[p]; - a[p] = a[start]; - a[start] = pivot; - - int i = start; - int j = end + 1; - - while (true) { - while (cmp.compare(a[++i], pivot) < 0) { - if (i == end) { - break; - } - } - while (cmp.compare(a[--j], pivot) >= 0) { - if (j == start) { - break; - } - } - if (i >= j) { - break; - } - swap(a, i, j); - } - - swap(a, start, j); - return j; - } - - private static void swap(Object[] a, int l, int h) { - final Object tmp = a[l]; - a[l] = a[h]; - a[h] = tmp; - } - - private static int log2(int n) { - return (int) (Math.log10(n) / Math.log10(2.0)); - } - - /* - Return the index of the median of three elements in the specified array range -- the - first, the last, and the one in the middle. - */ - public int median(final Object[] a, int start, int end, Comparator cmp) { - final int m = start + ((end - start) / 2); - int smallest = start; - - if (cmp.compare(a[smallest], a[m]) > 0) { - smallest = m; - } - if (cmp.compare(a[smallest], a[end]) > 0) { - smallest = end; - } - - if (smallest == start) { - return (cmp.compare(a[m], a[end]) < 0) ? m : end; - } - if (smallest == m) { - return (cmp.compare(a[start], a[end]) < 0) ? start : end; - } - return (cmp.compare(a[start], a[m]) < 0) ? start : m; - } -} diff --git a/rhino/src/test/java/org/mozilla/javascript/tests/SortingTest.java b/rhino/src/test/java/org/mozilla/javascript/tests/SortingTest.java deleted file mode 100644 index 34d4546c0d..0000000000 --- a/rhino/src/test/java/org/mozilla/javascript/tests/SortingTest.java +++ /dev/null @@ -1,195 +0,0 @@ -package org.mozilla.javascript.tests; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -import java.util.Arrays; -import java.util.Comparator; -import java.util.Random; -import org.junit.BeforeClass; -import org.junit.Test; -import org.mozilla.javascript.Sorting; - -public class SortingTest { - private static final int BIG_ARRAY = 100000; - private static final int ITERATIONS = 1; - - private static final Random rand = new Random(); - - private static Object[] bigRandom; - private static Sorting sorter; - - @BeforeClass - public static void init() { - bigRandom = randomArray(BIG_ARRAY); - sorter = Sorting.get(); - } - - private void insertionSort(Object[] expected) { - Object[] after = Arrays.copyOf(expected, expected.length); - sorter.insertionSort(after, new IntComparator()); - Arrays.sort(expected, new IntComparator()); - assertArrayEquals(expected, after); - } - - @Test - public void insertionSort() { - insertionSort(forwardArray(100)); - insertionSort(reverseArray(100)); - insertionSort(randomArray(100)); - insertionSort(sameArray(100)); - insertionSort(new Object[] {}); - insertionSort(randomArray(10000)); - } - - private void hybridSort(Object[] expected) { - Object[] after = Arrays.copyOf(expected, expected.length); - sorter.hybridSort(after, new IntComparator()); - Arrays.sort(expected, new IntComparator()); - assertArrayEquals(expected, after); - } - - @Test - public void hybridSort() { - hybridSort(randomArray(10)); - hybridSort(forwardArray(100)); - hybridSort(reverseArray(100)); - hybridSort(randomArray(100)); - hybridSort(sameArray(100)); - hybridSort(new Object[] {}); - hybridSort(randomArray(10000)); - } - - @Test - public void median() { - Object[] a = new Object[] {1, 2, 3, 4, 5}; - assertEquals(2, sorter.median(a, 0, 4, new IntComparator())); - a = new Object[] {5, 4, 3, 2, 1}; - assertEquals(2, sorter.median(a, 0, 4, new IntComparator())); - a = new Object[] {3, 4, 5, 2, 1}; - assertEquals(0, sorter.median(a, 0, 4, new IntComparator())); - a = new Object[] {4, 5, 1, 2, 3}; - assertEquals(4, sorter.median(a, 0, 4, new IntComparator())); - } - - /* - @Test - public void nenchInsertionRandom() - { - Object[] a = Arrays.copyOf(bigRandom, bigRandom.length); - Sorting.insertionSort(a, new IntComparator()); - } - */ - - @Test - public void benchRandomHybrid() { - for (int i = 0; i < ITERATIONS; i++) { - Object[] a = Arrays.copyOf(bigRandom, bigRandom.length); - sorter.hybridSort(a, new IntComparator()); - } - } - - @Test - public void benchRandomJavaUtil() { - for (int i = 0; i < ITERATIONS; i++) { - Object[] a = Arrays.copyOf(bigRandom, bigRandom.length); - Arrays.sort(a, new IntComparator()); - } - } - - /* - @Test - public void benchInsertionReverse() - { - for (int i = 0; i < ITERATIONS; i++) { - Object[] a = reverseArray(BIG_ARRAY); - Sorting.insertionSort(a, new IntComparator()); - } - } - */ - - @Test - public void benchReverseHybrid() { - for (int i = 0; i < ITERATIONS; i++) { - Object[] a = reverseArray(BIG_ARRAY); - sorter.hybridSort(a, new IntComparator()); - } - } - - @Test - public void benchReverseJavaUtil() { - for (int i = 0; i < ITERATIONS; i++) { - Object[] a = reverseArray(BIG_ARRAY); - Arrays.sort(a, new IntComparator()); - } - } - - @Test - public void benchSequentialInsertion() { - for (int i = 0; i < ITERATIONS; i++) { - Object[] a = forwardArray(BIG_ARRAY); - sorter.insertionSort(a, new IntComparator()); - } - } - - @Test - public void benchSequentialHybrid() { - for (int i = 0; i < ITERATIONS; i++) { - Object[] a = forwardArray(BIG_ARRAY); - sorter.hybridSort(a, new IntComparator()); - } - } - - @Test - public void benchSequentialJavaUtil() { - for (int i = 0; i < ITERATIONS; i++) { - Object[] a = forwardArray(BIG_ARRAY); - Arrays.sort(a, new IntComparator()); - } - } - - private static Integer[] forwardArray(int length) { - Integer[] a = new Integer[length]; - for (int i = 0; i < length; i++) { - a[i] = i; - } - return a; - } - - private static Integer[] reverseArray(int length) { - Integer[] a = new Integer[length]; - for (int i = 0; i < length; i++) { - a[i] = length - i - 1; - } - return a; - } - - private static Integer[] randomArray(int length) { - Integer[] a = new Integer[length]; - for (int i = 0; i < length; i++) { - a[i] = rand.nextInt(); - } - return a; - } - - private static Integer[] sameArray(int length) { - Integer[] a = new Integer[length]; - Arrays.fill(a, 1); - return a; - } - - private final class IntComparator implements Comparator { - @Override - public int compare(Object a, Object b) { - Integer ia = (Integer) a; - Integer ib = (Integer) b; - if (ia < ib) { - return -1; - } - if (ia > ib) { - return 1; - } - return 0; - } - } -} diff --git a/tests/testsrc/test262.properties b/tests/testsrc/test262.properties index d757219c6a..7842fa18e3 100644 --- a/tests/testsrc/test262.properties +++ b/tests/testsrc/test262.properties @@ -117,8 +117,6 @@ built-ins/Array 146/2670 (5.47%) prototype/slice/target-array-with-non-configurable-property.js prototype/some/15.4.4.17-5-1-s.js non-strict prototype/sort/S15.4.4.11_A8.js non-strict - prototype/sort/stability-2048-elements.js - prototype/sort/stability-513-elements.js prototype/splice/clamps-length-to-integer-limit.js prototype/splice/create-ctor-non-object.js prototype/splice/create-ctor-poisoned.js