| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2017 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/builtins/builtins-utils.h" | 5 #include "src/builtins/builtins-utils-gen.h" |
| 6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
| 7 #include "src/code-factory.h" | |
| 8 #include "src/code-stub-assembler.h" | 7 #include "src/code-stub-assembler.h" |
| 9 #include "src/conversions.h" | |
| 10 #include "src/counters.h" | |
| 11 #include "src/objects-inl.h" | |
| 12 | 8 |
| 13 namespace v8 { | 9 namespace v8 { |
| 14 namespace internal { | 10 namespace internal { |
| 15 | 11 |
| 12 // ----------------------------------------------------------------------------- |
| 13 // ES6 section 20.1 Number Objects |
| 14 |
| 16 class NumberBuiltinsAssembler : public CodeStubAssembler { | 15 class NumberBuiltinsAssembler : public CodeStubAssembler { |
| 17 public: | 16 public: |
| 18 explicit NumberBuiltinsAssembler(compiler::CodeAssemblerState* state) | 17 explicit NumberBuiltinsAssembler(compiler::CodeAssemblerState* state) |
| 19 : CodeStubAssembler(state) {} | 18 : CodeStubAssembler(state) {} |
| 20 | 19 |
| 21 protected: | 20 protected: |
| 22 template <Signedness signed_result = kSigned> | 21 template <Signedness signed_result = kSigned> |
| 23 void BitwiseOp(std::function<Node*(Node* lhs, Node* rhs)> body) { | 22 void BitwiseOp(std::function<Node*(Node* lhs, Node* rhs)> body) { |
| 24 Node* left = Parameter(0); | 23 Node* left = Parameter(0); |
| 25 Node* right = Parameter(1); | 24 Node* right = Parameter(1); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 43 | 42 |
| 44 void RelationalComparisonBuiltin(RelationalComparisonMode mode) { | 43 void RelationalComparisonBuiltin(RelationalComparisonMode mode) { |
| 45 Node* lhs = Parameter(0); | 44 Node* lhs = Parameter(0); |
| 46 Node* rhs = Parameter(1); | 45 Node* rhs = Parameter(1); |
| 47 Node* context = Parameter(2); | 46 Node* context = Parameter(2); |
| 48 | 47 |
| 49 Return(RelationalComparison(mode, lhs, rhs, context)); | 48 Return(RelationalComparison(mode, lhs, rhs, context)); |
| 50 } | 49 } |
| 51 }; | 50 }; |
| 52 | 51 |
| 53 // ----------------------------------------------------------------------------- | |
| 54 // ES6 section 20.1 Number Objects | |
| 55 | |
| 56 // ES6 section 20.1.2.2 Number.isFinite ( number ) | 52 // ES6 section 20.1.2.2 Number.isFinite ( number ) |
| 57 TF_BUILTIN(NumberIsFinite, CodeStubAssembler) { | 53 TF_BUILTIN(NumberIsFinite, CodeStubAssembler) { |
| 58 Node* number = Parameter(1); | 54 Node* number = Parameter(1); |
| 59 | 55 |
| 60 Label return_true(this), return_false(this); | 56 Label return_true(this), return_false(this); |
| 61 | 57 |
| 62 // Check if {number} is a Smi. | 58 // Check if {number} is a Smi. |
| 63 GotoIf(TaggedIsSmi(number), &return_true); | 59 GotoIf(TaggedIsSmi(number), &return_true); |
| 64 | 60 |
| 65 // Check if {number} is a HeapNumber. | 61 // Check if {number} is a HeapNumber. |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 } | 325 } |
| 330 } | 326 } |
| 331 | 327 |
| 332 Bind(&if_generic); | 328 Bind(&if_generic); |
| 333 { | 329 { |
| 334 Node* result = CallRuntime(Runtime::kStringParseInt, context, input, radix); | 330 Node* result = CallRuntime(Runtime::kStringParseInt, context, input, radix); |
| 335 Return(result); | 331 Return(result); |
| 336 } | 332 } |
| 337 } | 333 } |
| 338 | 334 |
| 339 // ES6 section 20.1.3.2 Number.prototype.toExponential ( fractionDigits ) | |
| 340 BUILTIN(NumberPrototypeToExponential) { | |
| 341 HandleScope scope(isolate); | |
| 342 Handle<Object> value = args.at(0); | |
| 343 Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1); | |
| 344 | |
| 345 // Unwrap the receiver {value}. | |
| 346 if (value->IsJSValue()) { | |
| 347 value = handle(Handle<JSValue>::cast(value)->value(), isolate); | |
| 348 } | |
| 349 if (!value->IsNumber()) { | |
| 350 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 351 isolate, NewTypeError(MessageTemplate::kNotGeneric, | |
| 352 isolate->factory()->NewStringFromAsciiChecked( | |
| 353 "Number.prototype.toExponential"))); | |
| 354 } | |
| 355 double const value_number = value->Number(); | |
| 356 | |
| 357 // Convert the {fraction_digits} to an integer first. | |
| 358 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 359 isolate, fraction_digits, Object::ToInteger(isolate, fraction_digits)); | |
| 360 double const fraction_digits_number = fraction_digits->Number(); | |
| 361 | |
| 362 if (std::isnan(value_number)) return isolate->heap()->nan_string(); | |
| 363 if (std::isinf(value_number)) { | |
| 364 return (value_number < 0.0) ? isolate->heap()->minus_infinity_string() | |
| 365 : isolate->heap()->infinity_string(); | |
| 366 } | |
| 367 if (fraction_digits_number < 0.0 || fraction_digits_number > 20.0) { | |
| 368 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 369 isolate, NewRangeError(MessageTemplate::kNumberFormatRange, | |
| 370 isolate->factory()->NewStringFromAsciiChecked( | |
| 371 "toExponential()"))); | |
| 372 } | |
| 373 int const f = args.atOrUndefined(isolate, 1)->IsUndefined(isolate) | |
| 374 ? -1 | |
| 375 : static_cast<int>(fraction_digits_number); | |
| 376 char* const str = DoubleToExponentialCString(value_number, f); | |
| 377 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str); | |
| 378 DeleteArray(str); | |
| 379 return *result; | |
| 380 } | |
| 381 | |
| 382 // ES6 section 20.1.3.3 Number.prototype.toFixed ( fractionDigits ) | |
| 383 BUILTIN(NumberPrototypeToFixed) { | |
| 384 HandleScope scope(isolate); | |
| 385 Handle<Object> value = args.at(0); | |
| 386 Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1); | |
| 387 | |
| 388 // Unwrap the receiver {value}. | |
| 389 if (value->IsJSValue()) { | |
| 390 value = handle(Handle<JSValue>::cast(value)->value(), isolate); | |
| 391 } | |
| 392 if (!value->IsNumber()) { | |
| 393 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 394 isolate, NewTypeError(MessageTemplate::kNotGeneric, | |
| 395 isolate->factory()->NewStringFromAsciiChecked( | |
| 396 "Number.prototype.toFixed"))); | |
| 397 } | |
| 398 double const value_number = value->Number(); | |
| 399 | |
| 400 // Convert the {fraction_digits} to an integer first. | |
| 401 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 402 isolate, fraction_digits, Object::ToInteger(isolate, fraction_digits)); | |
| 403 double const fraction_digits_number = fraction_digits->Number(); | |
| 404 | |
| 405 // Check if the {fraction_digits} are in the supported range. | |
| 406 if (fraction_digits_number < 0.0 || fraction_digits_number > 20.0) { | |
| 407 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 408 isolate, NewRangeError(MessageTemplate::kNumberFormatRange, | |
| 409 isolate->factory()->NewStringFromAsciiChecked( | |
| 410 "toFixed() digits"))); | |
| 411 } | |
| 412 | |
| 413 if (std::isnan(value_number)) return isolate->heap()->nan_string(); | |
| 414 if (std::isinf(value_number)) { | |
| 415 return (value_number < 0.0) ? isolate->heap()->minus_infinity_string() | |
| 416 : isolate->heap()->infinity_string(); | |
| 417 } | |
| 418 char* const str = DoubleToFixedCString( | |
| 419 value_number, static_cast<int>(fraction_digits_number)); | |
| 420 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str); | |
| 421 DeleteArray(str); | |
| 422 return *result; | |
| 423 } | |
| 424 | |
| 425 // ES6 section 20.1.3.4 Number.prototype.toLocaleString ( [ r1 [ , r2 ] ] ) | |
| 426 BUILTIN(NumberPrototypeToLocaleString) { | |
| 427 HandleScope scope(isolate); | |
| 428 Handle<Object> value = args.at(0); | |
| 429 | |
| 430 // Unwrap the receiver {value}. | |
| 431 if (value->IsJSValue()) { | |
| 432 value = handle(Handle<JSValue>::cast(value)->value(), isolate); | |
| 433 } | |
| 434 if (!value->IsNumber()) { | |
| 435 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 436 isolate, NewTypeError(MessageTemplate::kNotGeneric, | |
| 437 isolate->factory()->NewStringFromAsciiChecked( | |
| 438 "Number.prototype.toLocaleString"))); | |
| 439 } | |
| 440 | |
| 441 // Turn the {value} into a String. | |
| 442 return *isolate->factory()->NumberToString(value); | |
| 443 } | |
| 444 | |
| 445 // ES6 section 20.1.3.5 Number.prototype.toPrecision ( precision ) | |
| 446 BUILTIN(NumberPrototypeToPrecision) { | |
| 447 HandleScope scope(isolate); | |
| 448 Handle<Object> value = args.at(0); | |
| 449 Handle<Object> precision = args.atOrUndefined(isolate, 1); | |
| 450 | |
| 451 // Unwrap the receiver {value}. | |
| 452 if (value->IsJSValue()) { | |
| 453 value = handle(Handle<JSValue>::cast(value)->value(), isolate); | |
| 454 } | |
| 455 if (!value->IsNumber()) { | |
| 456 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 457 isolate, NewTypeError(MessageTemplate::kNotGeneric, | |
| 458 isolate->factory()->NewStringFromAsciiChecked( | |
| 459 "Number.prototype.toPrecision"))); | |
| 460 } | |
| 461 double const value_number = value->Number(); | |
| 462 | |
| 463 // If no {precision} was specified, just return ToString of {value}. | |
| 464 if (precision->IsUndefined(isolate)) { | |
| 465 return *isolate->factory()->NumberToString(value); | |
| 466 } | |
| 467 | |
| 468 // Convert the {precision} to an integer first. | |
| 469 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, precision, | |
| 470 Object::ToInteger(isolate, precision)); | |
| 471 double const precision_number = precision->Number(); | |
| 472 | |
| 473 if (std::isnan(value_number)) return isolate->heap()->nan_string(); | |
| 474 if (std::isinf(value_number)) { | |
| 475 return (value_number < 0.0) ? isolate->heap()->minus_infinity_string() | |
| 476 : isolate->heap()->infinity_string(); | |
| 477 } | |
| 478 if (precision_number < 1.0 || precision_number > 21.0) { | |
| 479 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 480 isolate, NewRangeError(MessageTemplate::kToPrecisionFormatRange)); | |
| 481 } | |
| 482 char* const str = DoubleToPrecisionCString( | |
| 483 value_number, static_cast<int>(precision_number)); | |
| 484 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str); | |
| 485 DeleteArray(str); | |
| 486 return *result; | |
| 487 } | |
| 488 | |
| 489 // ES6 section 20.1.3.6 Number.prototype.toString ( [ radix ] ) | |
| 490 BUILTIN(NumberPrototypeToString) { | |
| 491 HandleScope scope(isolate); | |
| 492 Handle<Object> value = args.at(0); | |
| 493 Handle<Object> radix = args.atOrUndefined(isolate, 1); | |
| 494 | |
| 495 // Unwrap the receiver {value}. | |
| 496 if (value->IsJSValue()) { | |
| 497 value = handle(Handle<JSValue>::cast(value)->value(), isolate); | |
| 498 } | |
| 499 if (!value->IsNumber()) { | |
| 500 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 501 isolate, NewTypeError(MessageTemplate::kNotGeneric, | |
| 502 isolate->factory()->NewStringFromAsciiChecked( | |
| 503 "Number.prototype.toString"))); | |
| 504 } | |
| 505 double const value_number = value->Number(); | |
| 506 | |
| 507 // If no {radix} was specified, just return ToString of {value}. | |
| 508 if (radix->IsUndefined(isolate)) { | |
| 509 return *isolate->factory()->NumberToString(value); | |
| 510 } | |
| 511 | |
| 512 // Convert the {radix} to an integer first. | |
| 513 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, radix, | |
| 514 Object::ToInteger(isolate, radix)); | |
| 515 double const radix_number = radix->Number(); | |
| 516 | |
| 517 // If {radix} is 10, just return ToString of {value}. | |
| 518 if (radix_number == 10.0) return *isolate->factory()->NumberToString(value); | |
| 519 | |
| 520 // Make sure the {radix} is within the valid range. | |
| 521 if (radix_number < 2.0 || radix_number > 36.0) { | |
| 522 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 523 isolate, NewRangeError(MessageTemplate::kToRadixFormatRange)); | |
| 524 } | |
| 525 | |
| 526 // Fast case where the result is a one character string. | |
| 527 if ((IsUint32Double(value_number) && value_number < radix_number) || | |
| 528 value_number == -0.0) { | |
| 529 // Character array used for conversion. | |
| 530 static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz"; | |
| 531 return *isolate->factory()->LookupSingleCharacterStringFromCode( | |
| 532 kCharTable[static_cast<uint32_t>(value_number)]); | |
| 533 } | |
| 534 | |
| 535 // Slow case. | |
| 536 if (std::isnan(value_number)) return isolate->heap()->nan_string(); | |
| 537 if (std::isinf(value_number)) { | |
| 538 return (value_number < 0.0) ? isolate->heap()->minus_infinity_string() | |
| 539 : isolate->heap()->infinity_string(); | |
| 540 } | |
| 541 char* const str = | |
| 542 DoubleToRadixCString(value_number, static_cast<int>(radix_number)); | |
| 543 Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str); | |
| 544 DeleteArray(str); | |
| 545 return *result; | |
| 546 } | |
| 547 | |
| 548 // ES6 section 20.1.3.7 Number.prototype.valueOf ( ) | 335 // ES6 section 20.1.3.7 Number.prototype.valueOf ( ) |
| 549 TF_BUILTIN(NumberPrototypeValueOf, CodeStubAssembler) { | 336 TF_BUILTIN(NumberPrototypeValueOf, CodeStubAssembler) { |
| 550 Node* receiver = Parameter(0); | 337 Node* receiver = Parameter(0); |
| 551 Node* context = Parameter(3); | 338 Node* context = Parameter(3); |
| 552 | 339 |
| 553 Node* result = ToThisValue(context, receiver, PrimitiveType::kNumber, | 340 Node* result = ToThisValue(context, receiver, PrimitiveType::kNumber, |
| 554 "Number.prototype.valueOf"); | 341 "Number.prototype.valueOf"); |
| 555 Return(result); | 342 Return(result); |
| 556 } | 343 } |
| 557 | 344 |
| (...skipping 1034 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1592 | 1379 |
| 1593 TF_BUILTIN(StrictEqual, CodeStubAssembler) { | 1380 TF_BUILTIN(StrictEqual, CodeStubAssembler) { |
| 1594 Node* lhs = Parameter(0); | 1381 Node* lhs = Parameter(0); |
| 1595 Node* rhs = Parameter(1); | 1382 Node* rhs = Parameter(1); |
| 1596 | 1383 |
| 1597 Return(StrictEqual(lhs, rhs)); | 1384 Return(StrictEqual(lhs, rhs)); |
| 1598 } | 1385 } |
| 1599 | 1386 |
| 1600 } // namespace internal | 1387 } // namespace internal |
| 1601 } // namespace v8 | 1388 } // namespace v8 |
| OLD | NEW |