@@ -306,157 +306,180 @@ function includes(searchElement /*, fromIndex*/)
306306 return false ;
307307}
308308
309- function sort ( comparator )
309+ @globalPrivate
310+ function sortMin ( a , b )
310311{
311312 "use strict" ;
312313
313- function min ( a , b )
314- {
315- return a < b ? a : b ;
316- }
314+ return a < b ? a : b ;
315+ }
317316
318- function stringComparator ( a , b )
319- {
320- var aString = a . string ;
321- var bString = b . string ;
317+ @ globalPrivate
318+ function sortStringComparator ( a , b )
319+ {
320+ "use strict" ;
322321
323- if ( aString === bString )
324- return 0 ;
322+ var aString = a . string ;
323+ var bString = b . string ;
325324
326- return aString > bString ? 1 : - 1 ;
327- }
325+ if ( aString === bString )
326+ return 0 ;
328327
329- function compact ( receiver , receiverLength , compacted , isStringSort )
330- {
331- var undefinedCount = 0 ;
332- var compactedIndex = 0 ;
333-
334- for ( var i = 0 ; i < receiverLength ; ++ i ) {
335- if ( i in receiver ) {
336- var value = receiver [ i ] ;
337- if ( value === @undefined )
338- ++ undefinedCount ;
339- else {
340- @putByValDirect ( compacted , compactedIndex ,
341- isStringSort ? { string : @toString ( value ) , value } : value ) ;
342- ++ compactedIndex ;
343- }
328+ return aString > bString ? 1 : - 1 ;
329+ }
330+
331+ @globalPrivate
332+ function sortCompact ( receiver , receiverLength , compacted , isStringSort )
333+ {
334+ "use strict" ;
335+
336+ var undefinedCount = 0 ;
337+ var compactedIndex = 0 ;
338+
339+ for ( var i = 0 ; i < receiverLength ; ++ i ) {
340+ if ( i in receiver ) {
341+ var value = receiver [ i ] ;
342+ if ( value === @undefined )
343+ ++ undefinedCount ;
344+ else {
345+ @putByValDirect ( compacted , compactedIndex ,
346+ isStringSort ? { string : @toString ( value ) , value } : value ) ;
347+ ++ compactedIndex ;
344348 }
345349 }
346-
347- return undefinedCount ;
348350 }
349351
352+ return undefinedCount ;
353+ }
354+
355+ @globalPrivate
356+ function sortCommit ( receiver , receiverLength , sorted , undefinedCount )
357+ {
358+ "use strict" ;
359+
350360 // Move undefineds and holes to the end of an array. Result is [values..., undefineds..., holes...].
351- function commit ( receiver , receiverLength , sorted , undefinedCount )
352- {
353- @assert ( @isJSArray ( sorted ) ) ;
354- var sortedLength = sorted . length ;
355- @assert ( sortedLength + undefinedCount <= receiverLength ) ;
356-
357- var i = 0 ;
358- if ( @isJSArray ( receiver ) && sortedLength >= 64 && typeof sorted [ 0 ] !== "number" ) { // heuristic
359- @appendMemcpy ( receiver , sorted , 0 ) ;
360- i = sortedLength ;
361- } else {
362- for ( ; i < sortedLength ; ++ i )
363- receiver [ i ] = sorted [ i ] ;
364- }
365361
366- for ( ; i < sortedLength + undefinedCount ; ++ i )
367- receiver [ i ] = @undefined ;
362+ @assert ( @isJSArray ( sorted ) ) ;
363+ var sortedLength = sorted . length ;
364+ @assert ( sortedLength + undefinedCount <= receiverLength ) ;
368365
369- for ( ; i < receiverLength ; ++ i )
370- delete receiver [ i ] ;
366+ var i = 0 ;
367+ if ( @isJSArray ( receiver ) && sortedLength >= 64 && typeof sorted [ 0 ] !== "number" ) { // heuristic
368+ @appendMemcpy ( receiver , sorted , 0 ) ;
369+ i = sortedLength ;
370+ } else {
371+ for ( ; i < sortedLength ; ++ i )
372+ receiver [ i ] = sorted [ i ] ;
371373 }
372374
373- function merge ( dst , src , srcIndex , srcEnd , width , comparator )
374- {
375- var left = srcIndex ;
376- var leftEnd = min ( left + width , srcEnd ) ;
377- var right = leftEnd ;
378- var rightEnd = min ( right + width , srcEnd ) ;
379-
380- for ( var dstIndex = left ; dstIndex < rightEnd ; ++ dstIndex ) {
381- if ( right < rightEnd ) {
382- if ( left >= leftEnd ) {
383- @putByValDirect ( dst , dstIndex , src [ right ] ) ;
384- ++ right ;
385- continue ;
386- }
375+ for ( ; i < sortedLength + undefinedCount ; ++ i )
376+ receiver [ i ] = @undefined ;
387377
388- // See https://bugs.webkit.org/show_bug.cgi?id=47825 on boolean special-casing
389- var comparisonResult = comparator ( src [ right ] , src [ left ] ) ;
390- if ( comparisonResult === false || comparisonResult < 0 ) {
391- @putByValDirect ( dst , dstIndex , src [ right ] ) ;
392- ++ right ;
393- continue ;
394- }
378+ for ( ; i < receiverLength ; ++ i )
379+ delete receiver [ i ] ;
380+ }
381+
382+
383+ @globalPrivate
384+ function sortMerge ( dst , src , srcIndex , srcEnd , width , comparator )
385+ {
386+ "use strict" ;
387+
388+ var left = srcIndex ;
389+ var leftEnd = @sortMin ( left + width , srcEnd ) ;
390+ var right = leftEnd ;
391+ var rightEnd = @sortMin ( right + width , srcEnd ) ;
392+
393+ for ( var dstIndex = left ; dstIndex < rightEnd ; ++ dstIndex ) {
394+ if ( right < rightEnd ) {
395+ if ( left >= leftEnd ) {
396+ @putByValDirect ( dst , dstIndex , src [ right ] ) ;
397+ ++ right ;
398+ continue ;
399+ }
395400
401+ // See https://bugs.webkit.org/show_bug.cgi?id=47825 on boolean special-casing
402+ var comparisonResult = comparator ( src [ right ] , src [ left ] ) ;
403+ if ( comparisonResult === false || comparisonResult < 0 ) {
404+ @putByValDirect ( dst , dstIndex , src [ right ] ) ;
405+ ++ right ;
406+ continue ;
396407 }
397408
398- @putByValDirect ( dst , dstIndex , src [ left ] ) ;
399- ++ left ;
400409 }
410+
411+ @putByValDirect ( dst , dstIndex , src [ left ] ) ;
412+ ++ left ;
401413 }
414+ }
402415
403- function mergeSort ( array , comparator )
404- {
405- var valueCount = array . length ;
406- var buffer = @newArrayWithSize ( valueCount ) ;
407-
408- var dst = buffer ;
409- var src = array ;
410- for ( var width = 1 ; width < valueCount ; width *= 2 ) {
411- for ( var srcIndex = 0 ; srcIndex < valueCount ; srcIndex += 2 * width )
412- merge ( dst , src , srcIndex , valueCount , width , comparator ) ;
413-
414- var tmp = src ;
415- src = dst ;
416- dst = tmp ;
417- }
416+ @globalPrivate
417+ function sortMergeSort ( array , comparator )
418+ {
419+ "use strict" ;
420+
421+ var valueCount = array . length ;
422+ var buffer = @newArrayWithSize ( valueCount ) ;
423+
424+ var dst = buffer ;
425+ var src = array ;
426+ for ( var width = 1 ; width < valueCount ; width *= 2 ) {
427+ for ( var srcIndex = 0 ; srcIndex < valueCount ; srcIndex += 2 * width )
428+ @sortMerge ( dst , src , srcIndex , valueCount , width , comparator ) ;
418429
419- return src ;
430+ var tmp = src ;
431+ src = dst ;
432+ dst = tmp ;
420433 }
421434
422- function bucketSort ( array , dst , bucket , depth )
423- {
424- if ( bucket . length < 32 || depth > 32 ) {
425- var sorted = mergeSort ( bucket , stringComparator ) ;
426- for ( var i = 0 ; i < sorted . length ; ++ i ) {
427- @putByValDirect ( array , dst , sorted [ i ] . value ) ;
428- ++ dst ;
429- }
430- return dst ;
431- }
435+ return src ;
436+ }
432437
433- var buckets = [ ] ;
434- for ( var i = 0 ; i < bucket . length ; ++ i ) {
435- var entry = bucket [ i ] ;
436- var string = entry . string ;
437- if ( string . length == depth ) {
438- @putByValDirect ( array , dst , entry . value ) ;
439- ++ dst ;
440- continue ;
441- }
438+ @globalPrivate
439+ function sortBucketSort ( array , dst , bucket , depth )
440+ {
441+ "use strict" ;
442442
443- var c = string . @charCodeAt ( depth ) ;
444- var cBucket = buckets [ c ] ;
445- if ( cBucket )
446- @putByValDirect ( cBucket , cBucket . length , entry ) ;
447- else
448- @putByValDirect ( buckets , c , [ entry ] ) ;
443+ if ( bucket . length < 32 || depth > 32 ) {
444+ var sorted = @sortMergeSort ( bucket , @sortStringComparator ) ;
445+ for ( var i = 0 ; i < sorted . length ; ++ i ) {
446+ @putByValDirect ( array , dst , sorted [ i ] . value ) ;
447+ ++ dst ;
449448 }
449+ return dst ;
450+ }
450451
451- for ( var i = 0 ; i < buckets . length ; ++ i ) {
452- if ( ! buckets [ i ] )
453- continue ;
454- dst = bucketSort ( array , dst , buckets [ i ] , depth + 1 ) ;
452+ var buckets = [ ] ;
453+ for ( var i = 0 ; i < bucket . length ; ++ i ) {
454+ var entry = bucket [ i ] ;
455+ var string = entry . string ;
456+ if ( string . length == depth ) {
457+ @putByValDirect ( array , dst , entry . value ) ;
458+ ++ dst ;
459+ continue ;
455460 }
456461
457- return dst ;
462+ var c = string . @charCodeAt ( depth ) ;
463+ var cBucket = buckets [ c ] ;
464+ if ( cBucket )
465+ @putByValDirect ( cBucket , cBucket . length , entry ) ;
466+ else
467+ @putByValDirect ( buckets , c , [ entry ] ) ;
458468 }
459469
470+ for ( var i = 0 ; i < buckets . length ; ++ i ) {
471+ if ( ! buckets [ i ] )
472+ continue ;
473+ dst = @sortBucketSort ( array , dst , buckets [ i ] , depth + 1 ) ;
474+ }
475+
476+ return dst ;
477+ }
478+
479+ function sort ( comparator )
480+ {
481+ "use strict" ;
482+
460483 var isStringSort = false ;
461484 if ( comparator === @undefined )
462485 isStringSort = true ;
@@ -473,15 +496,15 @@ function sort(comparator)
473496
474497 var compacted = [ ] ;
475498 var sorted = null ;
476- var undefinedCount = compact ( receiver , receiverLength , compacted , isStringSort ) ;
499+ var undefinedCount = @ sortCompact ( receiver , receiverLength , compacted , isStringSort ) ;
477500
478501 if ( isStringSort ) {
479502 sorted = @newArrayWithSize ( compacted . length ) ;
480- bucketSort ( sorted , 0 , compacted , 0 ) ;
503+ @ sortBucketSort ( sorted , 0 , compacted , 0 ) ;
481504 } else
482- sorted = mergeSort ( compacted , comparator ) ;
505+ sorted = @ sortMergeSort ( compacted , comparator ) ;
483506
484- commit ( receiver , receiverLength , sorted , undefinedCount ) ;
507+ @ sortCommit ( receiver , receiverLength , sorted , undefinedCount ) ;
485508 return receiver ;
486509}
487510
0 commit comments