Chromium Code Reviews| 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 |