Index: src/runtime.cc |
=================================================================== |
--- src/runtime.cc (revision 8424) |
+++ src/runtime.cc (working copy) |
@@ -45,6 +45,7 @@ |
#include "json-parser.h" |
#include "liveedit.h" |
#include "liveobjectlist-inl.h" |
+#include "misc-intrinsics.h" |
#include "parser.h" |
#include "platform.h" |
#include "runtime-profiler.h" |
@@ -6647,7 +6648,7 @@ |
// If the integers are equal so are the string representations. |
if (x_value == y_value) return Smi::FromInt(EQUAL); |
- // If one of the integers are zero the normal integer order is the |
+ // If one of the integers is zero the normal integer order is the |
// same as the lexicographic order of the string representations. |
if (x_value == 0 || y_value == 0) return Smi::FromInt(x_value - y_value); |
@@ -6661,36 +6662,47 @@ |
y_value = -y_value; |
} |
- // Arrays for the individual characters of the two Smis. Smis are |
- // 31 bit integers and 10 decimal digits are therefore enough. |
- // TODO(isolates): maybe we should simply allocate 20 bytes on the stack. |
- int* x_elms = isolate->runtime_state()->smi_lexicographic_compare_x_elms(); |
- int* y_elms = isolate->runtime_state()->smi_lexicographic_compare_y_elms(); |
+ static const int powersOf10[] = { 1, 10, 100, 1000, 10*1000, 100*1000, |
Erik Corry
2011/06/25 11:12:03
This is a constant so it should be named as a cons
sra1
2011/06/25 19:31:33
Done.
|
+ 1000*1000, 10*1000*1000, 100*1000*1000, |
+ 1000*1000*1000 }; |
+ // If the integers have the same number of decimal digits they can be |
+ // compared directly as the numeric order is the same as the |
+ // lexicographic order. If one integer has fewer digits, it is scaled |
+ // by some power of 10 to have the same number of digits as the longer |
+ // integer. If the scaled integers are equal it means the shorter |
+ // integer comes first in the lexicographic order. |
- // Convert the integers to arrays of their decimal digits. |
- int x_index = 0; |
- int y_index = 0; |
- while (x_value > 0) { |
- x_elms[x_index++] = x_value % 10; |
+ // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 |
+ int x_log2 = IntegerLog2(x_value); |
+ int x_log10 = ((x_log2 + 1) * 1233) >> 12; |
+ x_log10 -= x_value < powersOf10[x_log10]; |
+ |
+ int y_log2 = IntegerLog2(y_value); |
+ int y_log10 = ((y_log2 + 1) * 1233) >> 12; |
+ y_log10 -= y_value < powersOf10[y_log10]; |
+ |
+ int tie = EQUAL; |
+ |
+ if (x_log10 < y_log10) { |
+ // X has fewer digits. We would like to simply scale up X but that |
+ // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would |
+ // be scaled up to 9_000_000_000. So we scale up by the next |
+ // smallest power and scale down Y to drop one digit. It is OK to |
+ // drop one digit from the longer integer since the final digit is |
+ // past the length of the shorter integer. |
+ x_value *= powersOf10[y_log10 - x_log10 - 1]; |
+ y_value /= 10; |
+ tie = LESS; |
+ } else if (y_log10 < x_log10) { |
+ y_value *= powersOf10[x_log10 - y_log10 - 1]; |
x_value /= 10; |
+ tie = GREATER; |
} |
- while (y_value > 0) { |
- y_elms[y_index++] = y_value % 10; |
- y_value /= 10; |
- } |
- // Loop through the arrays of decimal digits finding the first place |
- // where they differ. |
- while (--x_index >= 0 && --y_index >= 0) { |
- int diff = x_elms[x_index] - y_elms[y_index]; |
- if (diff != 0) return Smi::FromInt(diff); |
- } |
- |
- // If one array is a suffix of the other array, the longest array is |
- // the representation of the largest of the Smis in the |
- // lexicographic ordering. |
- return Smi::FromInt(x_index - y_index); |
+ if (x_value < y_value) return Smi::FromInt(LESS); |
+ if (x_value > y_value) return Smi::FromInt(GREATER); |
+ return Smi::FromInt(tie); |
} |