OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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.h" | 6 #include "src/builtins/builtins.h" |
6 #include "src/builtins/builtins-utils.h" | 7 #include "src/code-factory.h" |
7 | 8 |
8 namespace v8 { | 9 namespace v8 { |
9 namespace internal { | 10 namespace internal { |
10 | 11 |
11 // ----------------------------------------------------------------------------- | 12 // ----------------------------------------------------------------------------- |
12 // ES6 section 20.1 Number Objects | 13 // ES6 section 20.1 Number Objects |
13 | 14 |
14 // ES6 section 20.1.2.2 Number.isFinite ( number ) | 15 // ES6 section 20.1.2.2 Number.isFinite ( number ) |
15 void Builtins::Generate_NumberIsFinite(CodeStubAssembler* assembler) { | 16 void Builtins::Generate_NumberIsFinite(CodeStubAssembler* assembler) { |
16 typedef CodeStubAssembler::Label Label; | 17 typedef CodeStubAssembler::Label Label; |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 typedef compiler::Node Node; | 363 typedef compiler::Node Node; |
363 | 364 |
364 Node* receiver = assembler->Parameter(0); | 365 Node* receiver = assembler->Parameter(0); |
365 Node* context = assembler->Parameter(3); | 366 Node* context = assembler->Parameter(3); |
366 | 367 |
367 Node* result = assembler->ToThisValue( | 368 Node* result = assembler->ToThisValue( |
368 context, receiver, PrimitiveType::kNumber, "Number.prototype.valueOf"); | 369 context, receiver, PrimitiveType::kNumber, "Number.prototype.valueOf"); |
369 assembler->Return(result); | 370 assembler->Return(result); |
370 } | 371 } |
371 | 372 |
| 373 // static |
| 374 void Builtins::Generate_Add(CodeStubAssembler* assembler) { |
| 375 typedef CodeStubAssembler::Label Label; |
| 376 typedef compiler::Node Node; |
| 377 typedef CodeStubAssembler::Variable Variable; |
| 378 |
| 379 Node* left = assembler->Parameter(0); |
| 380 Node* right = assembler->Parameter(1); |
| 381 Node* context = assembler->Parameter(2); |
| 382 |
| 383 // Shared entry for floating point addition. |
| 384 Label do_fadd(assembler); |
| 385 Variable var_fadd_lhs(assembler, MachineRepresentation::kFloat64), |
| 386 var_fadd_rhs(assembler, MachineRepresentation::kFloat64); |
| 387 |
| 388 // We might need to loop several times due to ToPrimitive, ToString and/or |
| 389 // ToNumber conversions. |
| 390 Variable var_lhs(assembler, MachineRepresentation::kTagged), |
| 391 var_rhs(assembler, MachineRepresentation::kTagged), |
| 392 var_result(assembler, MachineRepresentation::kTagged); |
| 393 Variable* loop_vars[2] = {&var_lhs, &var_rhs}; |
| 394 Label loop(assembler, 2, loop_vars), end(assembler), |
| 395 string_add_convert_left(assembler, Label::kDeferred), |
| 396 string_add_convert_right(assembler, Label::kDeferred); |
| 397 var_lhs.Bind(left); |
| 398 var_rhs.Bind(right); |
| 399 assembler->Goto(&loop); |
| 400 assembler->Bind(&loop); |
| 401 { |
| 402 // Load the current {lhs} and {rhs} values. |
| 403 Node* lhs = var_lhs.value(); |
| 404 Node* rhs = var_rhs.value(); |
| 405 |
| 406 // Check if the {lhs} is a Smi or a HeapObject. |
| 407 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); |
| 408 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); |
| 409 |
| 410 assembler->Bind(&if_lhsissmi); |
| 411 { |
| 412 // Check if the {rhs} is also a Smi. |
| 413 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
| 414 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
| 415 &if_rhsisnotsmi); |
| 416 |
| 417 assembler->Bind(&if_rhsissmi); |
| 418 { |
| 419 // Try fast Smi addition first. |
| 420 Node* pair = assembler->SmiAddWithOverflow(lhs, rhs); |
| 421 Node* overflow = assembler->Projection(1, pair); |
| 422 |
| 423 // Check if the Smi additon overflowed. |
| 424 Label if_overflow(assembler), if_notoverflow(assembler); |
| 425 assembler->Branch(overflow, &if_overflow, &if_notoverflow); |
| 426 |
| 427 assembler->Bind(&if_overflow); |
| 428 { |
| 429 var_fadd_lhs.Bind(assembler->SmiToFloat64(lhs)); |
| 430 var_fadd_rhs.Bind(assembler->SmiToFloat64(rhs)); |
| 431 assembler->Goto(&do_fadd); |
| 432 } |
| 433 |
| 434 assembler->Bind(&if_notoverflow); |
| 435 var_result.Bind(assembler->Projection(0, pair)); |
| 436 assembler->Goto(&end); |
| 437 } |
| 438 |
| 439 assembler->Bind(&if_rhsisnotsmi); |
| 440 { |
| 441 // Load the map of {rhs}. |
| 442 Node* rhs_map = assembler->LoadMap(rhs); |
| 443 |
| 444 // Check if the {rhs} is a HeapNumber. |
| 445 Label if_rhsisnumber(assembler), |
| 446 if_rhsisnotnumber(assembler, Label::kDeferred); |
| 447 assembler->Branch(assembler->IsHeapNumberMap(rhs_map), &if_rhsisnumber, |
| 448 &if_rhsisnotnumber); |
| 449 |
| 450 assembler->Bind(&if_rhsisnumber); |
| 451 { |
| 452 var_fadd_lhs.Bind(assembler->SmiToFloat64(lhs)); |
| 453 var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); |
| 454 assembler->Goto(&do_fadd); |
| 455 } |
| 456 |
| 457 assembler->Bind(&if_rhsisnotnumber); |
| 458 { |
| 459 // Load the instance type of {rhs}. |
| 460 Node* rhs_instance_type = assembler->LoadMapInstanceType(rhs_map); |
| 461 |
| 462 // Check if the {rhs} is a String. |
| 463 Label if_rhsisstring(assembler, Label::kDeferred), |
| 464 if_rhsisnotstring(assembler, Label::kDeferred); |
| 465 assembler->Branch(assembler->IsStringInstanceType(rhs_instance_type), |
| 466 &if_rhsisstring, &if_rhsisnotstring); |
| 467 |
| 468 assembler->Bind(&if_rhsisstring); |
| 469 { |
| 470 var_lhs.Bind(lhs); |
| 471 var_rhs.Bind(rhs); |
| 472 assembler->Goto(&string_add_convert_left); |
| 473 } |
| 474 |
| 475 assembler->Bind(&if_rhsisnotstring); |
| 476 { |
| 477 // Check if {rhs} is a JSReceiver. |
| 478 Label if_rhsisreceiver(assembler, Label::kDeferred), |
| 479 if_rhsisnotreceiver(assembler, Label::kDeferred); |
| 480 assembler->Branch( |
| 481 assembler->IsJSReceiverInstanceType(rhs_instance_type), |
| 482 &if_rhsisreceiver, &if_rhsisnotreceiver); |
| 483 |
| 484 assembler->Bind(&if_rhsisreceiver); |
| 485 { |
| 486 // Convert {rhs} to a primitive first passing no hint. |
| 487 Callable callable = |
| 488 CodeFactory::NonPrimitiveToPrimitive(assembler->isolate()); |
| 489 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
| 490 assembler->Goto(&loop); |
| 491 } |
| 492 |
| 493 assembler->Bind(&if_rhsisnotreceiver); |
| 494 { |
| 495 // Convert {rhs} to a Number first. |
| 496 Callable callable = |
| 497 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 498 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
| 499 assembler->Goto(&loop); |
| 500 } |
| 501 } |
| 502 } |
| 503 } |
| 504 } |
| 505 |
| 506 assembler->Bind(&if_lhsisnotsmi); |
| 507 { |
| 508 // Load the map and instance type of {lhs}. |
| 509 Node* lhs_instance_type = assembler->LoadInstanceType(lhs); |
| 510 |
| 511 // Check if {lhs} is a String. |
| 512 Label if_lhsisstring(assembler), if_lhsisnotstring(assembler); |
| 513 assembler->Branch(assembler->IsStringInstanceType(lhs_instance_type), |
| 514 &if_lhsisstring, &if_lhsisnotstring); |
| 515 |
| 516 assembler->Bind(&if_lhsisstring); |
| 517 { |
| 518 var_lhs.Bind(lhs); |
| 519 var_rhs.Bind(rhs); |
| 520 assembler->Goto(&string_add_convert_right); |
| 521 } |
| 522 |
| 523 assembler->Bind(&if_lhsisnotstring); |
| 524 { |
| 525 // Check if {rhs} is a Smi. |
| 526 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
| 527 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
| 528 &if_rhsisnotsmi); |
| 529 |
| 530 assembler->Bind(&if_rhsissmi); |
| 531 { |
| 532 // Check if {lhs} is a Number. |
| 533 Label if_lhsisnumber(assembler), |
| 534 if_lhsisnotnumber(assembler, Label::kDeferred); |
| 535 assembler->Branch(assembler->Word32Equal( |
| 536 lhs_instance_type, |
| 537 assembler->Int32Constant(HEAP_NUMBER_TYPE)), |
| 538 &if_lhsisnumber, &if_lhsisnotnumber); |
| 539 |
| 540 assembler->Bind(&if_lhsisnumber); |
| 541 { |
| 542 // The {lhs} is a HeapNumber, the {rhs} is a Smi, just add them. |
| 543 var_fadd_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); |
| 544 var_fadd_rhs.Bind(assembler->SmiToFloat64(rhs)); |
| 545 assembler->Goto(&do_fadd); |
| 546 } |
| 547 |
| 548 assembler->Bind(&if_lhsisnotnumber); |
| 549 { |
| 550 // The {lhs} is neither a Number nor a String, and the {rhs} is a |
| 551 // Smi. |
| 552 Label if_lhsisreceiver(assembler, Label::kDeferred), |
| 553 if_lhsisnotreceiver(assembler, Label::kDeferred); |
| 554 assembler->Branch( |
| 555 assembler->IsJSReceiverInstanceType(lhs_instance_type), |
| 556 &if_lhsisreceiver, &if_lhsisnotreceiver); |
| 557 |
| 558 assembler->Bind(&if_lhsisreceiver); |
| 559 { |
| 560 // Convert {lhs} to a primitive first passing no hint. |
| 561 Callable callable = |
| 562 CodeFactory::NonPrimitiveToPrimitive(assembler->isolate()); |
| 563 var_lhs.Bind(assembler->CallStub(callable, context, lhs)); |
| 564 assembler->Goto(&loop); |
| 565 } |
| 566 |
| 567 assembler->Bind(&if_lhsisnotreceiver); |
| 568 { |
| 569 // Convert {lhs} to a Number first. |
| 570 Callable callable = |
| 571 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 572 var_lhs.Bind(assembler->CallStub(callable, context, lhs)); |
| 573 assembler->Goto(&loop); |
| 574 } |
| 575 } |
| 576 } |
| 577 |
| 578 assembler->Bind(&if_rhsisnotsmi); |
| 579 { |
| 580 // Load the instance type of {rhs}. |
| 581 Node* rhs_instance_type = assembler->LoadInstanceType(rhs); |
| 582 |
| 583 // Check if {rhs} is a String. |
| 584 Label if_rhsisstring(assembler), if_rhsisnotstring(assembler); |
| 585 assembler->Branch(assembler->IsStringInstanceType(rhs_instance_type), |
| 586 &if_rhsisstring, &if_rhsisnotstring); |
| 587 |
| 588 assembler->Bind(&if_rhsisstring); |
| 589 { |
| 590 var_lhs.Bind(lhs); |
| 591 var_rhs.Bind(rhs); |
| 592 assembler->Goto(&string_add_convert_left); |
| 593 } |
| 594 |
| 595 assembler->Bind(&if_rhsisnotstring); |
| 596 { |
| 597 // Check if {lhs} is a HeapNumber. |
| 598 Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler); |
| 599 assembler->Branch(assembler->Word32Equal( |
| 600 lhs_instance_type, |
| 601 assembler->Int32Constant(HEAP_NUMBER_TYPE)), |
| 602 &if_lhsisnumber, &if_lhsisnotnumber); |
| 603 |
| 604 assembler->Bind(&if_lhsisnumber); |
| 605 { |
| 606 // Check if {rhs} is also a HeapNumber. |
| 607 Label if_rhsisnumber(assembler), |
| 608 if_rhsisnotnumber(assembler, Label::kDeferred); |
| 609 assembler->Branch(assembler->Word32Equal( |
| 610 rhs_instance_type, |
| 611 assembler->Int32Constant(HEAP_NUMBER_TYPE)), |
| 612 &if_rhsisnumber, &if_rhsisnotnumber); |
| 613 |
| 614 assembler->Bind(&if_rhsisnumber); |
| 615 { |
| 616 // Perform a floating point addition. |
| 617 var_fadd_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); |
| 618 var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); |
| 619 assembler->Goto(&do_fadd); |
| 620 } |
| 621 |
| 622 assembler->Bind(&if_rhsisnotnumber); |
| 623 { |
| 624 // Check if {rhs} is a JSReceiver. |
| 625 Label if_rhsisreceiver(assembler, Label::kDeferred), |
| 626 if_rhsisnotreceiver(assembler, Label::kDeferred); |
| 627 assembler->Branch( |
| 628 assembler->IsJSReceiverInstanceType(rhs_instance_type), |
| 629 &if_rhsisreceiver, &if_rhsisnotreceiver); |
| 630 |
| 631 assembler->Bind(&if_rhsisreceiver); |
| 632 { |
| 633 // Convert {rhs} to a primitive first passing no hint. |
| 634 Callable callable = CodeFactory::NonPrimitiveToPrimitive( |
| 635 assembler->isolate()); |
| 636 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
| 637 assembler->Goto(&loop); |
| 638 } |
| 639 |
| 640 assembler->Bind(&if_rhsisnotreceiver); |
| 641 { |
| 642 // Convert {rhs} to a Number first. |
| 643 Callable callable = |
| 644 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 645 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
| 646 assembler->Goto(&loop); |
| 647 } |
| 648 } |
| 649 } |
| 650 |
| 651 assembler->Bind(&if_lhsisnotnumber); |
| 652 { |
| 653 // Check if {lhs} is a JSReceiver. |
| 654 Label if_lhsisreceiver(assembler, Label::kDeferred), |
| 655 if_lhsisnotreceiver(assembler); |
| 656 assembler->Branch( |
| 657 assembler->IsJSReceiverInstanceType(lhs_instance_type), |
| 658 &if_lhsisreceiver, &if_lhsisnotreceiver); |
| 659 |
| 660 assembler->Bind(&if_lhsisreceiver); |
| 661 { |
| 662 // Convert {lhs} to a primitive first passing no hint. |
| 663 Callable callable = |
| 664 CodeFactory::NonPrimitiveToPrimitive(assembler->isolate()); |
| 665 var_lhs.Bind(assembler->CallStub(callable, context, lhs)); |
| 666 assembler->Goto(&loop); |
| 667 } |
| 668 |
| 669 assembler->Bind(&if_lhsisnotreceiver); |
| 670 { |
| 671 // Check if {rhs} is a JSReceiver. |
| 672 Label if_rhsisreceiver(assembler, Label::kDeferred), |
| 673 if_rhsisnotreceiver(assembler, Label::kDeferred); |
| 674 assembler->Branch( |
| 675 assembler->IsJSReceiverInstanceType(rhs_instance_type), |
| 676 &if_rhsisreceiver, &if_rhsisnotreceiver); |
| 677 |
| 678 assembler->Bind(&if_rhsisreceiver); |
| 679 { |
| 680 // Convert {rhs} to a primitive first passing no hint. |
| 681 Callable callable = CodeFactory::NonPrimitiveToPrimitive( |
| 682 assembler->isolate()); |
| 683 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
| 684 assembler->Goto(&loop); |
| 685 } |
| 686 |
| 687 assembler->Bind(&if_rhsisnotreceiver); |
| 688 { |
| 689 // Convert {lhs} to a Number first. |
| 690 Callable callable = |
| 691 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 692 var_lhs.Bind(assembler->CallStub(callable, context, lhs)); |
| 693 assembler->Goto(&loop); |
| 694 } |
| 695 } |
| 696 } |
| 697 } |
| 698 } |
| 699 } |
| 700 } |
| 701 } |
| 702 assembler->Bind(&string_add_convert_left); |
| 703 { |
| 704 // Convert {lhs}, which is a Smi, to a String and concatenate the |
| 705 // resulting string with the String {rhs}. |
| 706 Callable callable = CodeFactory::StringAdd( |
| 707 assembler->isolate(), STRING_ADD_CONVERT_LEFT, NOT_TENURED); |
| 708 var_result.Bind(assembler->CallStub(callable, context, var_lhs.value(), |
| 709 var_rhs.value())); |
| 710 assembler->Goto(&end); |
| 711 } |
| 712 |
| 713 assembler->Bind(&string_add_convert_right); |
| 714 { |
| 715 // Convert {lhs}, which is a Smi, to a String and concatenate the |
| 716 // resulting string with the String {rhs}. |
| 717 Callable callable = CodeFactory::StringAdd( |
| 718 assembler->isolate(), STRING_ADD_CONVERT_RIGHT, NOT_TENURED); |
| 719 var_result.Bind(assembler->CallStub(callable, context, var_lhs.value(), |
| 720 var_rhs.value())); |
| 721 assembler->Goto(&end); |
| 722 } |
| 723 |
| 724 assembler->Bind(&do_fadd); |
| 725 { |
| 726 Node* lhs_value = var_fadd_lhs.value(); |
| 727 Node* rhs_value = var_fadd_rhs.value(); |
| 728 Node* value = assembler->Float64Add(lhs_value, rhs_value); |
| 729 Node* result = assembler->ChangeFloat64ToTagged(value); |
| 730 var_result.Bind(result); |
| 731 assembler->Goto(&end); |
| 732 } |
| 733 assembler->Bind(&end); |
| 734 assembler->Return(var_result.value()); |
| 735 } |
| 736 |
| 737 void Builtins::Generate_Subtract(CodeStubAssembler* assembler) { |
| 738 typedef CodeStubAssembler::Label Label; |
| 739 typedef compiler::Node Node; |
| 740 typedef CodeStubAssembler::Variable Variable; |
| 741 |
| 742 Node* left = assembler->Parameter(0); |
| 743 Node* right = assembler->Parameter(1); |
| 744 Node* context = assembler->Parameter(2); |
| 745 |
| 746 // Shared entry for floating point subtraction. |
| 747 Label do_fsub(assembler), end(assembler); |
| 748 Variable var_fsub_lhs(assembler, MachineRepresentation::kFloat64), |
| 749 var_fsub_rhs(assembler, MachineRepresentation::kFloat64); |
| 750 |
| 751 // We might need to loop several times due to ToPrimitive and/or ToNumber |
| 752 // conversions. |
| 753 Variable var_lhs(assembler, MachineRepresentation::kTagged), |
| 754 var_rhs(assembler, MachineRepresentation::kTagged), |
| 755 var_result(assembler, MachineRepresentation::kTagged); |
| 756 Variable* loop_vars[2] = {&var_lhs, &var_rhs}; |
| 757 Label loop(assembler, 2, loop_vars); |
| 758 var_lhs.Bind(left); |
| 759 var_rhs.Bind(right); |
| 760 assembler->Goto(&loop); |
| 761 assembler->Bind(&loop); |
| 762 { |
| 763 // Load the current {lhs} and {rhs} values. |
| 764 Node* lhs = var_lhs.value(); |
| 765 Node* rhs = var_rhs.value(); |
| 766 |
| 767 // Check if the {lhs} is a Smi or a HeapObject. |
| 768 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); |
| 769 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); |
| 770 |
| 771 assembler->Bind(&if_lhsissmi); |
| 772 { |
| 773 // Check if the {rhs} is also a Smi. |
| 774 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
| 775 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
| 776 &if_rhsisnotsmi); |
| 777 |
| 778 assembler->Bind(&if_rhsissmi); |
| 779 { |
| 780 // Try a fast Smi subtraction first. |
| 781 Node* pair = assembler->SmiSubWithOverflow(lhs, rhs); |
| 782 Node* overflow = assembler->Projection(1, pair); |
| 783 |
| 784 // Check if the Smi subtraction overflowed. |
| 785 Label if_overflow(assembler), if_notoverflow(assembler); |
| 786 assembler->Branch(overflow, &if_overflow, &if_notoverflow); |
| 787 |
| 788 assembler->Bind(&if_overflow); |
| 789 { |
| 790 // The result doesn't fit into Smi range. |
| 791 var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs)); |
| 792 var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs)); |
| 793 assembler->Goto(&do_fsub); |
| 794 } |
| 795 |
| 796 assembler->Bind(&if_notoverflow); |
| 797 var_result.Bind(assembler->Projection(0, pair)); |
| 798 assembler->Goto(&end); |
| 799 } |
| 800 |
| 801 assembler->Bind(&if_rhsisnotsmi); |
| 802 { |
| 803 // Load the map of the {rhs}. |
| 804 Node* rhs_map = assembler->LoadMap(rhs); |
| 805 |
| 806 // Check if {rhs} is a HeapNumber. |
| 807 Label if_rhsisnumber(assembler), |
| 808 if_rhsisnotnumber(assembler, Label::kDeferred); |
| 809 assembler->Branch(assembler->IsHeapNumberMap(rhs_map), &if_rhsisnumber, |
| 810 &if_rhsisnotnumber); |
| 811 |
| 812 assembler->Bind(&if_rhsisnumber); |
| 813 { |
| 814 // Perform a floating point subtraction. |
| 815 var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs)); |
| 816 var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); |
| 817 assembler->Goto(&do_fsub); |
| 818 } |
| 819 |
| 820 assembler->Bind(&if_rhsisnotnumber); |
| 821 { |
| 822 // Convert the {rhs} to a Number first. |
| 823 Callable callable = |
| 824 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 825 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
| 826 assembler->Goto(&loop); |
| 827 } |
| 828 } |
| 829 } |
| 830 |
| 831 assembler->Bind(&if_lhsisnotsmi); |
| 832 { |
| 833 // Load the map of the {lhs}. |
| 834 Node* lhs_map = assembler->LoadMap(lhs); |
| 835 |
| 836 // Check if the {lhs} is a HeapNumber. |
| 837 Label if_lhsisnumber(assembler), |
| 838 if_lhsisnotnumber(assembler, Label::kDeferred); |
| 839 Node* number_map = assembler->HeapNumberMapConstant(); |
| 840 assembler->Branch(assembler->WordEqual(lhs_map, number_map), |
| 841 &if_lhsisnumber, &if_lhsisnotnumber); |
| 842 |
| 843 assembler->Bind(&if_lhsisnumber); |
| 844 { |
| 845 // Check if the {rhs} is a Smi. |
| 846 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
| 847 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
| 848 &if_rhsisnotsmi); |
| 849 |
| 850 assembler->Bind(&if_rhsissmi); |
| 851 { |
| 852 // Perform a floating point subtraction. |
| 853 var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); |
| 854 var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs)); |
| 855 assembler->Goto(&do_fsub); |
| 856 } |
| 857 |
| 858 assembler->Bind(&if_rhsisnotsmi); |
| 859 { |
| 860 // Load the map of the {rhs}. |
| 861 Node* rhs_map = assembler->LoadMap(rhs); |
| 862 |
| 863 // Check if the {rhs} is a HeapNumber. |
| 864 Label if_rhsisnumber(assembler), |
| 865 if_rhsisnotnumber(assembler, Label::kDeferred); |
| 866 assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
| 867 &if_rhsisnumber, &if_rhsisnotnumber); |
| 868 |
| 869 assembler->Bind(&if_rhsisnumber); |
| 870 { |
| 871 // Perform a floating point subtraction. |
| 872 var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); |
| 873 var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); |
| 874 assembler->Goto(&do_fsub); |
| 875 } |
| 876 |
| 877 assembler->Bind(&if_rhsisnotnumber); |
| 878 { |
| 879 // Convert the {rhs} to a Number first. |
| 880 Callable callable = |
| 881 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 882 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
| 883 assembler->Goto(&loop); |
| 884 } |
| 885 } |
| 886 } |
| 887 |
| 888 assembler->Bind(&if_lhsisnotnumber); |
| 889 { |
| 890 // Convert the {lhs} to a Number first. |
| 891 Callable callable = |
| 892 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 893 var_lhs.Bind(assembler->CallStub(callable, context, lhs)); |
| 894 assembler->Goto(&loop); |
| 895 } |
| 896 } |
| 897 } |
| 898 |
| 899 assembler->Bind(&do_fsub); |
| 900 { |
| 901 Node* lhs_value = var_fsub_lhs.value(); |
| 902 Node* rhs_value = var_fsub_rhs.value(); |
| 903 Node* value = assembler->Float64Sub(lhs_value, rhs_value); |
| 904 var_result.Bind(assembler->ChangeFloat64ToTagged(value)); |
| 905 assembler->Goto(&end); |
| 906 } |
| 907 assembler->Bind(&end); |
| 908 assembler->Return(var_result.value()); |
| 909 } |
| 910 |
| 911 void Builtins::Generate_Multiply(CodeStubAssembler* assembler) { |
| 912 typedef CodeStubAssembler::Label Label; |
| 913 typedef compiler::Node Node; |
| 914 typedef CodeStubAssembler::Variable Variable; |
| 915 |
| 916 Node* left = assembler->Parameter(0); |
| 917 Node* right = assembler->Parameter(1); |
| 918 Node* context = assembler->Parameter(2); |
| 919 |
| 920 // Shared entry point for floating point multiplication. |
| 921 Label do_fmul(assembler), return_result(assembler); |
| 922 Variable var_lhs_float64(assembler, MachineRepresentation::kFloat64), |
| 923 var_rhs_float64(assembler, MachineRepresentation::kFloat64); |
| 924 |
| 925 Node* number_map = assembler->HeapNumberMapConstant(); |
| 926 |
| 927 // We might need to loop one or two times due to ToNumber conversions. |
| 928 Variable var_lhs(assembler, MachineRepresentation::kTagged), |
| 929 var_rhs(assembler, MachineRepresentation::kTagged), |
| 930 var_result(assembler, MachineRepresentation::kTagged); |
| 931 Variable* loop_variables[] = {&var_lhs, &var_rhs}; |
| 932 Label loop(assembler, 2, loop_variables); |
| 933 var_lhs.Bind(left); |
| 934 var_rhs.Bind(right); |
| 935 assembler->Goto(&loop); |
| 936 assembler->Bind(&loop); |
| 937 { |
| 938 Node* lhs = var_lhs.value(); |
| 939 Node* rhs = var_rhs.value(); |
| 940 |
| 941 Label lhs_is_smi(assembler), lhs_is_not_smi(assembler); |
| 942 assembler->Branch(assembler->WordIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi); |
| 943 |
| 944 assembler->Bind(&lhs_is_smi); |
| 945 { |
| 946 Label rhs_is_smi(assembler), rhs_is_not_smi(assembler); |
| 947 assembler->Branch(assembler->WordIsSmi(rhs), &rhs_is_smi, |
| 948 &rhs_is_not_smi); |
| 949 |
| 950 assembler->Bind(&rhs_is_smi); |
| 951 { |
| 952 // Both {lhs} and {rhs} are Smis. The result is not necessarily a smi, |
| 953 // in case of overflow. |
| 954 var_result.Bind(assembler->SmiMul(lhs, rhs)); |
| 955 assembler->Goto(&return_result); |
| 956 } |
| 957 |
| 958 assembler->Bind(&rhs_is_not_smi); |
| 959 { |
| 960 Node* rhs_map = assembler->LoadMap(rhs); |
| 961 |
| 962 // Check if {rhs} is a HeapNumber. |
| 963 Label rhs_is_number(assembler), |
| 964 rhs_is_not_number(assembler, Label::kDeferred); |
| 965 assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
| 966 &rhs_is_number, &rhs_is_not_number); |
| 967 |
| 968 assembler->Bind(&rhs_is_number); |
| 969 { |
| 970 // Convert {lhs} to a double and multiply it with the value of {rhs}. |
| 971 var_lhs_float64.Bind(assembler->SmiToFloat64(lhs)); |
| 972 var_rhs_float64.Bind(assembler->LoadHeapNumberValue(rhs)); |
| 973 assembler->Goto(&do_fmul); |
| 974 } |
| 975 |
| 976 assembler->Bind(&rhs_is_not_number); |
| 977 { |
| 978 // Multiplication is commutative, swap {lhs} with {rhs} and loop. |
| 979 var_lhs.Bind(rhs); |
| 980 var_rhs.Bind(lhs); |
| 981 assembler->Goto(&loop); |
| 982 } |
| 983 } |
| 984 } |
| 985 |
| 986 assembler->Bind(&lhs_is_not_smi); |
| 987 { |
| 988 Node* lhs_map = assembler->LoadMap(lhs); |
| 989 |
| 990 // Check if {lhs} is a HeapNumber. |
| 991 Label lhs_is_number(assembler), |
| 992 lhs_is_not_number(assembler, Label::kDeferred); |
| 993 assembler->Branch(assembler->WordEqual(lhs_map, number_map), |
| 994 &lhs_is_number, &lhs_is_not_number); |
| 995 |
| 996 assembler->Bind(&lhs_is_number); |
| 997 { |
| 998 // Check if {rhs} is a Smi. |
| 999 Label rhs_is_smi(assembler), rhs_is_not_smi(assembler); |
| 1000 assembler->Branch(assembler->WordIsSmi(rhs), &rhs_is_smi, |
| 1001 &rhs_is_not_smi); |
| 1002 |
| 1003 assembler->Bind(&rhs_is_smi); |
| 1004 { |
| 1005 // Convert {rhs} to a double and multiply it with the value of {lhs}. |
| 1006 var_lhs_float64.Bind(assembler->LoadHeapNumberValue(lhs)); |
| 1007 var_rhs_float64.Bind(assembler->SmiToFloat64(rhs)); |
| 1008 assembler->Goto(&do_fmul); |
| 1009 } |
| 1010 |
| 1011 assembler->Bind(&rhs_is_not_smi); |
| 1012 { |
| 1013 Node* rhs_map = assembler->LoadMap(rhs); |
| 1014 |
| 1015 // Check if {rhs} is a HeapNumber. |
| 1016 Label rhs_is_number(assembler), |
| 1017 rhs_is_not_number(assembler, Label::kDeferred); |
| 1018 assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
| 1019 &rhs_is_number, &rhs_is_not_number); |
| 1020 |
| 1021 assembler->Bind(&rhs_is_number); |
| 1022 { |
| 1023 // Both {lhs} and {rhs} are HeapNumbers. Load their values and |
| 1024 // multiply them. |
| 1025 var_lhs_float64.Bind(assembler->LoadHeapNumberValue(lhs)); |
| 1026 var_rhs_float64.Bind(assembler->LoadHeapNumberValue(rhs)); |
| 1027 assembler->Goto(&do_fmul); |
| 1028 } |
| 1029 |
| 1030 assembler->Bind(&rhs_is_not_number); |
| 1031 { |
| 1032 // Multiplication is commutative, swap {lhs} with {rhs} and loop. |
| 1033 var_lhs.Bind(rhs); |
| 1034 var_rhs.Bind(lhs); |
| 1035 assembler->Goto(&loop); |
| 1036 } |
| 1037 } |
| 1038 } |
| 1039 |
| 1040 assembler->Bind(&lhs_is_not_number); |
| 1041 { |
| 1042 // Convert {lhs} to a Number and loop. |
| 1043 Callable callable = |
| 1044 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 1045 var_lhs.Bind(assembler->CallStub(callable, context, lhs)); |
| 1046 assembler->Goto(&loop); |
| 1047 } |
| 1048 } |
| 1049 } |
| 1050 |
| 1051 assembler->Bind(&do_fmul); |
| 1052 { |
| 1053 Node* value = |
| 1054 assembler->Float64Mul(var_lhs_float64.value(), var_rhs_float64.value()); |
| 1055 Node* result = assembler->ChangeFloat64ToTagged(value); |
| 1056 var_result.Bind(result); |
| 1057 assembler->Goto(&return_result); |
| 1058 } |
| 1059 |
| 1060 assembler->Bind(&return_result); |
| 1061 assembler->Return(var_result.value()); |
| 1062 } |
| 1063 |
| 1064 void Builtins::Generate_Divide(CodeStubAssembler* assembler) { |
| 1065 typedef CodeStubAssembler::Label Label; |
| 1066 typedef compiler::Node Node; |
| 1067 typedef CodeStubAssembler::Variable Variable; |
| 1068 |
| 1069 Node* left = assembler->Parameter(0); |
| 1070 Node* right = assembler->Parameter(1); |
| 1071 Node* context = assembler->Parameter(2); |
| 1072 |
| 1073 // Shared entry point for floating point division. |
| 1074 Label do_fdiv(assembler), end(assembler); |
| 1075 Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64), |
| 1076 var_divisor_float64(assembler, MachineRepresentation::kFloat64); |
| 1077 |
| 1078 Node* number_map = assembler->HeapNumberMapConstant(); |
| 1079 |
| 1080 // We might need to loop one or two times due to ToNumber conversions. |
| 1081 Variable var_dividend(assembler, MachineRepresentation::kTagged), |
| 1082 var_divisor(assembler, MachineRepresentation::kTagged), |
| 1083 var_result(assembler, MachineRepresentation::kTagged); |
| 1084 Variable* loop_variables[] = {&var_dividend, &var_divisor}; |
| 1085 Label loop(assembler, 2, loop_variables); |
| 1086 var_dividend.Bind(left); |
| 1087 var_divisor.Bind(right); |
| 1088 assembler->Goto(&loop); |
| 1089 assembler->Bind(&loop); |
| 1090 { |
| 1091 Node* dividend = var_dividend.value(); |
| 1092 Node* divisor = var_divisor.value(); |
| 1093 |
| 1094 Label dividend_is_smi(assembler), dividend_is_not_smi(assembler); |
| 1095 assembler->Branch(assembler->WordIsSmi(dividend), ÷nd_is_smi, |
| 1096 ÷nd_is_not_smi); |
| 1097 |
| 1098 assembler->Bind(÷nd_is_smi); |
| 1099 { |
| 1100 Label divisor_is_smi(assembler), divisor_is_not_smi(assembler); |
| 1101 assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi, |
| 1102 &divisor_is_not_smi); |
| 1103 |
| 1104 assembler->Bind(&divisor_is_smi); |
| 1105 { |
| 1106 Label bailout(assembler); |
| 1107 |
| 1108 // Do floating point division if {divisor} is zero. |
| 1109 assembler->GotoIf( |
| 1110 assembler->WordEqual(divisor, assembler->IntPtrConstant(0)), |
| 1111 &bailout); |
| 1112 |
| 1113 // Do floating point division {dividend} is zero and {divisor} is |
| 1114 // negative. |
| 1115 Label dividend_is_zero(assembler), dividend_is_not_zero(assembler); |
| 1116 assembler->Branch( |
| 1117 assembler->WordEqual(dividend, assembler->IntPtrConstant(0)), |
| 1118 ÷nd_is_zero, ÷nd_is_not_zero); |
| 1119 |
| 1120 assembler->Bind(÷nd_is_zero); |
| 1121 { |
| 1122 assembler->GotoIf( |
| 1123 assembler->IntPtrLessThan(divisor, assembler->IntPtrConstant(0)), |
| 1124 &bailout); |
| 1125 assembler->Goto(÷nd_is_not_zero); |
| 1126 } |
| 1127 assembler->Bind(÷nd_is_not_zero); |
| 1128 |
| 1129 Node* untagged_divisor = assembler->SmiUntag(divisor); |
| 1130 Node* untagged_dividend = assembler->SmiUntag(dividend); |
| 1131 |
| 1132 // Do floating point division if {dividend} is kMinInt (or kMinInt - 1 |
| 1133 // if the Smi size is 31) and {divisor} is -1. |
| 1134 Label divisor_is_minus_one(assembler), |
| 1135 divisor_is_not_minus_one(assembler); |
| 1136 assembler->Branch(assembler->Word32Equal(untagged_divisor, |
| 1137 assembler->Int32Constant(-1)), |
| 1138 &divisor_is_minus_one, &divisor_is_not_minus_one); |
| 1139 |
| 1140 assembler->Bind(&divisor_is_minus_one); |
| 1141 { |
| 1142 assembler->GotoIf( |
| 1143 assembler->Word32Equal( |
| 1144 untagged_dividend, |
| 1145 assembler->Int32Constant( |
| 1146 kSmiValueSize == 32 ? kMinInt : (kMinInt >> 1))), |
| 1147 &bailout); |
| 1148 assembler->Goto(&divisor_is_not_minus_one); |
| 1149 } |
| 1150 assembler->Bind(&divisor_is_not_minus_one); |
| 1151 |
| 1152 // TODO(epertoso): consider adding a machine instruction that returns |
| 1153 // both the result and the remainder. |
| 1154 Node* untagged_result = |
| 1155 assembler->Int32Div(untagged_dividend, untagged_divisor); |
| 1156 Node* truncated = |
| 1157 assembler->Int32Mul(untagged_result, untagged_divisor); |
| 1158 // Do floating point division if the remainder is not 0. |
| 1159 assembler->GotoIf( |
| 1160 assembler->Word32NotEqual(untagged_dividend, truncated), &bailout); |
| 1161 var_result.Bind(assembler->SmiTag(untagged_result)); |
| 1162 assembler->Goto(&end); |
| 1163 |
| 1164 // Bailout: convert {dividend} and {divisor} to double and do double |
| 1165 // division. |
| 1166 assembler->Bind(&bailout); |
| 1167 { |
| 1168 var_dividend_float64.Bind(assembler->SmiToFloat64(dividend)); |
| 1169 var_divisor_float64.Bind(assembler->SmiToFloat64(divisor)); |
| 1170 assembler->Goto(&do_fdiv); |
| 1171 } |
| 1172 } |
| 1173 |
| 1174 assembler->Bind(&divisor_is_not_smi); |
| 1175 { |
| 1176 Node* divisor_map = assembler->LoadMap(divisor); |
| 1177 |
| 1178 // Check if {divisor} is a HeapNumber. |
| 1179 Label divisor_is_number(assembler), |
| 1180 divisor_is_not_number(assembler, Label::kDeferred); |
| 1181 assembler->Branch(assembler->WordEqual(divisor_map, number_map), |
| 1182 &divisor_is_number, &divisor_is_not_number); |
| 1183 |
| 1184 assembler->Bind(&divisor_is_number); |
| 1185 { |
| 1186 // Convert {dividend} to a double and divide it with the value of |
| 1187 // {divisor}. |
| 1188 var_dividend_float64.Bind(assembler->SmiToFloat64(dividend)); |
| 1189 var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor)); |
| 1190 assembler->Goto(&do_fdiv); |
| 1191 } |
| 1192 |
| 1193 assembler->Bind(&divisor_is_not_number); |
| 1194 { |
| 1195 // Convert {divisor} to a number and loop. |
| 1196 Callable callable = |
| 1197 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 1198 var_divisor.Bind(assembler->CallStub(callable, context, divisor)); |
| 1199 assembler->Goto(&loop); |
| 1200 } |
| 1201 } |
| 1202 } |
| 1203 |
| 1204 assembler->Bind(÷nd_is_not_smi); |
| 1205 { |
| 1206 Node* dividend_map = assembler->LoadMap(dividend); |
| 1207 |
| 1208 // Check if {dividend} is a HeapNumber. |
| 1209 Label dividend_is_number(assembler), |
| 1210 dividend_is_not_number(assembler, Label::kDeferred); |
| 1211 assembler->Branch(assembler->WordEqual(dividend_map, number_map), |
| 1212 ÷nd_is_number, ÷nd_is_not_number); |
| 1213 |
| 1214 assembler->Bind(÷nd_is_number); |
| 1215 { |
| 1216 // Check if {divisor} is a Smi. |
| 1217 Label divisor_is_smi(assembler), divisor_is_not_smi(assembler); |
| 1218 assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi, |
| 1219 &divisor_is_not_smi); |
| 1220 |
| 1221 assembler->Bind(&divisor_is_smi); |
| 1222 { |
| 1223 // Convert {divisor} to a double and use it for a floating point |
| 1224 // division. |
| 1225 var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend)); |
| 1226 var_divisor_float64.Bind(assembler->SmiToFloat64(divisor)); |
| 1227 assembler->Goto(&do_fdiv); |
| 1228 } |
| 1229 |
| 1230 assembler->Bind(&divisor_is_not_smi); |
| 1231 { |
| 1232 Node* divisor_map = assembler->LoadMap(divisor); |
| 1233 |
| 1234 // Check if {divisor} is a HeapNumber. |
| 1235 Label divisor_is_number(assembler), |
| 1236 divisor_is_not_number(assembler, Label::kDeferred); |
| 1237 assembler->Branch(assembler->WordEqual(divisor_map, number_map), |
| 1238 &divisor_is_number, &divisor_is_not_number); |
| 1239 |
| 1240 assembler->Bind(&divisor_is_number); |
| 1241 { |
| 1242 // Both {dividend} and {divisor} are HeapNumbers. Load their values |
| 1243 // and divide them. |
| 1244 var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend)); |
| 1245 var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor)); |
| 1246 assembler->Goto(&do_fdiv); |
| 1247 } |
| 1248 |
| 1249 assembler->Bind(&divisor_is_not_number); |
| 1250 { |
| 1251 // Convert {divisor} to a number and loop. |
| 1252 Callable callable = |
| 1253 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 1254 var_divisor.Bind(assembler->CallStub(callable, context, divisor)); |
| 1255 assembler->Goto(&loop); |
| 1256 } |
| 1257 } |
| 1258 } |
| 1259 |
| 1260 assembler->Bind(÷nd_is_not_number); |
| 1261 { |
| 1262 // Convert {dividend} to a Number and loop. |
| 1263 Callable callable = |
| 1264 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 1265 var_dividend.Bind(assembler->CallStub(callable, context, dividend)); |
| 1266 assembler->Goto(&loop); |
| 1267 } |
| 1268 } |
| 1269 } |
| 1270 |
| 1271 assembler->Bind(&do_fdiv); |
| 1272 { |
| 1273 Node* value = assembler->Float64Div(var_dividend_float64.value(), |
| 1274 var_divisor_float64.value()); |
| 1275 var_result.Bind(assembler->ChangeFloat64ToTagged(value)); |
| 1276 assembler->Goto(&end); |
| 1277 } |
| 1278 assembler->Bind(&end); |
| 1279 assembler->Return(var_result.value()); |
| 1280 } |
| 1281 |
| 1282 void Builtins::Generate_Modulus(CodeStubAssembler* assembler) { |
| 1283 typedef CodeStubAssembler::Label Label; |
| 1284 typedef compiler::Node Node; |
| 1285 typedef CodeStubAssembler::Variable Variable; |
| 1286 |
| 1287 Node* left = assembler->Parameter(0); |
| 1288 Node* right = assembler->Parameter(1); |
| 1289 Node* context = assembler->Parameter(2); |
| 1290 |
| 1291 Variable var_result(assembler, MachineRepresentation::kTagged); |
| 1292 Label return_result(assembler, &var_result); |
| 1293 |
| 1294 // Shared entry point for floating point modulus. |
| 1295 Label do_fmod(assembler); |
| 1296 Variable var_dividend_float64(assembler, MachineRepresentation::kFloat64), |
| 1297 var_divisor_float64(assembler, MachineRepresentation::kFloat64); |
| 1298 |
| 1299 Node* number_map = assembler->HeapNumberMapConstant(); |
| 1300 |
| 1301 // We might need to loop one or two times due to ToNumber conversions. |
| 1302 Variable var_dividend(assembler, MachineRepresentation::kTagged), |
| 1303 var_divisor(assembler, MachineRepresentation::kTagged); |
| 1304 Variable* loop_variables[] = {&var_dividend, &var_divisor}; |
| 1305 Label loop(assembler, 2, loop_variables); |
| 1306 var_dividend.Bind(left); |
| 1307 var_divisor.Bind(right); |
| 1308 assembler->Goto(&loop); |
| 1309 assembler->Bind(&loop); |
| 1310 { |
| 1311 Node* dividend = var_dividend.value(); |
| 1312 Node* divisor = var_divisor.value(); |
| 1313 |
| 1314 Label dividend_is_smi(assembler), dividend_is_not_smi(assembler); |
| 1315 assembler->Branch(assembler->WordIsSmi(dividend), ÷nd_is_smi, |
| 1316 ÷nd_is_not_smi); |
| 1317 |
| 1318 assembler->Bind(÷nd_is_smi); |
| 1319 { |
| 1320 Label dividend_is_not_zero(assembler); |
| 1321 Label divisor_is_smi(assembler), divisor_is_not_smi(assembler); |
| 1322 assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi, |
| 1323 &divisor_is_not_smi); |
| 1324 |
| 1325 assembler->Bind(&divisor_is_smi); |
| 1326 { |
| 1327 // Compute the modulus of two Smis. |
| 1328 var_result.Bind(assembler->SmiMod(dividend, divisor)); |
| 1329 assembler->Goto(&return_result); |
| 1330 } |
| 1331 |
| 1332 assembler->Bind(&divisor_is_not_smi); |
| 1333 { |
| 1334 Node* divisor_map = assembler->LoadMap(divisor); |
| 1335 |
| 1336 // Check if {divisor} is a HeapNumber. |
| 1337 Label divisor_is_number(assembler), |
| 1338 divisor_is_not_number(assembler, Label::kDeferred); |
| 1339 assembler->Branch(assembler->WordEqual(divisor_map, number_map), |
| 1340 &divisor_is_number, &divisor_is_not_number); |
| 1341 |
| 1342 assembler->Bind(&divisor_is_number); |
| 1343 { |
| 1344 // Convert {dividend} to a double and compute its modulus with the |
| 1345 // value of {dividend}. |
| 1346 var_dividend_float64.Bind(assembler->SmiToFloat64(dividend)); |
| 1347 var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor)); |
| 1348 assembler->Goto(&do_fmod); |
| 1349 } |
| 1350 |
| 1351 assembler->Bind(&divisor_is_not_number); |
| 1352 { |
| 1353 // Convert {divisor} to a number and loop. |
| 1354 Callable callable = |
| 1355 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 1356 var_divisor.Bind(assembler->CallStub(callable, context, divisor)); |
| 1357 assembler->Goto(&loop); |
| 1358 } |
| 1359 } |
| 1360 } |
| 1361 |
| 1362 assembler->Bind(÷nd_is_not_smi); |
| 1363 { |
| 1364 Node* dividend_map = assembler->LoadMap(dividend); |
| 1365 |
| 1366 // Check if {dividend} is a HeapNumber. |
| 1367 Label dividend_is_number(assembler), |
| 1368 dividend_is_not_number(assembler, Label::kDeferred); |
| 1369 assembler->Branch(assembler->WordEqual(dividend_map, number_map), |
| 1370 ÷nd_is_number, ÷nd_is_not_number); |
| 1371 |
| 1372 assembler->Bind(÷nd_is_number); |
| 1373 { |
| 1374 // Check if {divisor} is a Smi. |
| 1375 Label divisor_is_smi(assembler), divisor_is_not_smi(assembler); |
| 1376 assembler->Branch(assembler->WordIsSmi(divisor), &divisor_is_smi, |
| 1377 &divisor_is_not_smi); |
| 1378 |
| 1379 assembler->Bind(&divisor_is_smi); |
| 1380 { |
| 1381 // Convert {divisor} to a double and compute {dividend}'s modulus with |
| 1382 // it. |
| 1383 var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend)); |
| 1384 var_divisor_float64.Bind(assembler->SmiToFloat64(divisor)); |
| 1385 assembler->Goto(&do_fmod); |
| 1386 } |
| 1387 |
| 1388 assembler->Bind(&divisor_is_not_smi); |
| 1389 { |
| 1390 Node* divisor_map = assembler->LoadMap(divisor); |
| 1391 |
| 1392 // Check if {divisor} is a HeapNumber. |
| 1393 Label divisor_is_number(assembler), |
| 1394 divisor_is_not_number(assembler, Label::kDeferred); |
| 1395 assembler->Branch(assembler->WordEqual(divisor_map, number_map), |
| 1396 &divisor_is_number, &divisor_is_not_number); |
| 1397 |
| 1398 assembler->Bind(&divisor_is_number); |
| 1399 { |
| 1400 // Both {dividend} and {divisor} are HeapNumbers. Load their values |
| 1401 // and compute their modulus. |
| 1402 var_dividend_float64.Bind(assembler->LoadHeapNumberValue(dividend)); |
| 1403 var_divisor_float64.Bind(assembler->LoadHeapNumberValue(divisor)); |
| 1404 assembler->Goto(&do_fmod); |
| 1405 } |
| 1406 |
| 1407 assembler->Bind(&divisor_is_not_number); |
| 1408 { |
| 1409 // Convert {divisor} to a number and loop. |
| 1410 Callable callable = |
| 1411 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 1412 var_divisor.Bind(assembler->CallStub(callable, context, divisor)); |
| 1413 assembler->Goto(&loop); |
| 1414 } |
| 1415 } |
| 1416 } |
| 1417 |
| 1418 assembler->Bind(÷nd_is_not_number); |
| 1419 { |
| 1420 // Convert {dividend} to a Number and loop. |
| 1421 Callable callable = |
| 1422 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 1423 var_dividend.Bind(assembler->CallStub(callable, context, dividend)); |
| 1424 assembler->Goto(&loop); |
| 1425 } |
| 1426 } |
| 1427 } |
| 1428 |
| 1429 assembler->Bind(&do_fmod); |
| 1430 { |
| 1431 Node* value = assembler->Float64Mod(var_dividend_float64.value(), |
| 1432 var_divisor_float64.value()); |
| 1433 var_result.Bind(assembler->ChangeFloat64ToTagged(value)); |
| 1434 assembler->Goto(&return_result); |
| 1435 } |
| 1436 |
| 1437 assembler->Bind(&return_result); |
| 1438 assembler->Return(var_result.value()); |
| 1439 } |
| 1440 |
| 1441 void Builtins::Generate_ShiftLeft(CodeStubAssembler* assembler) { |
| 1442 compiler::Node* left = assembler->Parameter(0); |
| 1443 compiler::Node* right = assembler->Parameter(1); |
| 1444 compiler::Node* context = assembler->Parameter(2); |
| 1445 |
| 1446 using compiler::Node; |
| 1447 |
| 1448 Node* lhs_value = assembler->TruncateTaggedToWord32(context, left); |
| 1449 Node* rhs_value = assembler->TruncateTaggedToWord32(context, right); |
| 1450 Node* shift_count = |
| 1451 assembler->Word32And(rhs_value, assembler->Int32Constant(0x1f)); |
| 1452 Node* value = assembler->Word32Shl(lhs_value, shift_count); |
| 1453 Node* result = assembler->ChangeInt32ToTagged(value); |
| 1454 assembler->Return(result); |
| 1455 } |
| 1456 |
| 1457 void Builtins::Generate_ShiftRight(CodeStubAssembler* assembler) { |
| 1458 compiler::Node* left = assembler->Parameter(0); |
| 1459 compiler::Node* right = assembler->Parameter(1); |
| 1460 compiler::Node* context = assembler->Parameter(2); |
| 1461 |
| 1462 using compiler::Node; |
| 1463 |
| 1464 Node* lhs_value = assembler->TruncateTaggedToWord32(context, left); |
| 1465 Node* rhs_value = assembler->TruncateTaggedToWord32(context, right); |
| 1466 Node* shift_count = |
| 1467 assembler->Word32And(rhs_value, assembler->Int32Constant(0x1f)); |
| 1468 Node* value = assembler->Word32Sar(lhs_value, shift_count); |
| 1469 Node* result = assembler->ChangeInt32ToTagged(value); |
| 1470 assembler->Return(result); |
| 1471 } |
| 1472 |
| 1473 void Builtins::Generate_ShiftRightLogical(CodeStubAssembler* assembler) { |
| 1474 compiler::Node* left = assembler->Parameter(0); |
| 1475 compiler::Node* right = assembler->Parameter(1); |
| 1476 compiler::Node* context = assembler->Parameter(2); |
| 1477 |
| 1478 using compiler::Node; |
| 1479 |
| 1480 Node* lhs_value = assembler->TruncateTaggedToWord32(context, left); |
| 1481 Node* rhs_value = assembler->TruncateTaggedToWord32(context, right); |
| 1482 Node* shift_count = |
| 1483 assembler->Word32And(rhs_value, assembler->Int32Constant(0x1f)); |
| 1484 Node* value = assembler->Word32Shr(lhs_value, shift_count); |
| 1485 Node* result = assembler->ChangeUint32ToTagged(value); |
| 1486 assembler->Return(result); |
| 1487 } |
| 1488 |
| 1489 void Builtins::Generate_BitwiseAnd(CodeStubAssembler* assembler) { |
| 1490 compiler::Node* left = assembler->Parameter(0); |
| 1491 compiler::Node* right = assembler->Parameter(1); |
| 1492 compiler::Node* context = assembler->Parameter(2); |
| 1493 |
| 1494 using compiler::Node; |
| 1495 |
| 1496 Node* lhs_value = assembler->TruncateTaggedToWord32(context, left); |
| 1497 Node* rhs_value = assembler->TruncateTaggedToWord32(context, right); |
| 1498 Node* value = assembler->Word32And(lhs_value, rhs_value); |
| 1499 Node* result = assembler->ChangeInt32ToTagged(value); |
| 1500 assembler->Return(result); |
| 1501 } |
| 1502 |
| 1503 void Builtins::Generate_BitwiseOr(CodeStubAssembler* assembler) { |
| 1504 compiler::Node* left = assembler->Parameter(0); |
| 1505 compiler::Node* right = assembler->Parameter(1); |
| 1506 compiler::Node* context = assembler->Parameter(2); |
| 1507 |
| 1508 using compiler::Node; |
| 1509 |
| 1510 Node* lhs_value = assembler->TruncateTaggedToWord32(context, left); |
| 1511 Node* rhs_value = assembler->TruncateTaggedToWord32(context, right); |
| 1512 Node* value = assembler->Word32Or(lhs_value, rhs_value); |
| 1513 Node* result = assembler->ChangeInt32ToTagged(value); |
| 1514 assembler->Return(result); |
| 1515 } |
| 1516 |
| 1517 void Builtins::Generate_BitwiseXor(CodeStubAssembler* assembler) { |
| 1518 compiler::Node* left = assembler->Parameter(0); |
| 1519 compiler::Node* right = assembler->Parameter(1); |
| 1520 compiler::Node* context = assembler->Parameter(2); |
| 1521 |
| 1522 using compiler::Node; |
| 1523 |
| 1524 Node* lhs_value = assembler->TruncateTaggedToWord32(context, left); |
| 1525 Node* rhs_value = assembler->TruncateTaggedToWord32(context, right); |
| 1526 Node* value = assembler->Word32Xor(lhs_value, rhs_value); |
| 1527 Node* result = assembler->ChangeInt32ToTagged(value); |
| 1528 assembler->Return(result); |
| 1529 } |
| 1530 |
| 1531 void Builtins::Generate_LessThan(CodeStubAssembler* assembler) { |
| 1532 compiler::Node* lhs = assembler->Parameter(0); |
| 1533 compiler::Node* rhs = assembler->Parameter(1); |
| 1534 compiler::Node* context = assembler->Parameter(2); |
| 1535 |
| 1536 assembler->Return(assembler->RelationalComparison( |
| 1537 CodeStubAssembler::kLessThan, lhs, rhs, context)); |
| 1538 } |
| 1539 |
| 1540 void Builtins::Generate_LessThanOrEqual(CodeStubAssembler* assembler) { |
| 1541 compiler::Node* lhs = assembler->Parameter(0); |
| 1542 compiler::Node* rhs = assembler->Parameter(1); |
| 1543 compiler::Node* context = assembler->Parameter(2); |
| 1544 |
| 1545 assembler->Return(assembler->RelationalComparison( |
| 1546 CodeStubAssembler::kLessThanOrEqual, lhs, rhs, context)); |
| 1547 } |
| 1548 |
| 1549 void Builtins::Generate_GreaterThan(CodeStubAssembler* assembler) { |
| 1550 compiler::Node* lhs = assembler->Parameter(0); |
| 1551 compiler::Node* rhs = assembler->Parameter(1); |
| 1552 compiler::Node* context = assembler->Parameter(2); |
| 1553 |
| 1554 assembler->Return(assembler->RelationalComparison( |
| 1555 CodeStubAssembler::kGreaterThan, lhs, rhs, context)); |
| 1556 } |
| 1557 |
| 1558 void Builtins::Generate_GreaterThanOrEqual(CodeStubAssembler* assembler) { |
| 1559 compiler::Node* lhs = assembler->Parameter(0); |
| 1560 compiler::Node* rhs = assembler->Parameter(1); |
| 1561 compiler::Node* context = assembler->Parameter(2); |
| 1562 |
| 1563 assembler->Return(assembler->RelationalComparison( |
| 1564 CodeStubAssembler::kGreaterThanOrEqual, lhs, rhs, context)); |
| 1565 } |
| 1566 |
| 1567 void Builtins::Generate_Equal(CodeStubAssembler* assembler) { |
| 1568 compiler::Node* lhs = assembler->Parameter(0); |
| 1569 compiler::Node* rhs = assembler->Parameter(1); |
| 1570 compiler::Node* context = assembler->Parameter(2); |
| 1571 |
| 1572 assembler->Return(assembler->Equal(CodeStubAssembler::kDontNegateResult, lhs, |
| 1573 rhs, context)); |
| 1574 } |
| 1575 |
| 1576 void Builtins::Generate_NotEqual(CodeStubAssembler* assembler) { |
| 1577 compiler::Node* lhs = assembler->Parameter(0); |
| 1578 compiler::Node* rhs = assembler->Parameter(1); |
| 1579 compiler::Node* context = assembler->Parameter(2); |
| 1580 |
| 1581 assembler->Return( |
| 1582 assembler->Equal(CodeStubAssembler::kNegateResult, lhs, rhs, context)); |
| 1583 } |
| 1584 |
| 1585 void Builtins::Generate_StrictEqual(CodeStubAssembler* assembler) { |
| 1586 compiler::Node* lhs = assembler->Parameter(0); |
| 1587 compiler::Node* rhs = assembler->Parameter(1); |
| 1588 compiler::Node* context = assembler->Parameter(2); |
| 1589 |
| 1590 assembler->Return(assembler->StrictEqual(CodeStubAssembler::kDontNegateResult, |
| 1591 lhs, rhs, context)); |
| 1592 } |
| 1593 |
| 1594 void Builtins::Generate_StrictNotEqual(CodeStubAssembler* assembler) { |
| 1595 compiler::Node* lhs = assembler->Parameter(0); |
| 1596 compiler::Node* rhs = assembler->Parameter(1); |
| 1597 compiler::Node* context = assembler->Parameter(2); |
| 1598 |
| 1599 assembler->Return(assembler->StrictEqual(CodeStubAssembler::kNegateResult, |
| 1600 lhs, rhs, context)); |
| 1601 } |
| 1602 |
372 } // namespace internal | 1603 } // namespace internal |
373 } // namespace v8 | 1604 } // namespace v8 |
OLD | NEW |