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