Changeset 20974 in webkit


Ignore:
Timestamp:
Apr 20, 2007 3:20:15 PM (17 years ago)
Author:
mjs
Message:

Reviewed by Darin.


  • <rdar://problem/5149915> use mergesort when possible, since it leads to fewer compares (2% JS iBench speedup)
  • kjs/array_object.cpp: (ArrayInstance::sort): Use mergesort(3) on platforms that have it, since it tends to do fewer compares than qsort; but avoid it very on large arrays since it uses extra memory. Also added comments identifying possibly even better sorting algorithms for sort by string value and sort by compare function.
  • kjs/config.h:
Location:
trunk/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r20973 r20974  
     12007-04-20  Maciej Stachowiak  <mjs@apple.com>
     2
     3        Reviewed by Darin.
     4       
     5        - <rdar://problem/5149915> use mergesort when possible, since it leads to fewer compares (2% JS iBench speedup)
     6
     7        * kjs/array_object.cpp:
     8        (ArrayInstance::sort): Use mergesort(3) on platforms that have it, since it tends
     9        to do fewer compares than qsort; but avoid it very on large arrays since it uses extra
     10        memory. Also added comments identifying possibly even better sorting algorithms
     11        for sort by string value and sort by compare function.
     12        * kjs/config.h:
     13
    1142007-04-20  Maciej Stachowiak  <mjs@apple.com>
    215
  • trunk/JavaScriptCore/kjs/array_object.cpp

    r20949 r20974  
    303303void ArrayInstance::sort(ExecState* exec)
    304304{
    305     int lengthNotIncludingUndefined = pushUndefinedObjectsToEnd(exec);
    306 
     305    size_t lengthNotIncludingUndefined = pushUndefinedObjectsToEnd(exec);
     306     
    307307    ExecState* oldExec = execForCompareByStringForQSort;
    308308    execForCompareByStringForQSort = exec;
     309#if HAVE(MERGESORT)
     310    // mergesort usually does fewer compares, so it is actually faster than qsort for JS sorts.
     311    // however, becuase it requires extra copies of the storage buffer, don't use it for very
     312    // large arrays
     313    // FIXME: for sorting by string value, the fastest thing would actually be to convert all the
     314    // values to string once up front, and then use a radix sort. That would be O(N) rather than
     315    // O(N log N).
     316    if (lengthNotIncludingUndefined < sparseArrayCutoff) {
     317        JSValue** storageCopy = static_cast<JSValue**>(fastMalloc(capacity * sizeof(JSValue*)));
     318        memcpy(storageCopy, storage, capacity * sizeof(JSValue*));
     319        mergesort(storageCopy, lengthNotIncludingUndefined, sizeof(JSValue *), compareByStringForQSort);
     320        storage = storageCopy;
     321        fastFree(storage);
     322        execForCompareByStringForQSort = oldExec;
     323        return;
     324    }
     325#endif
     326
    309327    qsort(storage, lengthNotIncludingUndefined, sizeof(JSValue*), compareByStringForQSort);
    310328    execForCompareByStringForQSort = oldExec;
     
    352370void ArrayInstance::sort(ExecState* exec, JSObject* compareFunction)
    353371{
    354     int lengthNotIncludingUndefined = pushUndefinedObjectsToEnd(exec);
     372    size_t lengthNotIncludingUndefined = pushUndefinedObjectsToEnd(exec);
    355373
    356374    CompareWithCompareFunctionArguments* oldArgs = compareWithCompareFunctionArguments;
    357375    CompareWithCompareFunctionArguments args(exec, compareFunction);
    358376    compareWithCompareFunctionArguments = &args;
     377#if HAVE(MERGESORT)
     378    // mergesort usually does fewer compares, so it is actually faster than qsort for JS sorts.
     379    // however, becuase it requires extra copies of the storage buffer, don't use it for very
     380    // large arrays
     381    // FIXME: a tree sort using a perfectly balanced tree (e.g. an AVL tree) could do an even
     382    // better job of minimizing compares
     383    if (lengthNotIncludingUndefined < sparseArrayCutoff) {
     384        JSValue** storageCopy = static_cast<JSValue**>(fastMalloc(capacity * sizeof(JSValue*)));
     385        memcpy(storageCopy, storage, capacity * sizeof(JSValue*));
     386        mergesort(storageCopy, lengthNotIncludingUndefined, sizeof(JSValue *), compareWithCompareFunctionForQSort);
     387        storage = storageCopy;
     388        compareWithCompareFunctionArguments = oldArgs;
     389        return;
     390    }
     391#endif
    359392    qsort(storage, lengthNotIncludingUndefined, sizeof(JSValue*), compareWithCompareFunctionForQSort);
    360393    compareWithCompareFunctionArguments = oldArgs;
  • trunk/JavaScriptCore/kjs/config.h

    r20229 r20974  
    3232#define HAVE_FUNC_ISNAN 1
    3333#define HAVE_MMAP 1
     34#define HAVE_MERGESORT 1
    3435#define HAVE_SBRK 1
    3536#define HAVE_STRINGS_H 1
Note: See TracChangeset for help on using the changeset viewer.