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 3 // found in the LICENSE file. 4 5 #include "src/conversions.h" 6 7 #include <limits.h> 8 #include <stdarg.h> 9 #include <cmath> 10 11 #include "src/allocation.h" 12 #include "src/assert-scope.h" 13 #include "src/char-predicates-inl.h" 14 #include "src/dtoa.h" 15 #include "src/handles.h" 16 #include "src/heap/factory.h" 17 #include "src/objects-inl.h" 18 #include "src/objects/bigint.h" 19 #include "src/strtod.h" 20 #include "src/unicode-cache-inl.h" 21 #include "src/utils.h" 22 23 #if defined(_STLP_VENDOR_CSTD) 24 // STLPort doesn't import fpclassify into the std namespace. 25 #define FPCLASSIFY_NAMESPACE 26 #else 27 #define FPCLASSIFY_NAMESPACE std 28 #endif 29 30 namespace v8 { 31 namespace internal { 32 33 namespace { 34 35 inline double JunkStringValue() { 36 return bit_cast<double, uint64_t>(kQuietNaNMask); 37 } 38 39 inline double SignedZero(bool negative) { 40 return negative ? uint64_to_double(Double::kSignMask) : 0.0; 41 } 42 43 inline bool isDigit(int x, int radix) { 44 return (x >= '0' && x <= '9' && x < '0' + radix) || 45 (radix > 10 && x >= 'a' && x < 'a' + radix - 10) || 46 (radix > 10 && x >= 'A' && x < 'A' + radix - 10); 47 } 48 49 inline bool isBinaryDigit(int x) { return x == '0' || x == '1'; } 50 51 template <class Iterator, class EndMark> 52 bool SubStringEquals(Iterator* current, EndMark end, const char* substring) { 53 DCHECK(**current == *substring); 54 for (substring++; *substring != '\0'; substring++) { 55 ++*current; 56 if (*current == end || **current != *substring) return false; 57 } 58 ++*current; 59 return true; 60 } 61 62 // Returns true if a nonspace character has been found and false if the 63 // end was been reached before finding a nonspace character. 64 template <class Iterator, class EndMark> 65 inline bool AdvanceToNonspace(UnicodeCache* unicode_cache, Iterator* current, 66 EndMark end) { 67 while (*current != end) { 68 if (!unicode_cache->IsWhiteSpaceOrLineTerminator(**current)) return true; 69 ++*current; 70 } 71 return false; 72 } 73 74 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. 75 template <int radix_log_2, class Iterator, class EndMark> 76 double InternalStringToIntDouble(UnicodeCache* unicode_cache, Iterator current, 77 EndMark end, bool negative, 78 bool allow_trailing_junk) { 79 DCHECK(current != end); 80 81 // Skip leading 0s. 82 while (*current == '0') { 83 ++current; 84 if (current == end) return SignedZero(negative); 85 } 86 87 int64_t number = 0; 88 int exponent = 0; 89 const int radix = (1 << radix_log_2); 90 91 int lim_0 = '0' + (radix < 10 ? radix : 10); 92 int lim_a = 'a' + (radix - 10); 93 int lim_A = 'A' + (radix - 10); 94 95 do { 96 int digit; 97 if (*current >= '0' && *current < lim_0) { 98 digit = static_cast<char>(*current) - '0'; 99 } else if (*current >= 'a' && *current < lim_a) { 100 digit = static_cast<char>(*current) - 'a' + 10; 101 } else if (*current >= 'A' && *current < lim_A) { 102 digit = static_cast<char>(*current) - 'A' + 10; 103 } else { 104 if (allow_trailing_junk || 105 !AdvanceToNonspace(unicode_cache, ¤t, end)) { 106 break; 107 } else { 108 return JunkStringValue(); 109 } 110 } 111 112 number = number * radix + digit; 113 int overflow = static_cast<int>(number >> 53); 114 if (overflow != 0) { 115 // Overflow occurred. Need to determine which direction to round the 116 // result. 117 int overflow_bits_count = 1; 118 while (overflow > 1) { 119 overflow_bits_count++; 120 overflow >>= 1; 121 } 122 123 int dropped_bits_mask = ((1 << overflow_bits_count) - 1); 124 int dropped_bits = static_cast<int>(number) & dropped_bits_mask; 125 number >>= overflow_bits_count; 126 exponent = overflow_bits_count; 127 128 bool zero_tail = true; 129 while (true) { 130 ++current; 131 if (current == end || !isDigit(*current, radix)) break; 132 zero_tail = zero_tail && *current == '0'; 133 exponent += radix_log_2; 134 } 135 136 if (!allow_trailing_junk && 137 AdvanceToNonspace(unicode_cache, ¤t, end)) { 138 return JunkStringValue(); 139 } 140 141 int middle_value = (1 << (overflow_bits_count - 1)); 142 if (dropped_bits > middle_value) { 143 number++; // Rounding up. 144 } else if (dropped_bits == middle_value) { 145 // Rounding to even to consistency with decimals: half-way case rounds 146 // up if significant part is odd and down otherwise. 147 if ((number & 1) != 0 || !zero_tail) { 148 number++; // Rounding up. 149 } 150 } 151 152 // Rounding up may cause overflow. 153 if ((number & (static_cast<int64_t>(1) << 53)) != 0) { 154 exponent++; 155 number >>= 1; 156 } 157 break; 158 } 159 ++current; 160 } while (current != end); 161 162 DCHECK(number < ((int64_t)1 << 53)); 163 DCHECK(static_cast<int64_t>(static_cast<double>(number)) == number); 164 165 if (exponent == 0) { 166 if (negative) { 167 if (number == 0) return -0.0; 168 number = -number; 169 } 170 return static_cast<double>(number); 171 } 172 173 DCHECK_NE(number, 0); 174 return std::ldexp(static_cast<double>(negative ? -number : number), exponent); 175 } 176 177 // ES6 18.2.5 parseInt(string, radix) (with NumberParseIntHelper subclass); 178 // and BigInt parsing cases from https://tc39.github.io/proposal-bigint/ 179 // (with StringToBigIntHelper subclass). 180 class StringToIntHelper { 181 public: 182 StringToIntHelper(Isolate* isolate, Handle<String> subject, int radix) 183 : isolate_(isolate), subject_(subject), radix_(radix) { 184 DCHECK(subject->IsFlat()); 185 } 186 187 // Used for the StringToBigInt operation. 188 StringToIntHelper(Isolate* isolate, Handle<String> subject) 189 : isolate_(isolate), subject_(subject) { 190 DCHECK(subject->IsFlat()); 191 } 192 193 // Used for parsing BigInt literals, where the input is a Zone-allocated 194 // buffer of one-byte digits, along with an optional radix prefix. 195 StringToIntHelper(Isolate* isolate, const uint8_t* subject, int length) 196 : isolate_(isolate), raw_one_byte_subject_(subject), length_(length) {} 197 virtual ~StringToIntHelper() {} 198 199 protected: 200 // Subclasses must implement these: 201 virtual void AllocateResult() = 0; 202 virtual void ResultMultiplyAdd(uint32_t multiplier, uint32_t part) = 0; 203 204 // Subclasses must call this to do all the work. 205 void ParseInt(); 206 207 // Subclasses may override this. 208 virtual void HandleSpecialCases() {} 209 210 // Subclass constructors should call these for configuration before calling 211 // ParseInt(). 212 void set_allow_binary_and_octal_prefixes() { 213 allow_binary_and_octal_prefixes_ = true; 214 } 215 void set_disallow_trailing_junk() { allow_trailing_junk_ = false; } 216 217 bool IsOneByte() const { 218 return raw_one_byte_subject_ != nullptr || 219 subject_->IsOneByteRepresentationUnderneath(); 220 } 221 222 Vector<const uint8_t> GetOneByteVector() { 223 if (raw_one_byte_subject_ != nullptr) { 224 return Vector<const uint8_t>(raw_one_byte_subject_, length_); 225 } 226 return subject_->GetFlatContent().ToOneByteVector(); 227 } 228 229 Vector<const uc16> GetTwoByteVector() { 230 return subject_->GetFlatContent().ToUC16Vector(); 231 } 232 233 // Subclasses get access to internal state: 234 enum State { kRunning, kError, kJunk, kEmpty, kZero, kDone }; 235 236 enum class Sign { kNegative, kPositive, kNone }; 237 238 Isolate* isolate() { return isolate_; } 239 int radix() { return radix_; } 240 int cursor() { return cursor_; } 241 int length() { return length_; } 242 bool negative() { return sign_ == Sign::kNegative; } 243 Sign sign() { return sign_; } 244 State state() { return state_; } 245 void set_state(State state) { state_ = state; } 246 247 private: 248 template <class Char> 249 void DetectRadixInternal(Char current, int length); 250 template <class Char> 251 void ParseInternal(Char start); 252 253 Isolate* isolate_; 254 Handle<String> subject_; 255 const uint8_t* raw_one_byte_subject_ = nullptr; 256 int radix_ = 0; 257 int cursor_ = 0; 258 int length_ = 0; 259 Sign sign_ = Sign::kNone; 260 bool leading_zero_ = false; 261 bool allow_binary_and_octal_prefixes_ = false; 262 bool allow_trailing_junk_ = true; 263 State state_ = kRunning; 264 }; 265 266 void StringToIntHelper::ParseInt() { 267 { 268 DisallowHeapAllocation no_gc; 269 if (IsOneByte()) { 270 Vector<const uint8_t> vector = GetOneByteVector(); 271 DetectRadixInternal(vector.start(), vector.length()); 272 } else { 273 Vector<const uc16> vector = GetTwoByteVector(); 274 DetectRadixInternal(vector.start(), vector.length()); 275 } 276 } 277 if (state_ != kRunning) return; 278 AllocateResult(); 279 HandleSpecialCases(); 280 if (state_ != kRunning) return; 281 { 282 DisallowHeapAllocation no_gc; 283 if (IsOneByte()) { 284 Vector<const uint8_t> vector = GetOneByteVector(); 285 DCHECK_EQ(length_, vector.length()); 286 ParseInternal(vector.start()); 287 } else { 288 Vector<const uc16> vector = GetTwoByteVector(); 289 DCHECK_EQ(length_, vector.length()); 290 ParseInternal(vector.start()); 291 } 292 } 293 DCHECK_NE(state_, kRunning); 294 } 295 296 template <class Char> 297 void StringToIntHelper::DetectRadixInternal(Char current, int length) { 298 Char start = current; 299 length_ = length; 300 Char end = start + length; 301 UnicodeCache* unicode_cache = isolate_->unicode_cache(); 302 303 if (!AdvanceToNonspace(unicode_cache, ¤t, end)) { 304 return set_state(kEmpty); 305 } 306 307 if (*current == '+') { 308 // Ignore leading sign; skip following spaces. 309 ++current; 310 if (current == end) { 311 return set_state(kJunk); 312 } 313 sign_ = Sign::kPositive; 314 } else if (*current == '-') { 315 ++current; 316 if (current == end) { 317 return set_state(kJunk); 318 } 319 sign_ = Sign::kNegative; 320 } 321 322 if (radix_ == 0) { 323 // Radix detection. 324 radix_ = 10; 325 if (*current == '0') { 326 ++current; 327 if (current == end) return set_state(kZero); 328 if (*current == 'x' || *current == 'X') { 329 radix_ = 16; 330 ++current; 331 if (current == end) return set_state(kJunk); 332 } else if (allow_binary_and_octal_prefixes_ && 333 (*current == 'o' || *current == 'O')) { 334 radix_ = 8; 335 ++current; 336 if (current == end) return set_state(kJunk); 337 } else if (allow_binary_and_octal_prefixes_ && 338 (*current == 'b' || *current == 'B')) { 339 radix_ = 2; 340 ++current; 341 if (current == end) return set_state(kJunk); 342 } else { 343 leading_zero_ = true; 344 } 345 } 346 } else if (radix_ == 16) { 347 if (*current == '0') { 348 // Allow "0x" prefix. 349 ++current; 350 if (current == end) return set_state(kZero); 351 if (*current == 'x' || *current == 'X') { 352 ++current; 353 if (current == end) return set_state(kJunk); 354 } else { 355 leading_zero_ = true; 356 } 357 } 358 } 359 // Skip leading zeros. 360 while (*current == '0') { 361 leading_zero_ = true; 362 ++current; 363 if (current == end) return set_state(kZero); 364 } 365 366 if (!leading_zero_ && !isDigit(*current, radix_)) { 367 return set_state(kJunk); 368 } 369 370 DCHECK(radix_ >= 2 && radix_ <= 36); 371 STATIC_ASSERT(String::kMaxLength <= INT_MAX); 372 cursor_ = static_cast<int>(current - start); 373 } 374 375 template <class Char> 376 void StringToIntHelper::ParseInternal(Char start) { 377 Char current = start + cursor_; 378 Char end = start + length_; 379 380 // The following code causes accumulating rounding error for numbers greater 381 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10, 382 // 16, or 32, then mathInt may be an implementation-dependent approximation to 383 // the mathematical integer value" (15.1.2.2). 384 385 int lim_0 = '0' + (radix_ < 10 ? radix_ : 10); 386 int lim_a = 'a' + (radix_ - 10); 387 int lim_A = 'A' + (radix_ - 10); 388 389 // NOTE: The code for computing the value may seem a bit complex at 390 // first glance. It is structured to use 32-bit multiply-and-add 391 // loops as long as possible to avoid losing precision. 392 393 bool done = false; 394 do { 395 // Parse the longest part of the string starting at {current} 396 // possible while keeping the multiplier, and thus the part 397 // itself, within 32 bits. 398 uint32_t part = 0, multiplier = 1; 399 while (true) { 400 uint32_t d; 401 if (*current >= '0' && *current < lim_0) { 402 d = *current - '0'; 403 } else if (*current >= 'a' && *current < lim_a) { 404 d = *current - 'a' + 10; 405 } else if (*current >= 'A' && *current < lim_A) { 406 d = *current - 'A' + 10; 407 } else { 408 done = true; 409 break; 410 } 411 412 // Update the value of the part as long as the multiplier fits 413 // in 32 bits. When we can't guarantee that the next iteration 414 // will not overflow the multiplier, we stop parsing the part 415 // by leaving the loop. 416 const uint32_t kMaximumMultiplier = 0xFFFFFFFFU / 36; 417 uint32_t m = multiplier * static_cast<uint32_t>(radix_); 418 if (m > kMaximumMultiplier) break; 419 part = part * radix_ + d; 420 multiplier = m; 421 DCHECK(multiplier > part); 422 423 ++current; 424 if (current == end) { 425 done = true; 426 break; 427 } 428 } 429 430 // Update the value and skip the part in the string. 431 ResultMultiplyAdd(multiplier, part); 432 } while (!done); 433 434 if (!allow_trailing_junk_ && 435 AdvanceToNonspace(isolate_->unicode_cache(), ¤t, end)) { 436 return set_state(kJunk); 437 } 438 439 return set_state(kDone); 440 } 441 442 class NumberParseIntHelper : public StringToIntHelper { 443 public: 444 NumberParseIntHelper(Isolate* isolate, Handle<String> string, int radix) 445 : StringToIntHelper(isolate, string, radix) {} 446 447 double GetResult() { 448 ParseInt(); 449 switch (state()) { 450 case kJunk: 451 case kEmpty: 452 return JunkStringValue(); 453 case kZero: 454 return SignedZero(negative()); 455 case kDone: 456 return negative() ? -result_ : result_; 457 case kError: 458 case kRunning: 459 break; 460 } 461 UNREACHABLE(); 462 } 463 464 protected: 465 virtual void AllocateResult() {} 466 virtual void ResultMultiplyAdd(uint32_t multiplier, uint32_t part) { 467 result_ = result_ * multiplier + part; 468 } 469 470 private: 471 virtual void HandleSpecialCases() { 472 bool is_power_of_two = base::bits::IsPowerOfTwo(radix()); 473 if (!is_power_of_two && radix() != 10) return; 474 DisallowHeapAllocation no_gc; 475 if (IsOneByte()) { 476 Vector<const uint8_t> vector = GetOneByteVector(); 477 DCHECK_EQ(length(), vector.length()); 478 result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.start()) 479 : HandleBaseTenCase(vector.start()); 480 } else { 481 Vector<const uc16> vector = GetTwoByteVector(); 482 DCHECK_EQ(length(), vector.length()); 483 result_ = is_power_of_two ? HandlePowerOfTwoCase(vector.start()) 484 : HandleBaseTenCase(vector.start()); 485 } 486 set_state(kDone); 487 } 488 489 template <class Char> 490 double HandlePowerOfTwoCase(Char start) { 491 Char current = start + cursor(); 492 Char end = start + length(); 493 UnicodeCache* unicode_cache = isolate()->unicode_cache(); 494 const bool allow_trailing_junk = true; 495 // GetResult() will take care of the sign bit, so ignore it for now. 496 const bool negative = false; 497 switch (radix()) { 498 case 2: 499 return InternalStringToIntDouble<1>(unicode_cache, current, end, 500 negative, allow_trailing_junk); 501 case 4: 502 return InternalStringToIntDouble<2>(unicode_cache, current, end, 503 negative, allow_trailing_junk); 504 case 8: 505 return InternalStringToIntDouble<3>(unicode_cache, current, end, 506 negative, allow_trailing_junk); 507 508 case 16: 509 return InternalStringToIntDouble<4>(unicode_cache, current, end, 510 negative, allow_trailing_junk); 511 512 case 32: 513 return InternalStringToIntDouble<5>(unicode_cache, current, end, 514 negative, allow_trailing_junk); 515 default: 516 UNREACHABLE(); 517 } 518 } 519 520 template <class Char> 521 double HandleBaseTenCase(Char start) { 522 // Parsing with strtod. 523 Char current = start + cursor(); 524 Char end = start + length(); 525 const int kMaxSignificantDigits = 309; // Doubles are less than 1.8e308. 526 // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero 527 // end. 528 const int kBufferSize = kMaxSignificantDigits + 2; 529 char buffer[kBufferSize]; 530 int buffer_pos = 0; 531 while (*current >= '0' && *current <= '9') { 532 if (buffer_pos <= kMaxSignificantDigits) { 533 // If the number has more than kMaxSignificantDigits it will be parsed 534 // as infinity. 535 DCHECK_LT(buffer_pos, kBufferSize); 536 buffer[buffer_pos++] = static_cast<char>(*current); 537 } 538 ++current; 539 if (current == end) break; 540 } 541 542 SLOW_DCHECK(buffer_pos < kBufferSize); 543 buffer[buffer_pos] = '\0'; 544 Vector<const char> buffer_vector(buffer, buffer_pos); 545 return Strtod(buffer_vector, 0); 546 } 547 548 double result_ = 0; 549 }; 550 551 // Converts a string to a double value. Assumes the Iterator supports 552 // the following operations: 553 // 1. current == end (other ops are not allowed), current != end. 554 // 2. *current - gets the current character in the sequence. 555 // 3. ++current (advances the position). 556 template <class Iterator, class EndMark> 557 double InternalStringToDouble(UnicodeCache* unicode_cache, Iterator current, 558 EndMark end, int flags, double empty_string_val) { 559 // To make sure that iterator dereferencing is valid the following 560 // convention is used: 561 // 1. Each '++current' statement is followed by check for equality to 'end'. 562 // 2. If AdvanceToNonspace returned false then current == end. 563 // 3. If 'current' becomes be equal to 'end' the function returns or goes to 564 // 'parsing_done'. 565 // 4. 'current' is not dereferenced after the 'parsing_done' label. 566 // 5. Code before 'parsing_done' may rely on 'current != end'. 567 if (!AdvanceToNonspace(unicode_cache, ¤t, end)) { 568 return empty_string_val; 569 } 570 571 const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0; 572 573 // Maximum number of significant digits in decimal representation. 574 // The longest possible double in decimal representation is 575 // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 576 // (768 digits). If we parse a number whose first digits are equal to a 577 // mean of 2 adjacent doubles (that could have up to 769 digits) the result 578 // must be rounded to the bigger one unless the tail consists of zeros, so 579 // we don't need to preserve all the digits. 580 const int kMaxSignificantDigits = 772; 581 582 // The longest form of simplified number is: "-<significant digits>'.1eXXX\0". 583 const int kBufferSize = kMaxSignificantDigits + 10; 584 char buffer[kBufferSize]; // NOLINT: size is known at compile time. 585 int buffer_pos = 0; 586 587 // Exponent will be adjusted if insignificant digits of the integer part 588 // or insignificant leading zeros of the fractional part are dropped. 589 int exponent = 0; 590 int significant_digits = 0; 591 int insignificant_digits = 0; 592 bool nonzero_digit_dropped = false; 593 594 enum Sign { NONE, NEGATIVE, POSITIVE }; 595 596 Sign sign = NONE; 597 598 if (*current == '+') { 599 // Ignore leading sign. 600 ++current; 601 if (current == end) return JunkStringValue(); 602 sign = POSITIVE; 603 } else if (*current == '-') { 604 ++current; 605 if (current == end) return JunkStringValue(); 606 sign = NEGATIVE; 607 } 608 609 static const char kInfinityString[] = "Infinity"; 610 if (*current == kInfinityString[0]) { 611 if (!SubStringEquals(¤t, end, kInfinityString)) { 612 return JunkStringValue(); 613 } 614 615 if (!allow_trailing_junk && 616 AdvanceToNonspace(unicode_cache, ¤t, end)) { 617 return JunkStringValue(); 618 } 619 620 DCHECK_EQ(buffer_pos, 0); 621 return (sign == NEGATIVE) ? -V8_INFINITY : V8_INFINITY; 622 } 623 624 bool leading_zero = false; 625 if (*current == '0') { 626 ++current; 627 if (current == end) return SignedZero(sign == NEGATIVE); 628 629 leading_zero = true; 630 631 // It could be hexadecimal value. 632 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { 633 ++current; 634 if (current == end || !isDigit(*current, 16) || sign != NONE) { 635 return JunkStringValue(); // "0x". 636 } 637 638 return InternalStringToIntDouble<4>(unicode_cache, current, end, false, 639 allow_trailing_junk); 640 641 // It could be an explicit octal value. 642 } else if ((flags & ALLOW_OCTAL) && (*current == 'o' || *current == 'O')) { 643 ++current; 644 if (current == end || !isDigit(*current, 8) || sign != NONE) { 645 return JunkStringValue(); // "0o". 646 } 647 648 return InternalStringToIntDouble<3>(unicode_cache, current, end, false, 649 allow_trailing_junk); 650 651 // It could be a binary value. 652 } else if ((flags & ALLOW_BINARY) && (*current == 'b' || *current == 'B')) { 653 ++current; 654 if (current == end || !isBinaryDigit(*current) || sign != NONE) { 655 return JunkStringValue(); // "0b". 656 } 657 658 return InternalStringToIntDouble<1>(unicode_cache, current, end, false, 659 allow_trailing_junk); 660 } 661 662 // Ignore leading zeros in the integer part. 663 while (*current == '0') { 664 ++current; 665 if (current == end) return SignedZero(sign == NEGATIVE); 666 } 667 } 668 669 bool octal = leading_zero && (flags & ALLOW_IMPLICIT_OCTAL) != 0; 670 671 // Copy significant digits of the integer part (if any) to the buffer. 672 while (*current >= '0' && *current <= '9') { 673 if (significant_digits < kMaxSignificantDigits) { 674 DCHECK_LT(buffer_pos, kBufferSize); 675 buffer[buffer_pos++] = static_cast<char>(*current); 676 significant_digits++; 677 // Will later check if it's an octal in the buffer. 678 } else { 679 insignificant_digits++; // Move the digit into the exponential part. 680 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; 681 } 682 octal = octal && *current < '8'; 683 ++current; 684 if (current == end) goto parsing_done; 685 } 686 687 if (significant_digits == 0) { 688 octal = false; 689 } 690 691 if (*current == '.') { 692 if (octal && !allow_trailing_junk) return JunkStringValue(); 693 if (octal) goto parsing_done; 694 695 ++current; 696 if (current == end) { 697 if (significant_digits == 0 && !leading_zero) { 698 return JunkStringValue(); 699 } else { 700 goto parsing_done; 701 } 702 } 703 704 if (significant_digits == 0) { 705 // octal = false; 706 // Integer part consists of 0 or is absent. Significant digits start after 707 // leading zeros (if any). 708 while (*current == '0') { 709 ++current; 710 if (current == end) return SignedZero(sign == NEGATIVE); 711 exponent--; // Move this 0 into the exponent. 712 } 713 } 714 715 // There is a fractional part. We don't emit a '.', but adjust the exponent 716 // instead. 717 while (*current >= '0' && *current <= '9') { 718 if (significant_digits < kMaxSignificantDigits) { 719 DCHECK_LT(buffer_pos, kBufferSize); 720 buffer[buffer_pos++] = static_cast<char>(*current); 721 significant_digits++; 722 exponent--; 723 } else { 724 // Ignore insignificant digits in the fractional part. 725 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; 726 } 727 ++current; 728 if (current == end) goto parsing_done; 729 } 730 } 731 732 if (!leading_zero && exponent == 0 && significant_digits == 0) { 733 // If leading_zeros is true then the string contains zeros. 734 // If exponent < 0 then string was [+-]\.0*... 735 // If significant_digits != 0 the string is not equal to 0. 736 // Otherwise there are no digits in the string. 737 return JunkStringValue(); 738 } 739 740 // Parse exponential part. 741 if (*current == 'e' || *current == 'E') { 742 if (octal) return JunkStringValue(); 743 ++current; 744 if (current == end) { 745 if (allow_trailing_junk) { 746 goto parsing_done; 747 } else { 748 return JunkStringValue(); 749 } 750 } 751 char sign = '+'; 752 if (*current == '+' || *current == '-') { 753 sign = static_cast<char>(*current); 754 ++current; 755 if (current == end) { 756 if (allow_trailing_junk) { 757 goto parsing_done; 758 } else { 759 return JunkStringValue(); 760 } 761 } 762 } 763 764 if (current == end || *current < '0' || *current > '9') { 765 if (allow_trailing_junk) { 766 goto parsing_done; 767 } else { 768 return JunkStringValue(); 769 } 770 } 771 772 const int max_exponent = INT_MAX / 2; 773 DCHECK(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2); 774 int num = 0; 775 do { 776 // Check overflow. 777 int digit = *current - '0'; 778 if (num >= max_exponent / 10 && 779 !(num == max_exponent / 10 && digit <= max_exponent % 10)) { 780 num = max_exponent; 781 } else { 782 num = num * 10 + digit; 783 } 784 ++current; 785 } while (current != end && *current >= '0' && *current <= '9'); 786 787 exponent += (sign == '-' ? -num : num); 788 } 789 790 if (!allow_trailing_junk && AdvanceToNonspace(unicode_cache, ¤t, end)) { 791 return JunkStringValue(); 792 } 793 794 parsing_done: 795 exponent += insignificant_digits; 796 797 if (octal) { 798 return InternalStringToIntDouble<3>(unicode_cache, buffer, 799 buffer + buffer_pos, sign == NEGATIVE, 800 allow_trailing_junk); 801 } 802 803 if (nonzero_digit_dropped) { 804 buffer[buffer_pos++] = '1'; 805 exponent--; 806 } 807 808 SLOW_DCHECK(buffer_pos < kBufferSize); 809 buffer[buffer_pos] = '\0'; 810 811 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); 812 return (sign == NEGATIVE) ? -converted : converted; 813 } 814 815 } // namespace 816 817 double StringToDouble(UnicodeCache* unicode_cache, 818 const char* str, int flags, double empty_string_val) { 819 // We cast to const uint8_t* here to avoid instantiating the 820 // InternalStringToDouble() template for const char* as well. 821 const uint8_t* start = reinterpret_cast<const uint8_t*>(str); 822 const uint8_t* end = start + StrLength(str); 823 return InternalStringToDouble(unicode_cache, start, end, flags, 824 empty_string_val); 825 } 826 827 828 double StringToDouble(UnicodeCache* unicode_cache, 829 Vector<const uint8_t> str, 830 int flags, 831 double empty_string_val) { 832 // We cast to const uint8_t* here to avoid instantiating the 833 // InternalStringToDouble() template for const char* as well. 834 const uint8_t* start = reinterpret_cast<const uint8_t*>(str.start()); 835 const uint8_t* end = start + str.length(); 836 return InternalStringToDouble(unicode_cache, start, end, flags, 837 empty_string_val); 838 } 839 840 841 double StringToDouble(UnicodeCache* unicode_cache, 842 Vector<const uc16> str, 843 int flags, 844 double empty_string_val) { 845 const uc16* end = str.start() + str.length(); 846 return InternalStringToDouble(unicode_cache, str.start(), end, flags, 847 empty_string_val); 848 } 849 850 double StringToInt(Isolate* isolate, Handle<String> string, int radix) { 851 NumberParseIntHelper helper(isolate, string, radix); 852 return helper.GetResult(); 853 } 854 855 class StringToBigIntHelper : public StringToIntHelper { 856 public: 857 enum class Behavior { kStringToBigInt, kLiteral }; 858 859 // Used for StringToBigInt operation (BigInt constructor and == operator). 860 StringToBigIntHelper(Isolate* isolate, Handle<String> string) 861 : StringToIntHelper(isolate, string), 862 behavior_(Behavior::kStringToBigInt) { 863 set_allow_binary_and_octal_prefixes(); 864 set_disallow_trailing_junk(); 865 } 866 867 // Used for parsing BigInt literals, where the input is a buffer of 868 // one-byte ASCII digits, along with an optional radix prefix. 869 StringToBigIntHelper(Isolate* isolate, const uint8_t* string, int length) 870 : StringToIntHelper(isolate, string, length), 871 behavior_(Behavior::kLiteral) { 872 set_allow_binary_and_octal_prefixes(); 873 } 874 875 MaybeHandle<BigInt> GetResult() { 876 ParseInt(); 877 if (behavior_ == Behavior::kStringToBigInt && sign() != Sign::kNone && 878 radix() != 10) { 879 return MaybeHandle<BigInt>(); 880 } 881 if (state() == kEmpty) { 882 if (behavior_ == Behavior::kStringToBigInt) { 883 set_state(kZero); 884 } else { 885 UNREACHABLE(); 886 } 887 } 888 switch (state()) { 889 case kJunk: 890 if (should_throw() == kThrowOnError) { 891 THROW_NEW_ERROR(isolate(), 892 NewSyntaxError(MessageTemplate::kBigIntInvalidString), 893 BigInt); 894 } else { 895 DCHECK_EQ(should_throw(), kDontThrow); 896 return MaybeHandle<BigInt>(); 897 } 898 case kZero: 899 return BigInt::Zero(isolate()); 900 case kError: 901 DCHECK_EQ(should_throw() == kThrowOnError, 902 isolate()->has_pending_exception()); 903 return MaybeHandle<BigInt>(); 904 case kDone: 905 return BigInt::Finalize(result_, negative()); 906 case kEmpty: 907 case kRunning: 908 break; 909 } 910 UNREACHABLE(); 911 } 912 913 protected: 914 virtual void AllocateResult() { 915 // We have to allocate a BigInt that's big enough to fit the result. 916 // Conseratively assume that all remaining digits are significant. 917 // Optimization opportunity: Would it makes sense to scan for trailing 918 // junk before allocating the result? 919 int charcount = length() - cursor(); 920 // For literals, we pretenure the allocated BigInt, since it's about 921 // to be stored in the interpreter's constants array. 922 PretenureFlag pretenure = 923 behavior_ == Behavior::kLiteral ? TENURED : NOT_TENURED; 924 MaybeHandle<FreshlyAllocatedBigInt> maybe = BigInt::AllocateFor( 925 isolate(), radix(), charcount, should_throw(), pretenure); 926 if (!maybe.ToHandle(&result_)) { 927 set_state(kError); 928 } 929 } 930 931 virtual void ResultMultiplyAdd(uint32_t multiplier, uint32_t part) { 932 BigInt::InplaceMultiplyAdd(result_, static_cast<uintptr_t>(multiplier), 933 static_cast<uintptr_t>(part)); 934 } 935 936 private: 937 ShouldThrow should_throw() const { return kDontThrow; } 938 939 Handle<FreshlyAllocatedBigInt> result_; 940 Behavior behavior_; 941 }; 942 943 MaybeHandle<BigInt> StringToBigInt(Isolate* isolate, Handle<String> string) { 944 string = String::Flatten(isolate, string); 945 StringToBigIntHelper helper(isolate, string); 946 return helper.GetResult(); 947 } 948 949 MaybeHandle<BigInt> BigIntLiteral(Isolate* isolate, const char* string) { 950 StringToBigIntHelper helper(isolate, reinterpret_cast<const uint8_t*>(string), 951 static_cast<int>(strlen(string))); 952 return helper.GetResult(); 953 } 954 955 const char* DoubleToCString(double v, Vector<char> buffer) { 956 switch (FPCLASSIFY_NAMESPACE::fpclassify(v)) { 957 case FP_NAN: return "NaN"; 958 case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity"); 959 case FP_ZERO: return "0"; 960 default: { 961 SimpleStringBuilder builder(buffer.start(), buffer.length()); 962 int decimal_point; 963 int sign; 964 const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1; 965 char decimal_rep[kV8DtoaBufferCapacity]; 966 int length; 967 968 DoubleToAscii(v, DTOA_SHORTEST, 0, 969 Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 970 &sign, &length, &decimal_point); 971 972 if (sign) builder.AddCharacter('-'); 973 974 if (length <= decimal_point && decimal_point <= 21) { 975 // ECMA-262 section 9.8.1 step 6. 976 builder.AddString(decimal_rep); 977 builder.AddPadding('0', decimal_point - length); 978 979 } else if (0 < decimal_point && decimal_point <= 21) { 980 // ECMA-262 section 9.8.1 step 7. 981 builder.AddSubstring(decimal_rep, decimal_point); 982 builder.AddCharacter('.'); 983 builder.AddString(decimal_rep + decimal_point); 984 985 } else if (decimal_point <= 0 && decimal_point > -6) { 986 // ECMA-262 section 9.8.1 step 8. 987 builder.AddString("0."); 988 builder.AddPadding('0', -decimal_point); 989 builder.AddString(decimal_rep); 990 991 } else { 992 // ECMA-262 section 9.8.1 step 9 and 10 combined. 993 builder.AddCharacter(decimal_rep[0]); 994 if (length != 1) { 995 builder.AddCharacter('.'); 996 builder.AddString(decimal_rep + 1); 997 } 998 builder.AddCharacter('e'); 999 builder.AddCharacter((decimal_point >= 0) ? '+' : '-'); 1000 int exponent = decimal_point - 1; 1001 if (exponent < 0) exponent = -exponent; 1002 builder.AddDecimalInteger(exponent); 1003 } 1004 return builder.Finalize(); 1005 } 1006 } 1007 } 1008 1009 1010 const char* IntToCString(int n, Vector<char> buffer) { 1011 bool negative = false; 1012 if (n < 0) { 1013 // We must not negate the most negative int. 1014 if (n == kMinInt) return DoubleToCString(n, buffer); 1015 negative = true; 1016 n = -n; 1017 } 1018 // Build the string backwards from the least significant digit. 1019 int i = buffer.length(); 1020 buffer[--i] = '\0'; 1021 do { 1022 buffer[--i] = '0' + (n % 10); 1023 n /= 10; 1024 } while (n); 1025 if (negative) buffer[--i] = '-'; 1026 return buffer.start() + i; 1027 } 1028 1029 1030 char* DoubleToFixedCString(double value, int f) { 1031 const int kMaxDigitsBeforePoint = 21; 1032 const double kFirstNonFixed = 1e21; 1033 DCHECK_GE(f, 0); 1034 DCHECK_LE(f, kMaxFractionDigits); 1035 1036 bool negative = false; 1037 double abs_value = value; 1038 if (value < 0) { 1039 abs_value = -value; 1040 negative = true; 1041 } 1042 1043 // If abs_value has more than kMaxDigitsBeforePoint digits before the point 1044 // use the non-fixed conversion routine. 1045 if (abs_value >= kFirstNonFixed) { 1046 char arr[kMaxFractionDigits]; 1047 Vector<char> buffer(arr, arraysize(arr)); 1048 return StrDup(DoubleToCString(value, buffer)); 1049 } 1050 1051 // Find a sufficiently precise decimal representation of n. 1052 int decimal_point; 1053 int sign; 1054 // Add space for the '\0' byte. 1055 const int kDecimalRepCapacity = 1056 kMaxDigitsBeforePoint + kMaxFractionDigits + 1; 1057 char decimal_rep[kDecimalRepCapacity]; 1058 int decimal_rep_length; 1059 DoubleToAscii(value, DTOA_FIXED, f, 1060 Vector<char>(decimal_rep, kDecimalRepCapacity), 1061 &sign, &decimal_rep_length, &decimal_point); 1062 1063 // Create a representation that is padded with zeros if needed. 1064 int zero_prefix_length = 0; 1065 int zero_postfix_length = 0; 1066 1067 if (decimal_point <= 0) { 1068 zero_prefix_length = -decimal_point + 1; 1069 decimal_point = 1; 1070 } 1071 1072 if (zero_prefix_length + decimal_rep_length < decimal_point + f) { 1073 zero_postfix_length = decimal_point + f - decimal_rep_length - 1074 zero_prefix_length; 1075 } 1076 1077 unsigned rep_length = 1078 zero_prefix_length + decimal_rep_length + zero_postfix_length; 1079 SimpleStringBuilder rep_builder(rep_length + 1); 1080 rep_builder.AddPadding('0', zero_prefix_length); 1081 rep_builder.AddString(decimal_rep); 1082 rep_builder.AddPadding('0', zero_postfix_length); 1083 char* rep = rep_builder.Finalize(); 1084 1085 // Create the result string by appending a minus and putting in a 1086 // decimal point if needed. 1087 unsigned result_size = decimal_point + f + 2; 1088 SimpleStringBuilder builder(result_size + 1); 1089 if (negative) builder.AddCharacter('-'); 1090 builder.AddSubstring(rep, decimal_point); 1091 if (f > 0) { 1092 builder.AddCharacter('.'); 1093 builder.AddSubstring(rep + decimal_point, f); 1094 } 1095 DeleteArray(rep); 1096 return builder.Finalize(); 1097 } 1098 1099 1100 static char* CreateExponentialRepresentation(char* decimal_rep, 1101 int exponent, 1102 bool negative, 1103 int significant_digits) { 1104 bool negative_exponent = false; 1105 if (exponent < 0) { 1106 negative_exponent = true; 1107 exponent = -exponent; 1108 } 1109 1110 // Leave room in the result for appending a minus, for a period, the 1111 // letter 'e', a minus or a plus depending on the exponent, and a 1112 // three digit exponent. 1113 unsigned result_size = significant_digits + 7; 1114 SimpleStringBuilder builder(result_size + 1); 1115 1116 if (negative) builder.AddCharacter('-'); 1117 builder.AddCharacter(decimal_rep[0]); 1118 if (significant_digits != 1) { 1119 builder.AddCharacter('.'); 1120 builder.AddString(decimal_rep + 1); 1121 int rep_length = StrLength(decimal_rep); 1122 builder.AddPadding('0', significant_digits - rep_length); 1123 } 1124 1125 builder.AddCharacter('e'); 1126 builder.AddCharacter(negative_exponent ? '-' : '+'); 1127 builder.AddDecimalInteger(exponent); 1128 return builder.Finalize(); 1129 } 1130 1131 1132 char* DoubleToExponentialCString(double value, int f) { 1133 // f might be -1 to signal that f was undefined in JavaScript. 1134 DCHECK(f >= -1 && f <= kMaxFractionDigits); 1135 1136 bool negative = false; 1137 if (value < 0) { 1138 value = -value; 1139 negative = true; 1140 } 1141 1142 // Find a sufficiently precise decimal representation of n. 1143 int decimal_point; 1144 int sign; 1145 // f corresponds to the digits after the point. There is always one digit 1146 // before the point. The number of requested_digits equals hence f + 1. 1147 // And we have to add one character for the null-terminator. 1148 const int kV8DtoaBufferCapacity = kMaxFractionDigits + 1 + 1; 1149 // Make sure that the buffer is big enough, even if we fall back to the 1150 // shortest representation (which happens when f equals -1). 1151 DCHECK_LE(kBase10MaximalLength, kMaxFractionDigits + 1); 1152 char decimal_rep[kV8DtoaBufferCapacity]; 1153 int decimal_rep_length; 1154 1155 if (f == -1) { 1156 DoubleToAscii(value, DTOA_SHORTEST, 0, 1157 Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 1158 &sign, &decimal_rep_length, &decimal_point); 1159 f = decimal_rep_length - 1; 1160 } else { 1161 DoubleToAscii(value, DTOA_PRECISION, f + 1, 1162 Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 1163 &sign, &decimal_rep_length, &decimal_point); 1164 } 1165 DCHECK_GT(decimal_rep_length, 0); 1166 DCHECK(decimal_rep_length <= f + 1); 1167 1168 int exponent = decimal_point - 1; 1169 char* result = 1170 CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1); 1171 1172 return result; 1173 } 1174 1175 1176 char* DoubleToPrecisionCString(double value, int p) { 1177 const int kMinimalDigits = 1; 1178 DCHECK(p >= kMinimalDigits && p <= kMaxFractionDigits); 1179 USE(kMinimalDigits); 1180 1181 bool negative = false; 1182 if (value < 0) { 1183 value = -value; 1184 negative = true; 1185 } 1186 1187 // Find a sufficiently precise decimal representation of n. 1188 int decimal_point; 1189 int sign; 1190 // Add one for the terminating null character. 1191 const int kV8DtoaBufferCapacity = kMaxFractionDigits + 1; 1192 char decimal_rep[kV8DtoaBufferCapacity]; 1193 int decimal_rep_length; 1194 1195 DoubleToAscii(value, DTOA_PRECISION, p, 1196 Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 1197 &sign, &decimal_rep_length, &decimal_point); 1198 DCHECK(decimal_rep_length <= p); 1199 1200 int exponent = decimal_point - 1; 1201 1202 char* result = nullptr; 1203 1204 if (exponent < -6 || exponent >= p) { 1205 result = 1206 CreateExponentialRepresentation(decimal_rep, exponent, negative, p); 1207 } else { 1208 // Use fixed notation. 1209 // 1210 // Leave room in the result for appending a minus, a period and in 1211 // the case where decimal_point is not positive for a zero in 1212 // front of the period. 1213 unsigned result_size = (decimal_point <= 0) 1214 ? -decimal_point + p + 3 1215 : p + 2; 1216 SimpleStringBuilder builder(result_size + 1); 1217 if (negative) builder.AddCharacter('-'); 1218 if (decimal_point <= 0) { 1219 builder.AddString("0."); 1220 builder.AddPadding('0', -decimal_point); 1221 builder.AddString(decimal_rep); 1222 builder.AddPadding('0', p - decimal_rep_length); 1223 } else { 1224 const int m = Min(decimal_rep_length, decimal_point); 1225 builder.AddSubstring(decimal_rep, m); 1226 builder.AddPadding('0', decimal_point - decimal_rep_length); 1227 if (decimal_point < p) { 1228 builder.AddCharacter('.'); 1229 const int extra = negative ? 2 : 1; 1230 if (decimal_rep_length > decimal_point) { 1231 const int len = StrLength(decimal_rep + decimal_point); 1232 const int n = Min(len, p - (builder.position() - extra)); 1233 builder.AddSubstring(decimal_rep + decimal_point, n); 1234 } 1235 builder.AddPadding('0', extra + (p - builder.position())); 1236 } 1237 } 1238 result = builder.Finalize(); 1239 } 1240 1241 return result; 1242 } 1243 1244 char* DoubleToRadixCString(double value, int radix) { 1245 DCHECK(radix >= 2 && radix <= 36); 1246 DCHECK(std::isfinite(value)); 1247 DCHECK_NE(0.0, value); 1248 // Character array used for conversion. 1249 static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 1250 1251 // Temporary buffer for the result. We start with the decimal point in the 1252 // middle and write to the left for the integer part and to the right for the 1253 // fractional part. 1024 characters for the exponent and 52 for the mantissa 1254 // either way, with additional space for sign, decimal point and string 1255 // termination should be sufficient. 1256 static const int kBufferSize = 2200; 1257 char buffer[kBufferSize]; 1258 int integer_cursor = kBufferSize / 2; 1259 int fraction_cursor = integer_cursor; 1260 1261 bool negative = value < 0; 1262 if (negative) value = -value; 1263 1264 // Split the value into an integer part and a fractional part. 1265 double integer = std::floor(value); 1266 double fraction = value - integer; 1267 // We only compute fractional digits up to the input double's precision. 1268 double delta = 0.5 * (Double(value).NextDouble() - value); 1269 delta = std::max(Double(0.0).NextDouble(), delta); 1270 DCHECK_GT(delta, 0.0); 1271 if (fraction > delta) { 1272 // Insert decimal point. 1273 buffer[fraction_cursor++] = '.'; 1274 do { 1275 // Shift up by one digit. 1276 fraction *= radix; 1277 delta *= radix; 1278 // Write digit. 1279 int digit = static_cast<int>(fraction); 1280 buffer[fraction_cursor++] = chars[digit]; 1281 // Calculate remainder. 1282 fraction -= digit; 1283 // Round to even. 1284 if (fraction > 0.5 || (fraction == 0.5 && (digit & 1))) { 1285 if (fraction + delta > 1) { 1286 // We need to back trace already written digits in case of carry-over. 1287 while (true) { 1288 fraction_cursor--; 1289 if (fraction_cursor == kBufferSize / 2) { 1290 CHECK_EQ('.', buffer[fraction_cursor]); 1291 // Carry over to the integer part. 1292 integer += 1; 1293 break; 1294 } 1295 char c = buffer[fraction_cursor]; 1296 // Reconstruct digit. 1297 int digit = c > '9' ? (c - 'a' + 10) : (c - '0'); 1298 if (digit + 1 < radix) { 1299 buffer[fraction_cursor++] = chars[digit + 1]; 1300 break; 1301 } 1302 } 1303 break; 1304 } 1305 } 1306 } while (fraction > delta); 1307 } 1308 1309 // Compute integer digits. Fill unrepresented digits with zero. 1310 while (Double(integer / radix).Exponent() > 0) { 1311 integer /= radix; 1312 buffer[--integer_cursor] = '0'; 1313 } 1314 do { 1315 double remainder = Modulo(integer, radix); 1316 buffer[--integer_cursor] = chars[static_cast<int>(remainder)]; 1317 integer = (integer - remainder) / radix; 1318 } while (integer > 0); 1319 1320 // Add sign and terminate string. 1321 if (negative) buffer[--integer_cursor] = '-'; 1322 buffer[fraction_cursor++] = '\0'; 1323 DCHECK_LT(fraction_cursor, kBufferSize); 1324 DCHECK_LE(0, integer_cursor); 1325 // Allocate new string as return value. 1326 char* result = NewArray<char>(fraction_cursor - integer_cursor); 1327 memcpy(result, buffer + integer_cursor, fraction_cursor - integer_cursor); 1328 return result; 1329 } 1330 1331 1332 // ES6 18.2.4 parseFloat(string) 1333 double StringToDouble(Isolate* isolate, UnicodeCache* unicode_cache, 1334 Handle<String> string, int flags, 1335 double empty_string_val) { 1336 Handle<String> flattened = String::Flatten(isolate, string); 1337 { 1338 DisallowHeapAllocation no_gc; 1339 String::FlatContent flat = flattened->GetFlatContent(); 1340 DCHECK(flat.IsFlat()); 1341 if (flat.IsOneByte()) { 1342 return StringToDouble(unicode_cache, flat.ToOneByteVector(), flags, 1343 empty_string_val); 1344 } else { 1345 return StringToDouble(unicode_cache, flat.ToUC16Vector(), flags, 1346 empty_string_val); 1347 } 1348 } 1349 } 1350 1351 1352 bool IsSpecialIndex(UnicodeCache* unicode_cache, String* string) { 1353 // Max length of canonical double: -X.XXXXXXXXXXXXXXXXX-eXXX 1354 const int kBufferSize = 24; 1355 const int length = string->length(); 1356 if (length == 0 || length > kBufferSize) return false; 1357 uint16_t buffer[kBufferSize]; 1358 String::WriteToFlat(string, buffer, 0, length); 1359 // If the first char is not a digit or a '-' or we can't match 'NaN' or 1360 // '(-)Infinity', bailout immediately. 1361 int offset = 0; 1362 if (!IsDecimalDigit(buffer[0])) { 1363 if (buffer[0] == '-') { 1364 if (length == 1) return false; // Just '-' is bad. 1365 if (!IsDecimalDigit(buffer[1])) { 1366 if (buffer[1] == 'I' && length == 9) { 1367 // Allow matching of '-Infinity' below. 1368 } else { 1369 return false; 1370 } 1371 } 1372 offset++; 1373 } else if (buffer[0] == 'I' && length == 8) { 1374 // Allow matching of 'Infinity' below. 1375 } else if (buffer[0] == 'N' && length == 3) { 1376 // Match NaN. 1377 return buffer[1] == 'a' && buffer[2] == 'N'; 1378 } else { 1379 return false; 1380 } 1381 } 1382 // Expected fast path: key is an integer. 1383 static const int kRepresentableIntegerLength = 15; // (-)XXXXXXXXXXXXXXX 1384 if (length - offset <= kRepresentableIntegerLength) { 1385 const int initial_offset = offset; 1386 bool matches = true; 1387 for (; offset < length; offset++) { 1388 matches &= IsDecimalDigit(buffer[offset]); 1389 } 1390 if (matches) { 1391 // Match 0 and -0. 1392 if (buffer[initial_offset] == '0') return initial_offset == length - 1; 1393 return true; 1394 } 1395 } 1396 // Slow path: test DoubleToString(StringToDouble(string)) == string. 1397 Vector<const uint16_t> vector(buffer, length); 1398 double d = StringToDouble(unicode_cache, vector, NO_FLAGS); 1399 if (std::isnan(d)) return false; 1400 // Compute reverse string. 1401 char reverse_buffer[kBufferSize + 1]; // Result will be /0 terminated. 1402 Vector<char> reverse_vector(reverse_buffer, arraysize(reverse_buffer)); 1403 const char* reverse_string = DoubleToCString(d, reverse_vector); 1404 for (int i = 0; i < length; ++i) { 1405 if (static_cast<uint16_t>(reverse_string[i]) != buffer[i]) return false; 1406 } 1407 return true; 1408 } 1409 } // namespace internal 1410 } // namespace v8 1411