aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/conversions.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/conversions.cc')
-rw-r--r--deps/v8/src/conversions.cc89
1 files changed, 48 insertions, 41 deletions
diff --git a/deps/v8/src/conversions.cc b/deps/v8/src/conversions.cc
index 82a521bd90..32de34c6a7 100644
--- a/deps/v8/src/conversions.cc
+++ b/deps/v8/src/conversions.cc
@@ -503,53 +503,60 @@ double StringToDouble(UnicodeCache* unicode_cache, Handle<String> string,
}
-bool IsNonArrayIndexInteger(String* string) {
- const int kBufferSize = 64;
- const int kUint32MaxChars = 11;
+bool IsSpecialIndex(UnicodeCache* unicode_cache, String* string) {
+ // Max length of canonical double: -X.XXXXXXXXXXXXXXXXX-eXXX
+ const int kBufferSize = 24;
+ const int length = string->length();
+ if (length == 0 || length > kBufferSize) return false;
uint16_t buffer[kBufferSize];
+ String::WriteToFlat(string, buffer, 0, length);
+ // If the first char is not a digit or a '-' or we can't match 'NaN' or
+ // '(-)Infinity', bailout immediately.
int offset = 0;
- const int length = string->length();
- if (length == 0) return false;
- // First iteration, check for minus, 0 followed by anything else, etc.
- int to = std::min(offset + kUint32MaxChars, length);
- {
- String::WriteToFlat(string, buffer, offset, to);
- bool negative = false;
- if (buffer[offset] == '-') {
- negative = true;
- ++offset;
- if (offset == to) return false; // Just '-' is bad.
- }
- if (buffer[offset] == '0') {
- return to == 2 && negative; // Match just '-0'.
- }
- // Process positive integers.
- if (!negative) {
- uint64_t acc = 0;
- for (; offset < to; ++offset) {
- uint64_t digit = buffer[offset] - '0';
- if (digit > 9) return false;
- acc = 10 * acc + digit;
- }
- // String is consumed. Evaluate what we have.
- if (offset == length) {
- return acc >
- static_cast<uint64_t>(std::numeric_limits<uint32_t>::max());
+ if (!IsDecimalDigit(buffer[0])) {
+ if (buffer[0] == '-') {
+ if (length == 1) return false; // Just '-' is bad.
+ if (!IsDecimalDigit(buffer[1])) {
+ if (buffer[1] == 'I' && length == 9) {
+ // Allow matching of '-Infinity' below.
+ } else {
+ return false;
+ }
}
+ offset++;
+ } else if (buffer[0] == 'I' && length == 8) {
+ // Allow matching of 'Infinity' below.
+ } else if (buffer[0] == 'N' && length == 3) {
+ // Match NaN.
+ return buffer[1] == 'a' && buffer[2] == 'N';
+ } else {
+ return false;
}
}
- // Consume rest of string. If we get here, we're way out of uint32_t bounds
- // or negative.
- int i = offset;
- while (true) {
- for (; offset < to; ++offset, ++i) {
- if (!IsDecimalDigit(buffer[i])) return false;
+ // Expected fast path: key is an integer.
+ static const int kRepresentableIntegerLength = 15; // (-)XXXXXXXXXXXXXXX
+ if (length - offset <= kRepresentableIntegerLength) {
+ const int initial_offset = offset;
+ bool matches = true;
+ for (; offset < length; offset++) {
+ matches &= IsDecimalDigit(buffer[offset]);
}
- if (offset == length) break;
- // Read next chunk.
- to = std::min(offset + kBufferSize, length);
- String::WriteToFlat(string, buffer, offset, to);
- i = 0;
+ if (matches) {
+ // Match 0 and -0.
+ if (buffer[initial_offset] == '0') return initial_offset == length - 1;
+ return true;
+ }
+ }
+ // Slow path: test DoubleToString(StringToDouble(string)) == string.
+ Vector<const uint16_t> vector(buffer, length);
+ double d = StringToDouble(unicode_cache, vector, NO_FLAGS);
+ if (std::isnan(d)) return false;
+ // Compute reverse string.
+ char reverse_buffer[kBufferSize + 1]; // Result will be /0 terminated.
+ Vector<char> reverse_vector(reverse_buffer, arraysize(reverse_buffer));
+ const char* reverse_string = DoubleToCString(d, reverse_vector);
+ for (int i = 0; i < length; ++i) {
+ if (static_cast<uint16_t>(reverse_string[i]) != buffer[i]) return false;
}
return true;
}