OLD | NEW |
---|---|
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
634 while (arguments_index < arguments_length) { | 634 while (arguments_index < arguments_length) { |
635 this[i++] = %_Arguments(arguments_index++); | 635 this[i++] = %_Arguments(arguments_index++); |
636 } | 636 } |
637 this.length = len - del_count + num_additional_args; | 637 this.length = len - del_count + num_additional_args; |
638 | 638 |
639 // Return the deleted elements. | 639 // Return the deleted elements. |
640 return deleted_elements; | 640 return deleted_elements; |
641 } | 641 } |
642 | 642 |
643 | 643 |
644 function InsertionSort(a, from, to, comparefn, global_receiver) { | |
645 for (var i = from + 1; i < to; i++) { | |
646 var element = a[i]; | |
647 for (var j = i - 1; j >= from; j--) { | |
648 var tmp = a[j]; | |
649 var order = %_CallFunction(global_receiver, tmp, element, comparefn); | |
650 if (order > 0) { | |
651 a[j + 1] = tmp; | |
652 } else { | |
653 break; | |
654 } | |
655 } | |
656 a[j + 1] = element; | |
657 } | |
Karl Klose
2010/12/17 09:55:37
Consider putting InsertionSort back into ArraySort
Lasse Reichstein
2010/12/17 10:04:22
Done.
It was an attempt at a micro-optimization, b
| |
658 } | |
659 | |
660 | |
644 function ArraySort(comparefn) { | 661 function ArraySort(comparefn) { |
645 // In-place QuickSort algorithm. | 662 // In-place QuickSort algorithm. |
646 // For short (length <= 22) arrays, insertion sort is used for efficiency. | 663 // For short (length <= 22) arrays, insertion sort is used for efficiency. |
647 | 664 |
648 if (!IS_FUNCTION(comparefn)) { | 665 if (!IS_FUNCTION(comparefn)) { |
649 comparefn = function (x, y) { | 666 comparefn = function (x, y) { |
650 if (x === y) return 0; | 667 if (x === y) return 0; |
651 if (%_IsSmi(x) && %_IsSmi(y)) { | 668 if (%_IsSmi(x) && %_IsSmi(y)) { |
652 return %SmiLexicographicCompare(x, y); | 669 return %SmiLexicographicCompare(x, y); |
653 } | 670 } |
654 x = ToString(x); | 671 x = ToString(x); |
655 y = ToString(y); | 672 y = ToString(y); |
656 if (x == y) return 0; | 673 if (x == y) return 0; |
657 else return x < y ? -1 : 1; | 674 else return x < y ? -1 : 1; |
658 }; | 675 }; |
659 } | 676 } |
660 var global_receiver = %GetGlobalReceiver(); | 677 var global_receiver = %GetGlobalReceiver(); |
661 | 678 |
662 function InsertionSort(a, from, to) { | |
663 for (var i = from + 1; i < to; i++) { | |
664 var element = a[i]; | |
665 for (var j = i - 1; j >= from; j--) { | |
666 var tmp = a[j]; | |
667 var order = %_CallFunction(global_receiver, tmp, element, comparefn); | |
668 if (order > 0) { | |
669 a[j + 1] = tmp; | |
670 } else { | |
671 break; | |
672 } | |
673 } | |
674 a[j + 1] = element; | |
675 } | |
676 } | |
677 | |
678 function QuickSort(a, from, to) { | 679 function QuickSort(a, from, to) { |
679 // Insertion sort is faster for short arrays. | 680 // Insertion sort is faster for short arrays. |
680 if (to - from <= 22) { | 681 if (to - from <= 13) { |
681 InsertionSort(a, from, to); | 682 InsertionSort(a, from, to, comparefn, global_receiver); |
682 return; | 683 return; |
683 } | 684 } |
684 var pivot_index = $floor($random() * (to - from)) + from; | 685 |
685 var pivot = a[pivot_index]; | 686 // Find a pivot as the median of first, last and middle element. |
686 // Issue 95: Keep the pivot element out of the comparisons to avoid | 687 var v0 = a[from]; |
687 // infinite recursion if comparefn(pivot, pivot) != 0. | 688 var v1 = a[to - 1]; |
688 %_SwapElements(a, from, pivot_index); | 689 var middle_index = from + ((to - from) >> 1); |
689 var low_end = from; // Upper bound of the elements lower than pivot. | 690 var v2 = a[middle_index]; |
690 var high_start = to; // Lower bound of the elements greater than pivot. | 691 var c01 = comparefn(v0, v1); |
692 if (c01 > 0) { | |
693 // v1 < v0, so swap them. | |
694 var tmp = v0; | |
695 v0 = v1; | |
696 v1 = tmp; | |
697 } // v0 <= v1. | |
698 var c02 = comparefn(v0, v2); | |
699 if (c02 >= 0) { | |
700 // v2 <= v0 <= v1. | |
701 var tmp = v0; | |
702 v0 = v2; | |
703 v2 = v1; | |
704 v1 = tmp; | |
705 } else { | |
706 // v0 <= v1 && v0 < v2 | |
707 var c12 = comparefn(v1, v2); | |
708 if (c12 > 0) { | |
709 // v0 <= v2 < v1 | |
710 var tmp = v1; | |
711 v1 = v2; | |
712 v2 = tmp; | |
713 } | |
714 } | |
715 // v0 <= v1 <= v2 | |
716 a[from] = v0; | |
717 a[to - 1] = v2; | |
718 var pivot = v1; | |
719 var low_end = from + 1; // Upper bound of the elements lower than pivot. | |
720 var high_start = to - 1; // Lower bound of the elements greater than pivot. | |
721 a[middle_index] = a[low_end]; | |
722 a[low_end] = pivot; | |
723 | |
691 // From low_end to i are elements equal to pivot. | 724 // From low_end to i are elements equal to pivot. |
692 // From i to high_start are elements that haven't been compared yet. | 725 // From i to high_start are elements that haven't been compared yet. |
693 for (var i = from + 1; i < high_start; ) { | 726 for (var i = low_end + 1; i < high_start; ) { |
694 var element = a[i]; | 727 var element = a[i]; |
695 var order = %_CallFunction(global_receiver, element, pivot, comparefn); | 728 var order = %_CallFunction(global_receiver, element, pivot, comparefn); |
696 if (order < 0) { | 729 if (order < 0) { |
697 %_SwapElements(a, i, low_end); | 730 %_SwapElements(a, i, low_end); |
698 i++; | 731 i++; |
699 low_end++; | 732 low_end++; |
700 } else if (order > 0) { | 733 } else if (order > 0) { |
701 high_start--; | 734 high_start--; |
702 %_SwapElements(a, i, high_start); | 735 %_SwapElements(a, i, high_start); |
703 } else { // order == 0 | 736 } else { // order == 0 |
704 i++; | 737 i++; |
705 } | 738 } |
706 } | 739 } |
707 QuickSort(a, from, low_end); | 740 QuickSort(a, from, low_end); |
708 QuickSort(a, high_start, to); | 741 QuickSort(a, high_start, to); |
709 } | 742 } |
710 | 743 |
711 // Copies elements in the range 0..length from obj's prototype chain | 744 // Copies elements in the range 0..length from obj's prototype chain |
712 // to obj itself, if obj has holes. Returns one more than the maximal index | 745 // to obj itself, if obj has holes. Returns one more than the maximal index |
713 // of a prototype property. | 746 // of a prototype property. |
Karl Klose
2010/12/17 09:55:37
Not in that change, but we should have consistent
Lasse Reichstein
2010/12/17 10:04:22
Done.
| |
714 function CopyFromPrototype(obj, length) { | 747 function CopyFromPrototype(obj, length) { |
715 var max = 0; | 748 var max = 0; |
716 for (var proto = obj.__proto__; proto; proto = proto.__proto__) { | 749 for (var proto = obj.__proto__; proto; proto = proto.__proto__) { |
717 var indices = %GetArrayKeys(proto, length); | 750 var indices = %GetArrayKeys(proto, length); |
718 if (indices.length > 0) { | 751 if (indices.length > 0) { |
719 if (indices[0] == -1) { | 752 if (indices[0] == -1) { |
720 // It's an interval. | 753 // It's an interval. |
721 var proto_length = indices[1]; | 754 var proto_length = indices[1]; |
722 for (var i = 0; i < proto_length; i++) { | 755 for (var i = 0; i < proto_length; i++) { |
723 if (!obj.hasOwnProperty(i) && proto.hasOwnProperty(i)) { | 756 if (!obj.hasOwnProperty(i) && proto.hasOwnProperty(i)) { |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1172 "lastIndexOf", getFunction("lastIndexOf", ArrayLastIndexOf, 1), | 1205 "lastIndexOf", getFunction("lastIndexOf", ArrayLastIndexOf, 1), |
1173 "reduce", getFunction("reduce", ArrayReduce, 1), | 1206 "reduce", getFunction("reduce", ArrayReduce, 1), |
1174 "reduceRight", getFunction("reduceRight", ArrayReduceRight, 1) | 1207 "reduceRight", getFunction("reduceRight", ArrayReduceRight, 1) |
1175 )); | 1208 )); |
1176 | 1209 |
1177 %FinishArrayPrototypeSetup($Array.prototype); | 1210 %FinishArrayPrototypeSetup($Array.prototype); |
1178 } | 1211 } |
1179 | 1212 |
1180 | 1213 |
1181 SetupArray(); | 1214 SetupArray(); |
OLD | NEW |