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

Side by Side Diff: src/array.js

Issue 1706010: Unify treatment of sorting with and without custom comparator. (Closed)
Patch Set: Created 10 years, 8 months 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 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
637 637
638 // Return the deleted elements. 638 // Return the deleted elements.
639 return deleted_elements; 639 return deleted_elements;
640 } 640 }
641 641
642 642
643 function ArraySort(comparefn) { 643 function ArraySort(comparefn) {
644 // In-place QuickSort algorithm. 644 // In-place QuickSort algorithm.
645 // For short (length <= 22) arrays, insertion sort is used for efficiency. 645 // For short (length <= 22) arrays, insertion sort is used for efficiency.
646 646
647 var global_receiver; 647 if (!IS_FUNCTION(comparefn)) {
648 comparefn = function (x, y) {
649 if (x === y) return 0;
650 if (%_IsSmi(x) && %_IsSmi(y)) {
651 return %SmiLexicographicCompare(x, y);
652 }
653 x = ToString(x);
654 y = ToString(y);
655 if (x == y) return 0;
656 else return x < y ? -1 : 1;
657 };
658 }
659 var global_receiver = %GetGlobalReceiver();
648 660
649 function InsertionSortWithFunc(a, from, to) { 661 function InsertionSort(a, from, to) {
650 for (var i = from + 1; i < to; i++) { 662 for (var i = from + 1; i < to; i++) {
651 var element = a[i]; 663 var element = a[i];
652 for (var j = i - 1; j >= from; j--) { 664 for (var j = i - 1; j >= from; j--) {
653 var tmp = a[j]; 665 var tmp = a[j];
654 var order = %_CallFunction(global_receiver, tmp, element, comparefn); 666 var order = %_CallFunction(global_receiver, tmp, element, comparefn);
655 if (order > 0) { 667 if (order > 0) {
656 a[j + 1] = tmp; 668 a[j + 1] = tmp;
657 } else { 669 } else {
658 break;
659 }
660 }
661 a[j + 1] = element;
662 }
663 }
664
665 function QuickSortWithFunc(a, from, to) {
666 // Insertion sort is faster for short arrays.
667 if (to - from <= 22) {
668 InsertionSortWithFunc(a, from, to);
669 return;
670 }
671 var pivot_index = $floor($random() * (to - from)) + from;
672 var pivot = a[pivot_index];
673 // Issue 95: Keep the pivot element out of the comparisons to avoid
674 // infinite recursion if comparefn(pivot, pivot) != 0.
675 a[pivot_index] = a[from];
676 a[from] = pivot;
677 var low_end = from; // Upper bound of the elements lower than pivot.
678 var high_start = to; // Lower bound of the elements greater than pivot.
679 // From low_end to i are elements equal to pivot.
680 // From i to high_start are elements that haven't been compared yet.
681 for (var i = from + 1; i < high_start; ) {
682 var element = a[i];
683 var order = %_CallFunction(global_receiver, element, pivot, comparefn);
684 if (order < 0) {
685 a[i] = a[low_end];
686 a[low_end] = element;
687 i++;
688 low_end++;
689 } else if (order > 0) {
690 high_start--;
691 a[i] = a[high_start];
692 a[high_start] = element;
693 } else { // order == 0
694 i++;
695 }
696 }
697 QuickSortWithFunc(a, from, low_end);
698 QuickSortWithFunc(a, high_start, to);
699 }
700
701 function Compare(x,y) {
702 if (x === y) return 0;
703 if (%_IsSmi(x) && %_IsSmi(y)) {
704 return %SmiLexicographicCompare(x, y);
705 }
706 x = ToString(x);
707 y = ToString(y);
708 if (x == y) return 0;
709 else return x < y ? -1 : 1;
710 };
711
712 function InsertionSort(a, from, to) {
713 for (var i = from + 1; i < to; i++) {
714 var element = a[i];
715 for (var j = i - 1; j >= from; j--) {
716 var tmp = a[j];
717 var order = Compare(tmp, element);
718 if (order > 0) {
719 a[j + 1] = tmp;
720 } else {
721 break; 670 break;
722 } 671 }
723 } 672 }
724 a[j + 1] = element; 673 a[j + 1] = element;
725 } 674 }
726 } 675 }
727 676
728 function QuickSort(a, from, to) { 677 function QuickSort(a, from, to) {
729 // Insertion sort is faster for short arrays. 678 // Insertion sort is faster for short arrays.
730 if (to - from <= 22) { 679 if (to - from <= 22) {
731 InsertionSort(a, from, to); 680 InsertionSort(a, from, to);
732 return; 681 return;
733 } 682 }
734 var pivot_index = $floor($random() * (to - from)) + from; 683 var pivot_index = $floor($random() * (to - from)) + from;
735 var pivot = a[pivot_index]; 684 var pivot = a[pivot_index];
736 // Issue 95: Keep the pivot element out of the comparisons to avoid 685 // Issue 95: Keep the pivot element out of the comparisons to avoid
737 // infinite recursion if comparefn(pivot, pivot) != 0. 686 // infinite recursion if comparefn(pivot, pivot) != 0.
738 a[pivot_index] = a[from]; 687 a[pivot_index] = a[from];
739 a[from] = pivot; 688 a[from] = pivot;
740 var low_end = from; // Upper bound of the elements lower than pivot. 689 var low_end = from; // Upper bound of the elements lower than pivot.
741 var high_start = to; // Lower bound of the elements greater than pivot. 690 var high_start = to; // Lower bound of the elements greater than pivot.
742 // From low_end to i are elements equal to pivot. 691 // From low_end to i are elements equal to pivot.
743 // From i to high_start are elements that haven't been compared yet. 692 // From i to high_start are elements that haven't been compared yet.
744 for (var i = from + 1; i < high_start; ) { 693 for (var i = from + 1; i < high_start; ) {
745 var element = a[i]; 694 var element = a[i];
746 var order = Compare(element, pivot); 695 var order = %_CallFunction(global_receiver, element, pivot, comparefn);
747 if (order < 0) { 696 if (order < 0) {
748 a[i] = a[low_end]; 697 a[i] = a[low_end];
749 a[low_end] = element; 698 a[low_end] = element;
750 i++; 699 i++;
751 low_end++; 700 low_end++;
752 } else if (order > 0) { 701 } else if (order > 0) {
753 high_start--; 702 high_start--;
754 a[i] = a[high_start]; 703 a[i] = a[high_start];
755 a[high_start] = element; 704 a[high_start] = element;
756 } else { // order == 0 705 } else { // order == 0
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 } 845 }
897 846
898 var num_non_undefined = %RemoveArrayHoles(this, length); 847 var num_non_undefined = %RemoveArrayHoles(this, length);
899 if (num_non_undefined == -1) { 848 if (num_non_undefined == -1) {
900 // There were indexed accessors in the array. Move array holes and 849 // There were indexed accessors in the array. Move array holes and
901 // undefineds to the end using a Javascript function that is safe 850 // undefineds to the end using a Javascript function that is safe
902 // in the presence of accessors. 851 // in the presence of accessors.
903 num_non_undefined = SafeRemoveArrayHoles(this); 852 num_non_undefined = SafeRemoveArrayHoles(this);
904 } 853 }
905 854
906 if(IS_FUNCTION(comparefn)) { 855 QuickSort(this, 0, num_non_undefined);
907 global_receiver = %GetGlobalReceiver();
908 QuickSortWithFunc(this, 0, num_non_undefined);
909 } else {
910 QuickSort(this, 0, num_non_undefined);
911 }
912 856
913 if (!is_array && (num_non_undefined + 1 < max_prototype_element)) { 857 if (!is_array && (num_non_undefined + 1 < max_prototype_element)) {
914 // For compatibility with JSC, we shadow any elements in the prototype 858 // For compatibility with JSC, we shadow any elements in the prototype
915 // chain that has become exposed by sort moving a hole to its position. 859 // chain that has become exposed by sort moving a hole to its position.
916 ShadowPrototypeElements(this, num_non_undefined, max_prototype_element); 860 ShadowPrototypeElements(this, num_non_undefined, max_prototype_element);
917 } 861 }
918 862
919 return this; 863 return this;
920 } 864 }
921 865
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
1177 "lastIndexOf", getFunction("lastIndexOf", ArrayLastIndexOf, 1), 1121 "lastIndexOf", getFunction("lastIndexOf", ArrayLastIndexOf, 1),
1178 "reduce", getFunction("reduce", ArrayReduce, 1), 1122 "reduce", getFunction("reduce", ArrayReduce, 1),
1179 "reduceRight", getFunction("reduceRight", ArrayReduceRight, 1) 1123 "reduceRight", getFunction("reduceRight", ArrayReduceRight, 1)
1180 )); 1124 ));
1181 1125
1182 %FinishArrayPrototypeSetup($Array.prototype); 1126 %FinishArrayPrototypeSetup($Array.prototype);
1183 } 1127 }
1184 1128
1185 1129
1186 SetupArray(); 1130 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