OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 27 matching lines...) Expand all Loading... |
38 #include "cpu.h" | 38 #include "cpu.h" |
39 #include "dateparser-inl.h" | 39 #include "dateparser-inl.h" |
40 #include "debug.h" | 40 #include "debug.h" |
41 #include "deoptimizer.h" | 41 #include "deoptimizer.h" |
42 #include "execution.h" | 42 #include "execution.h" |
43 #include "global-handles.h" | 43 #include "global-handles.h" |
44 #include "jsregexp.h" | 44 #include "jsregexp.h" |
45 #include "json-parser.h" | 45 #include "json-parser.h" |
46 #include "liveedit.h" | 46 #include "liveedit.h" |
47 #include "liveobjectlist-inl.h" | 47 #include "liveobjectlist-inl.h" |
| 48 #include "misc-intrinsics.h" |
48 #include "parser.h" | 49 #include "parser.h" |
49 #include "platform.h" | 50 #include "platform.h" |
50 #include "runtime-profiler.h" | 51 #include "runtime-profiler.h" |
51 #include "runtime.h" | 52 #include "runtime.h" |
52 #include "scopeinfo.h" | 53 #include "scopeinfo.h" |
53 #include "smart-pointer.h" | 54 #include "smart-pointer.h" |
54 #include "string-search.h" | 55 #include "string-search.h" |
55 #include "stub-cache.h" | 56 #include "stub-cache.h" |
56 #include "v8threads.h" | 57 #include "v8threads.h" |
57 #include "vm-state-inl.h" | 58 #include "vm-state-inl.h" |
(...skipping 6582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6640 | 6641 |
6641 // Extract the integer values from the Smis. | 6642 // Extract the integer values from the Smis. |
6642 CONVERT_CHECKED(Smi, x, args[0]); | 6643 CONVERT_CHECKED(Smi, x, args[0]); |
6643 CONVERT_CHECKED(Smi, y, args[1]); | 6644 CONVERT_CHECKED(Smi, y, args[1]); |
6644 int x_value = x->value(); | 6645 int x_value = x->value(); |
6645 int y_value = y->value(); | 6646 int y_value = y->value(); |
6646 | 6647 |
6647 // If the integers are equal so are the string representations. | 6648 // If the integers are equal so are the string representations. |
6648 if (x_value == y_value) return Smi::FromInt(EQUAL); | 6649 if (x_value == y_value) return Smi::FromInt(EQUAL); |
6649 | 6650 |
6650 // If one of the integers are zero the normal integer order is the | 6651 // If one of the integers is zero the normal integer order is the |
6651 // same as the lexicographic order of the string representations. | 6652 // same as the lexicographic order of the string representations. |
6652 if (x_value == 0 || y_value == 0) return Smi::FromInt(x_value - y_value); | 6653 if (x_value == 0 || y_value == 0) |
| 6654 return Smi::FromInt(x_value < y_value ? LESS : GREATER); |
6653 | 6655 |
6654 // If only one of the integers is negative the negative number is | 6656 // If only one of the integers is negative the negative number is |
6655 // smallest because the char code of '-' is less than the char code | 6657 // smallest because the char code of '-' is less than the char code |
6656 // of any digit. Otherwise, we make both values positive. | 6658 // of any digit. Otherwise, we make both values positive. |
| 6659 |
| 6660 // Use unsigned values otherwise the logic is incorrect for -MIN_INT on |
| 6661 // architectures using 32-bit Smis. |
| 6662 uint32_t x_scaled = x_value; |
| 6663 uint32_t y_scaled = y_value; |
6657 if (x_value < 0 || y_value < 0) { | 6664 if (x_value < 0 || y_value < 0) { |
6658 if (y_value >= 0) return Smi::FromInt(LESS); | 6665 if (y_value >= 0) return Smi::FromInt(LESS); |
6659 if (x_value >= 0) return Smi::FromInt(GREATER); | 6666 if (x_value >= 0) return Smi::FromInt(GREATER); |
6660 x_value = -x_value; | 6667 x_scaled = -x_value; |
6661 y_value = -y_value; | 6668 y_scaled = -y_value; |
6662 } | 6669 } |
6663 | 6670 |
6664 // Arrays for the individual characters of the two Smis. Smis are | 6671 static const uint32_t kPowersOf10[] = { |
6665 // 31 bit integers and 10 decimal digits are therefore enough. | 6672 1, 10, 100, 1000, 10*1000, 100*1000, |
6666 // TODO(isolates): maybe we should simply allocate 20 bytes on the stack. | 6673 1000*1000, 10*1000*1000, 100*1000*1000, |
6667 int* x_elms = isolate->runtime_state()->smi_lexicographic_compare_x_elms(); | 6674 1000*1000*1000 |
6668 int* y_elms = isolate->runtime_state()->smi_lexicographic_compare_y_elms(); | 6675 }; |
6669 | 6676 |
| 6677 // If the integers have the same number of decimal digits they can be |
| 6678 // compared directly as the numeric order is the same as the |
| 6679 // lexicographic order. If one integer has fewer digits, it is scaled |
| 6680 // by some power of 10 to have the same number of digits as the longer |
| 6681 // integer. If the scaled integers are equal it means the shorter |
| 6682 // integer comes first in the lexicographic order. |
6670 | 6683 |
6671 // Convert the integers to arrays of their decimal digits. | 6684 // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 |
6672 int x_index = 0; | 6685 int x_log2 = IntegerLog2(x_scaled); |
6673 int y_index = 0; | 6686 int x_log10 = ((x_log2 + 1) * 1233) >> 12; |
6674 while (x_value > 0) { | 6687 x_log10 -= x_scaled < kPowersOf10[x_log10]; |
6675 x_elms[x_index++] = x_value % 10; | 6688 |
6676 x_value /= 10; | 6689 int y_log2 = IntegerLog2(y_scaled); |
6677 } | 6690 int y_log10 = ((y_log2 + 1) * 1233) >> 12; |
6678 while (y_value > 0) { | 6691 y_log10 -= y_scaled < kPowersOf10[y_log10]; |
6679 y_elms[y_index++] = y_value % 10; | 6692 |
6680 y_value /= 10; | 6693 int tie = EQUAL; |
| 6694 |
| 6695 if (x_log10 < y_log10) { |
| 6696 // X has fewer digits. We would like to simply scale up X but that |
| 6697 // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would |
| 6698 // be scaled up to 9_000_000_000. So we scale up by the next |
| 6699 // smallest power and scale down Y to drop one digit. It is OK to |
| 6700 // drop one digit from the longer integer since the final digit is |
| 6701 // past the length of the shorter integer. |
| 6702 x_scaled *= kPowersOf10[y_log10 - x_log10 - 1]; |
| 6703 y_scaled /= 10; |
| 6704 tie = LESS; |
| 6705 } else if (y_log10 < x_log10) { |
| 6706 y_scaled *= kPowersOf10[x_log10 - y_log10 - 1]; |
| 6707 x_scaled /= 10; |
| 6708 tie = GREATER; |
6681 } | 6709 } |
6682 | 6710 |
6683 // Loop through the arrays of decimal digits finding the first place | 6711 if (x_scaled < y_scaled) return Smi::FromInt(LESS); |
6684 // where they differ. | 6712 if (x_scaled > y_scaled) return Smi::FromInt(GREATER); |
6685 while (--x_index >= 0 && --y_index >= 0) { | 6713 return Smi::FromInt(tie); |
6686 int diff = x_elms[x_index] - y_elms[y_index]; | |
6687 if (diff != 0) return Smi::FromInt(diff); | |
6688 } | |
6689 | |
6690 // If one array is a suffix of the other array, the longest array is | |
6691 // the representation of the largest of the Smis in the | |
6692 // lexicographic ordering. | |
6693 return Smi::FromInt(x_index - y_index); | |
6694 } | 6714 } |
6695 | 6715 |
6696 | 6716 |
6697 static Object* StringInputBufferCompare(RuntimeState* state, | 6717 static Object* StringInputBufferCompare(RuntimeState* state, |
6698 String* x, | 6718 String* x, |
6699 String* y) { | 6719 String* y) { |
6700 StringInputBuffer& bufx = *state->string_input_buffer_compare_bufx(); | 6720 StringInputBuffer& bufx = *state->string_input_buffer_compare_bufx(); |
6701 StringInputBuffer& bufy = *state->string_input_buffer_compare_bufy(); | 6721 StringInputBuffer& bufy = *state->string_input_buffer_compare_bufy(); |
6702 bufx.Reset(x); | 6722 bufx.Reset(x); |
6703 bufy.Reset(y); | 6723 bufy.Reset(y); |
(...skipping 5779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12483 } else { | 12503 } else { |
12484 // Handle last resort GC and make sure to allow future allocations | 12504 // Handle last resort GC and make sure to allow future allocations |
12485 // to grow the heap without causing GCs (if possible). | 12505 // to grow the heap without causing GCs (if possible). |
12486 isolate->counters()->gc_last_resort_from_js()->Increment(); | 12506 isolate->counters()->gc_last_resort_from_js()->Increment(); |
12487 isolate->heap()->CollectAllGarbage(false); | 12507 isolate->heap()->CollectAllGarbage(false); |
12488 } | 12508 } |
12489 } | 12509 } |
12490 | 12510 |
12491 | 12511 |
12492 } } // namespace v8::internal | 12512 } } // namespace v8::internal |
OLD | NEW |