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

Side by Side Diff: src/conversions.cc

Issue 1038313004: fix special index parsing (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: NaN test Created 5 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 | « src/conversions.h ('k') | src/hydrogen.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <limits.h> 5 #include <limits.h>
6 #include <stdarg.h> 6 #include <stdarg.h>
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "src/v8.h" 9 #include "src/v8.h"
10 10
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 return StringToDouble(unicode_cache, flat.ToOneByteVector(), flags, 496 return StringToDouble(unicode_cache, flat.ToOneByteVector(), flags,
497 empty_string_val); 497 empty_string_val);
498 } else { 498 } else {
499 return StringToDouble(unicode_cache, flat.ToUC16Vector(), flags, 499 return StringToDouble(unicode_cache, flat.ToUC16Vector(), flags,
500 empty_string_val); 500 empty_string_val);
501 } 501 }
502 } 502 }
503 } 503 }
504 504
505 505
506 bool IsNonArrayIndexInteger(String* string) { 506 bool IsSpecialIndex(UnicodeCache* unicode_cache, String* string) {
507 const int kBufferSize = 64; 507 // Max length of canonical double: -X.XXXXXXXXXXXXXXXXX-eXXX
508 const int kUint32MaxChars = 11; 508 const int kBufferSize = 24;
509 const int length = string->length();
510 if (length == 0 || length > kBufferSize) return false;
509 uint16_t buffer[kBufferSize]; 511 uint16_t buffer[kBufferSize];
512 String::WriteToFlat(string, buffer, 0, length);
513 // If the first char is not a digit or a '-' or we can't match 'NaN' or
514 // '(-)Infinity', bailout immediately.
510 int offset = 0; 515 int offset = 0;
511 const int length = string->length(); 516 if (!IsDecimalDigit(buffer[0])) {
512 if (length == 0) return false; 517 if (buffer[0] == '-') {
513 // First iteration, check for minus, 0 followed by anything else, etc. 518 if (length == 1) return false; // Just '-' is bad.
514 int to = std::min(offset + kUint32MaxChars, length); 519 if (!IsDecimalDigit(buffer[1])) {
515 { 520 if (buffer[1] == 'I' && length == 9) {
516 String::WriteToFlat(string, buffer, offset, to); 521 // Allow matching of '-Infinity' below.
517 bool negative = false; 522 } else {
518 if (buffer[offset] == '-') { 523 return false;
519 negative = true; 524 }
520 ++offset;
521 if (offset == to) return false; // Just '-' is bad.
522 }
523 if (buffer[offset] == '0') {
524 return to == 2 && negative; // Match just '-0'.
525 }
526 // Process positive integers.
527 if (!negative) {
528 uint64_t acc = 0;
529 for (; offset < to; ++offset) {
530 uint64_t digit = buffer[offset] - '0';
531 if (digit > 9) return false;
532 acc = 10 * acc + digit;
533 } 525 }
534 // String is consumed. Evaluate what we have. 526 offset++;
535 if (offset == length) { 527 } else if (buffer[0] == 'I' && length == 8) {
536 return acc > 528 // Allow matching of 'Infinity' below.
537 static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()); 529 } else if (buffer[0] == 'N' && length == 3) {
538 } 530 // Match NaN.
531 return buffer[1] == 'a' && buffer[2] == 'N';
532 } else {
533 return false;
539 } 534 }
540 } 535 }
541 // Consume rest of string. If we get here, we're way out of uint32_t bounds 536 // Expected fast path: key is an integer.
542 // or negative. 537 static const int kRepresentableIntegerLength = 15; // (-)XXXXXXXXXXXXXXX
543 int i = offset; 538 if (length - offset <= kRepresentableIntegerLength) {
544 while (true) { 539 const int initial_offset = offset;
545 for (; offset < to; ++offset, ++i) { 540 bool matches = true;
546 if (!IsDecimalDigit(buffer[i])) return false; 541 for (; offset < length; offset++) {
542 matches &= IsDecimalDigit(buffer[offset]);
547 } 543 }
548 if (offset == length) break; 544 if (matches) {
549 // Read next chunk. 545 // Match 0 and -0.
550 to = std::min(offset + kBufferSize, length); 546 if (buffer[initial_offset] == '0') return initial_offset == length - 1;
551 String::WriteToFlat(string, buffer, offset, to); 547 return true;
552 i = 0; 548 }
549 }
550 // Slow path: test DoubleToString(StringToDouble(string)) == string.
551 Vector<const uint16_t> vector(buffer, length);
552 double d = StringToDouble(unicode_cache, vector, NO_FLAGS);
553 if (std::isnan(d)) return false;
554 // Compute reverse string.
555 char reverse_buffer[kBufferSize + 1]; // Result will be /0 terminated.
556 Vector<char> reverse_vector(reverse_buffer, arraysize(reverse_buffer));
557 const char* reverse_string = DoubleToCString(d, reverse_vector);
558 for (int i = 0; i < length; ++i) {
559 if (static_cast<uint16_t>(reverse_string[i]) != buffer[i]) return false;
553 } 560 }
554 return true; 561 return true;
555 } 562 }
556 } } // namespace v8::internal 563 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/conversions.h ('k') | src/hydrogen.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698