Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(763)

Side by Side Diff: src/array.js

Issue 5962003: Change quicksort pivot from random to median-of-three. (Closed)
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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();
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698