OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/code-stubs.h" | 5 #include "src/code-stubs.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 void StringLengthStub::GenerateAssembly( | 508 void StringLengthStub::GenerateAssembly( |
509 compiler::CodeStubAssembler* assembler) const { | 509 compiler::CodeStubAssembler* assembler) const { |
510 compiler::Node* value = assembler->Parameter(0); | 510 compiler::Node* value = assembler->Parameter(0); |
511 compiler::Node* string = | 511 compiler::Node* string = |
512 assembler->LoadObjectField(value, JSValue::kValueOffset); | 512 assembler->LoadObjectField(value, JSValue::kValueOffset); |
513 compiler::Node* result = | 513 compiler::Node* result = |
514 assembler->LoadObjectField(string, String::kLengthOffset); | 514 assembler->LoadObjectField(string, String::kLengthOffset); |
515 assembler->Return(result); | 515 assembler->Return(result); |
516 } | 516 } |
517 | 517 |
| 518 void AddStub::GenerateAssembly(compiler::CodeStubAssembler* assembler) const { |
| 519 typedef compiler::CodeStubAssembler::Label Label; |
| 520 typedef compiler::Node Node; |
| 521 typedef compiler::CodeStubAssembler::Variable Variable; |
| 522 |
| 523 Node* context = assembler->Parameter(2); |
| 524 |
| 525 // Shared entry for floating point addition. |
| 526 Label do_fadd(assembler); |
| 527 Variable var_fadd_lhs(assembler, MachineRepresentation::kFloat64), |
| 528 var_fadd_rhs(assembler, MachineRepresentation::kFloat64); |
| 529 |
| 530 // We might need to loop several times due to ToPrimitive, ToString and/or |
| 531 // ToNumber conversions. |
| 532 Variable var_lhs(assembler, MachineRepresentation::kTagged), |
| 533 var_rhs(assembler, MachineRepresentation::kTagged); |
| 534 Variable* loop_vars[2] = {&var_lhs, &var_rhs}; |
| 535 Label loop(assembler, 2, loop_vars); |
| 536 var_lhs.Bind(assembler->Parameter(0)); |
| 537 var_rhs.Bind(assembler->Parameter(1)); |
| 538 assembler->Goto(&loop); |
| 539 assembler->Bind(&loop); |
| 540 { |
| 541 // Load the current {lhs} and {rhs} values. |
| 542 Node* lhs = var_lhs.value(); |
| 543 Node* rhs = var_rhs.value(); |
| 544 |
| 545 // Check if the {lhs} is a Smi or a HeapObject. |
| 546 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); |
| 547 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); |
| 548 |
| 549 assembler->Bind(&if_lhsissmi); |
| 550 { |
| 551 // Check if the {rhs} is also a Smi. |
| 552 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
| 553 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
| 554 &if_rhsisnotsmi); |
| 555 |
| 556 assembler->Bind(&if_rhsissmi); |
| 557 { |
| 558 // TODO(bmeurer): Properly fuse Int64AddWithOverflow on x64 |
| 559 Node* pair = assembler->SmiAddWithOverflow(lhs, rhs); |
| 560 Node* result = assembler->Projection(0, pair); |
| 561 Node* overflow = assembler->Projection(1, pair); |
| 562 |
| 563 Label if_overflow(assembler), if_notoverflow(assembler); |
| 564 assembler->Branch(overflow, &if_overflow, &if_notoverflow); |
| 565 |
| 566 assembler->Bind(&if_overflow); |
| 567 { |
| 568 var_fadd_lhs.Bind(assembler->SmiToFloat64(lhs)); |
| 569 var_fadd_rhs.Bind(assembler->SmiToFloat64(rhs)); |
| 570 assembler->Goto(&do_fadd); |
| 571 } |
| 572 |
| 573 assembler->Bind(&if_notoverflow); |
| 574 assembler->Return(result); |
| 575 } |
| 576 |
| 577 assembler->Bind(&if_rhsisnotsmi); |
| 578 { |
| 579 // Load the map of {rhs}. |
| 580 Node* rhs_map = assembler->LoadObjectField(rhs, HeapObject::kMapOffset); |
| 581 |
| 582 // Check if the {rhs} is a HeapNumber. |
| 583 Label if_rhsisnumber(assembler), |
| 584 if_rhsisnotnumber(assembler, Label::kDeferred); |
| 585 Node* number_map = assembler->HeapNumberMapConstant(); |
| 586 assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
| 587 &if_rhsisnumber, &if_rhsisnotnumber); |
| 588 |
| 589 assembler->Bind(&if_rhsisnumber); |
| 590 { |
| 591 var_fadd_lhs.Bind(assembler->SmiToFloat64(lhs)); |
| 592 var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); |
| 593 assembler->Goto(&do_fadd); |
| 594 } |
| 595 |
| 596 assembler->Bind(&if_rhsisnotnumber); |
| 597 { |
| 598 // Load the instance type of {rhs}. |
| 599 Node* rhs_instance_type = assembler->LoadMapInstanceType(rhs_map); |
| 600 |
| 601 // Check if the {rhs} is a String. |
| 602 Label if_rhsisstring(assembler, Label::kDeferred), |
| 603 if_rhsisnotstring(assembler, Label::kDeferred); |
| 604 assembler->Branch(assembler->Int32LessThan( |
| 605 rhs_instance_type, |
| 606 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), |
| 607 &if_rhsisstring, &if_rhsisnotstring); |
| 608 |
| 609 assembler->Bind(&if_rhsisstring); |
| 610 { |
| 611 // Convert {lhs}, which is a Smi, to a String and concatenate the |
| 612 // resulting string with the String {rhs}. |
| 613 Callable callable = CodeFactory::StringAdd( |
| 614 assembler->isolate(), STRING_ADD_CONVERT_LEFT, NOT_TENURED); |
| 615 assembler->TailCallStub(callable, context, lhs, rhs); |
| 616 } |
| 617 |
| 618 assembler->Bind(&if_rhsisnotstring); |
| 619 { |
| 620 // Check if {rhs} is a JSReceiver. |
| 621 Label if_rhsisreceiver(assembler, Label::kDeferred), |
| 622 if_rhsisnotreceiver(assembler, Label::kDeferred); |
| 623 assembler->Branch( |
| 624 assembler->Int32LessThanOrEqual( |
| 625 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE), |
| 626 rhs_instance_type), |
| 627 &if_rhsisreceiver, &if_rhsisnotreceiver); |
| 628 |
| 629 assembler->Bind(&if_rhsisreceiver); |
| 630 { |
| 631 // Convert {rhs} to a primitive first passing no hint. |
| 632 // TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there. |
| 633 var_rhs.Bind( |
| 634 assembler->CallRuntime(Runtime::kToPrimitive, context, rhs)); |
| 635 assembler->Goto(&loop); |
| 636 } |
| 637 |
| 638 assembler->Bind(&if_rhsisnotreceiver); |
| 639 { |
| 640 // Convert {rhs} to a Number first. |
| 641 Callable callable = |
| 642 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 643 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
| 644 assembler->Goto(&loop); |
| 645 } |
| 646 } |
| 647 } |
| 648 } |
| 649 } |
| 650 |
| 651 assembler->Bind(&if_lhsisnotsmi); |
| 652 { |
| 653 // Load the map and instance type of {lhs}. |
| 654 Node* lhs_instance_type = assembler->LoadInstanceType(lhs); |
| 655 |
| 656 // Check if {lhs} is a String. |
| 657 Label if_lhsisstring(assembler), if_lhsisnotstring(assembler); |
| 658 assembler->Branch(assembler->Int32LessThan( |
| 659 lhs_instance_type, |
| 660 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), |
| 661 &if_lhsisstring, &if_lhsisnotstring); |
| 662 |
| 663 assembler->Bind(&if_lhsisstring); |
| 664 { |
| 665 // Convert {rhs} to a String (using the sequence of ToPrimitive with |
| 666 // no hint followed by ToString) and concatenate the strings. |
| 667 Callable callable = CodeFactory::StringAdd( |
| 668 assembler->isolate(), STRING_ADD_CONVERT_RIGHT, NOT_TENURED); |
| 669 assembler->TailCallStub(callable, context, lhs, rhs); |
| 670 } |
| 671 |
| 672 assembler->Bind(&if_lhsisnotstring); |
| 673 { |
| 674 // Check if {rhs} is a Smi. |
| 675 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
| 676 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
| 677 &if_rhsisnotsmi); |
| 678 |
| 679 assembler->Bind(&if_rhsissmi); |
| 680 { |
| 681 // Check if {lhs} is a Number. |
| 682 Label if_lhsisnumber(assembler), |
| 683 if_lhsisnotnumber(assembler, Label::kDeferred); |
| 684 assembler->Branch(assembler->Word32Equal( |
| 685 lhs_instance_type, |
| 686 assembler->Int32Constant(HEAP_NUMBER_TYPE)), |
| 687 &if_lhsisnumber, &if_lhsisnotnumber); |
| 688 |
| 689 assembler->Bind(&if_lhsisnumber); |
| 690 { |
| 691 // The {lhs} is a HeapNumber, the {rhs} is a Smi, just add them. |
| 692 var_fadd_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); |
| 693 var_fadd_rhs.Bind(assembler->SmiToFloat64(rhs)); |
| 694 assembler->Goto(&do_fadd); |
| 695 } |
| 696 |
| 697 assembler->Bind(&if_lhsisnotnumber); |
| 698 { |
| 699 // The {lhs} is neither a Number nor a String, and the {rhs} is a |
| 700 // Smi. |
| 701 Label if_lhsisreceiver(assembler, Label::kDeferred), |
| 702 if_lhsisnotreceiver(assembler, Label::kDeferred); |
| 703 assembler->Branch( |
| 704 assembler->Int32LessThanOrEqual( |
| 705 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE), |
| 706 lhs_instance_type), |
| 707 &if_lhsisreceiver, &if_lhsisnotreceiver); |
| 708 |
| 709 assembler->Bind(&if_lhsisreceiver); |
| 710 { |
| 711 // Convert {lhs} to a primitive first passing no hint. |
| 712 // TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there. |
| 713 var_lhs.Bind( |
| 714 assembler->CallRuntime(Runtime::kToPrimitive, context, lhs)); |
| 715 assembler->Goto(&loop); |
| 716 } |
| 717 |
| 718 assembler->Bind(&if_lhsisnotreceiver); |
| 719 { |
| 720 // Convert {lhs} to a Number first. |
| 721 Callable callable = |
| 722 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 723 var_lhs.Bind(assembler->CallStub(callable, context, lhs)); |
| 724 assembler->Goto(&loop); |
| 725 } |
| 726 } |
| 727 } |
| 728 |
| 729 assembler->Bind(&if_rhsisnotsmi); |
| 730 { |
| 731 // Load the instance type of {rhs}. |
| 732 Node* rhs_instance_type = assembler->LoadInstanceType(rhs); |
| 733 |
| 734 // Check if {rhs} is a String. |
| 735 Label if_rhsisstring(assembler), if_rhsisnotstring(assembler); |
| 736 assembler->Branch(assembler->Int32LessThan( |
| 737 rhs_instance_type, |
| 738 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), |
| 739 &if_rhsisstring, &if_rhsisnotstring); |
| 740 |
| 741 assembler->Bind(&if_rhsisstring); |
| 742 { |
| 743 // Convert {lhs} to a String (using the sequence of ToPrimitive with |
| 744 // no hint followed by ToString) and concatenate the strings. |
| 745 Callable callable = CodeFactory::StringAdd( |
| 746 assembler->isolate(), STRING_ADD_CONVERT_LEFT, NOT_TENURED); |
| 747 assembler->TailCallStub(callable, context, lhs, rhs); |
| 748 } |
| 749 |
| 750 assembler->Bind(&if_rhsisnotstring); |
| 751 { |
| 752 // Check if {lhs} is a HeapNumber. |
| 753 Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler); |
| 754 assembler->Branch(assembler->Word32Equal( |
| 755 lhs_instance_type, |
| 756 assembler->Int32Constant(HEAP_NUMBER_TYPE)), |
| 757 &if_lhsisnumber, &if_lhsisnotnumber); |
| 758 |
| 759 assembler->Bind(&if_lhsisnumber); |
| 760 { |
| 761 // Check if {rhs} is also a HeapNumber. |
| 762 Label if_rhsisnumber(assembler), |
| 763 if_rhsisnotnumber(assembler, Label::kDeferred); |
| 764 assembler->Branch(assembler->Word32Equal( |
| 765 rhs_instance_type, |
| 766 assembler->Int32Constant(HEAP_NUMBER_TYPE)), |
| 767 &if_rhsisnumber, &if_rhsisnotnumber); |
| 768 |
| 769 assembler->Bind(&if_rhsisnumber); |
| 770 { |
| 771 // Perform a floating point addition. |
| 772 var_fadd_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); |
| 773 var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); |
| 774 assembler->Goto(&do_fadd); |
| 775 } |
| 776 |
| 777 assembler->Bind(&if_rhsisnotnumber); |
| 778 { |
| 779 // Check if {rhs} is a JSReceiver. |
| 780 Label if_rhsisreceiver(assembler, Label::kDeferred), |
| 781 if_rhsisnotreceiver(assembler, Label::kDeferred); |
| 782 assembler->Branch( |
| 783 assembler->Int32LessThanOrEqual( |
| 784 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE), |
| 785 rhs_instance_type), |
| 786 &if_rhsisreceiver, &if_rhsisnotreceiver); |
| 787 |
| 788 assembler->Bind(&if_rhsisreceiver); |
| 789 { |
| 790 // Convert {rhs} to a primitive first passing no hint. |
| 791 // TODO(bmeurer): Hook up ToPrimitiveStub here too. |
| 792 var_rhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive, |
| 793 context, rhs)); |
| 794 assembler->Goto(&loop); |
| 795 } |
| 796 |
| 797 assembler->Bind(&if_rhsisnotreceiver); |
| 798 { |
| 799 // Convert {rhs} to a Number first. |
| 800 Callable callable = |
| 801 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 802 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
| 803 assembler->Goto(&loop); |
| 804 } |
| 805 } |
| 806 } |
| 807 |
| 808 assembler->Bind(&if_lhsisnotnumber); |
| 809 { |
| 810 // Check if {lhs} is a JSReceiver. |
| 811 Label if_lhsisreceiver(assembler, Label::kDeferred), |
| 812 if_lhsisnotreceiver(assembler); |
| 813 assembler->Branch( |
| 814 assembler->Int32LessThanOrEqual( |
| 815 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE), |
| 816 lhs_instance_type), |
| 817 &if_lhsisreceiver, &if_lhsisnotreceiver); |
| 818 |
| 819 assembler->Bind(&if_lhsisreceiver); |
| 820 { |
| 821 // Convert {lhs} to a primitive first passing no hint. |
| 822 // TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there. |
| 823 var_lhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive, |
| 824 context, lhs)); |
| 825 assembler->Goto(&loop); |
| 826 } |
| 827 |
| 828 assembler->Bind(&if_lhsisnotreceiver); |
| 829 { |
| 830 // Check if {rhs} is a JSReceiver. |
| 831 Label if_rhsisreceiver(assembler, Label::kDeferred), |
| 832 if_rhsisnotreceiver(assembler, Label::kDeferred); |
| 833 assembler->Branch( |
| 834 assembler->Int32LessThanOrEqual( |
| 835 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE), |
| 836 rhs_instance_type), |
| 837 &if_rhsisreceiver, &if_rhsisnotreceiver); |
| 838 |
| 839 assembler->Bind(&if_rhsisreceiver); |
| 840 { |
| 841 // Convert {rhs} to a primitive first passing no hint. |
| 842 // TODO(bmeurer): Hook up ToPrimitiveStub here too. |
| 843 var_rhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive, |
| 844 context, rhs)); |
| 845 assembler->Goto(&loop); |
| 846 } |
| 847 |
| 848 assembler->Bind(&if_rhsisnotreceiver); |
| 849 { |
| 850 // Convert {lhs} to a Number first. |
| 851 Callable callable = |
| 852 CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 853 var_lhs.Bind(assembler->CallStub(callable, context, lhs)); |
| 854 assembler->Goto(&loop); |
| 855 } |
| 856 } |
| 857 } |
| 858 } |
| 859 } |
| 860 } |
| 861 } |
| 862 } |
| 863 |
| 864 assembler->Bind(&do_fadd); |
| 865 { |
| 866 Node* lhs_value = var_fadd_lhs.value(); |
| 867 Node* rhs_value = var_fadd_rhs.value(); |
| 868 Node* value = assembler->Float64Add(lhs_value, rhs_value); |
| 869 // TODO(bmeurer): Introduce a ChangeFloat64ToTagged. |
| 870 Node* result = assembler->Allocate(HeapNumber::kSize, |
| 871 compiler::CodeStubAssembler::kNone); |
| 872 assembler->StoreMapNoWriteBarrier(result, |
| 873 assembler->HeapNumberMapConstant()); |
| 874 assembler->StoreHeapNumberValue(result, value); |
| 875 assembler->Return(result); |
| 876 } |
| 877 } |
| 878 |
| 879 void SubtractStub::GenerateAssembly( |
| 880 compiler::CodeStubAssembler* assembler) const { |
| 881 typedef compiler::CodeStubAssembler::Label Label; |
| 882 typedef compiler::Node Node; |
| 883 typedef compiler::CodeStubAssembler::Variable Variable; |
| 884 |
| 885 Node* context = assembler->Parameter(2); |
| 886 |
| 887 // Shared entry for floating point subtraction. |
| 888 Label do_fsub(assembler); |
| 889 Variable var_fsub_lhs(assembler, MachineRepresentation::kFloat64), |
| 890 var_fsub_rhs(assembler, MachineRepresentation::kFloat64); |
| 891 |
| 892 // We might need to loop several times due to ToPrimitive and/or ToNumber |
| 893 // conversions. |
| 894 Variable var_lhs(assembler, MachineRepresentation::kTagged), |
| 895 var_rhs(assembler, MachineRepresentation::kTagged); |
| 896 Variable* loop_vars[2] = {&var_lhs, &var_rhs}; |
| 897 Label loop(assembler, 2, loop_vars); |
| 898 var_lhs.Bind(assembler->Parameter(0)); |
| 899 var_rhs.Bind(assembler->Parameter(1)); |
| 900 assembler->Goto(&loop); |
| 901 assembler->Bind(&loop); |
| 902 { |
| 903 // Load the current {lhs} and {rhs} values. |
| 904 Node* lhs = var_lhs.value(); |
| 905 Node* rhs = var_rhs.value(); |
| 906 |
| 907 // Check if the {lhs} is a Smi or a HeapObject. |
| 908 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); |
| 909 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); |
| 910 |
| 911 assembler->Bind(&if_lhsissmi); |
| 912 { |
| 913 // Check if the {rhs} is also a Smi. |
| 914 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
| 915 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
| 916 &if_rhsisnotsmi); |
| 917 |
| 918 assembler->Bind(&if_rhsissmi); |
| 919 { |
| 920 // Try a fast Smi subtraction first. |
| 921 Node* pair = assembler->SmiSubWithOverflow(lhs, rhs); |
| 922 Node* result = assembler->Projection(0, pair); |
| 923 Node* overflow = assembler->Projection(1, pair); |
| 924 |
| 925 // Check if the Smi subtraction overflowed. |
| 926 Label if_overflow(assembler), if_notoverflow(assembler); |
| 927 assembler->Branch(overflow, &if_overflow, &if_notoverflow); |
| 928 |
| 929 assembler->Bind(&if_overflow); |
| 930 { |
| 931 // The result doesn't fit into Smi range. |
| 932 var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs)); |
| 933 var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs)); |
| 934 assembler->Goto(&do_fsub); |
| 935 } |
| 936 |
| 937 assembler->Bind(&if_notoverflow); |
| 938 assembler->Return(result); |
| 939 } |
| 940 |
| 941 assembler->Bind(&if_rhsisnotsmi); |
| 942 { |
| 943 // Load the map of the {rhs}. |
| 944 Node* rhs_map = assembler->LoadMap(rhs); |
| 945 |
| 946 // Check if {rhs} is a HeapNumber. |
| 947 Label if_rhsisnumber(assembler), |
| 948 if_rhsisnotnumber(assembler, Label::kDeferred); |
| 949 Node* number_map = assembler->HeapNumberMapConstant(); |
| 950 assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
| 951 &if_rhsisnumber, &if_rhsisnotnumber); |
| 952 |
| 953 assembler->Bind(&if_rhsisnumber); |
| 954 { |
| 955 // Perform a floating point subtraction. |
| 956 var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs)); |
| 957 var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); |
| 958 assembler->Goto(&do_fsub); |
| 959 } |
| 960 |
| 961 assembler->Bind(&if_rhsisnotnumber); |
| 962 { |
| 963 // Convert the {rhs} to a Number first. |
| 964 Callable callable = CodeFactory::NonNumberToNumber(isolate()); |
| 965 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
| 966 assembler->Goto(&loop); |
| 967 } |
| 968 } |
| 969 } |
| 970 |
| 971 assembler->Bind(&if_lhsisnotsmi); |
| 972 { |
| 973 // Load the map of the {lhs}. |
| 974 Node* lhs_map = assembler->LoadMap(lhs); |
| 975 |
| 976 // Check if the {lhs} is a HeapNumber. |
| 977 Label if_lhsisnumber(assembler), |
| 978 if_lhsisnotnumber(assembler, Label::kDeferred); |
| 979 Node* number_map = assembler->HeapNumberMapConstant(); |
| 980 assembler->Branch(assembler->WordEqual(lhs_map, number_map), |
| 981 &if_lhsisnumber, &if_lhsisnotnumber); |
| 982 |
| 983 assembler->Bind(&if_lhsisnumber); |
| 984 { |
| 985 // Check if the {rhs} is a Smi. |
| 986 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
| 987 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
| 988 &if_rhsisnotsmi); |
| 989 |
| 990 assembler->Bind(&if_rhsissmi); |
| 991 { |
| 992 // Perform a floating point subtraction. |
| 993 var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); |
| 994 var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs)); |
| 995 assembler->Goto(&do_fsub); |
| 996 } |
| 997 |
| 998 assembler->Bind(&if_rhsisnotsmi); |
| 999 { |
| 1000 // Load the map of the {rhs}. |
| 1001 Node* rhs_map = assembler->LoadMap(rhs); |
| 1002 |
| 1003 // Check if the {rhs} is a HeapNumber. |
| 1004 Label if_rhsisnumber(assembler), |
| 1005 if_rhsisnotnumber(assembler, Label::kDeferred); |
| 1006 assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
| 1007 &if_rhsisnumber, &if_rhsisnotnumber); |
| 1008 |
| 1009 assembler->Bind(&if_rhsisnumber); |
| 1010 { |
| 1011 // Perform a floating point subtraction. |
| 1012 var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); |
| 1013 var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); |
| 1014 assembler->Goto(&do_fsub); |
| 1015 } |
| 1016 |
| 1017 assembler->Bind(&if_rhsisnotnumber); |
| 1018 { |
| 1019 // Convert the {rhs} to a Number first. |
| 1020 Callable callable = CodeFactory::NonNumberToNumber(isolate()); |
| 1021 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
| 1022 assembler->Goto(&loop); |
| 1023 } |
| 1024 } |
| 1025 } |
| 1026 |
| 1027 assembler->Bind(&if_lhsisnotnumber); |
| 1028 { |
| 1029 // Convert the {lhs} to a Number first. |
| 1030 Callable callable = CodeFactory::NonNumberToNumber(isolate()); |
| 1031 var_lhs.Bind(assembler->CallStub(callable, context, lhs)); |
| 1032 assembler->Goto(&loop); |
| 1033 } |
| 1034 } |
| 1035 } |
| 1036 |
| 1037 assembler->Bind(&do_fsub); |
| 1038 { |
| 1039 Node* lhs_value = var_fsub_lhs.value(); |
| 1040 Node* rhs_value = var_fsub_rhs.value(); |
| 1041 Node* value = assembler->Float64Sub(lhs_value, rhs_value); |
| 1042 // TODO(bmeurer): Introduce a ChangeFloat64ToTagged. |
| 1043 Node* result = assembler->Allocate(HeapNumber::kSize, |
| 1044 compiler::CodeStubAssembler::kNone); |
| 1045 assembler->StoreMapNoWriteBarrier(result, |
| 1046 assembler->HeapNumberMapConstant()); |
| 1047 assembler->StoreHeapNumberValue(result, value); |
| 1048 assembler->Return(result); |
| 1049 } |
| 1050 } |
| 1051 |
518 namespace { | 1052 namespace { |
519 | 1053 |
520 enum RelationalComparisonMode { | 1054 enum RelationalComparisonMode { |
521 kLessThan, | 1055 kLessThan, |
522 kLessThanOrEqual, | 1056 kLessThanOrEqual, |
523 kGreaterThan, | 1057 kGreaterThan, |
524 kGreaterThanOrEqual | 1058 kGreaterThanOrEqual |
525 }; | 1059 }; |
526 | 1060 |
527 void GenerateAbstractRelationalComparison( | 1061 void GenerateAbstractRelationalComparison( |
(...skipping 2289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2817 if (type->Is(Type::UntaggedPointer())) { | 3351 if (type->Is(Type::UntaggedPointer())) { |
2818 return Representation::External(); | 3352 return Representation::External(); |
2819 } | 3353 } |
2820 | 3354 |
2821 DCHECK(!type->Is(Type::Untagged())); | 3355 DCHECK(!type->Is(Type::Untagged())); |
2822 return Representation::Tagged(); | 3356 return Representation::Tagged(); |
2823 } | 3357 } |
2824 | 3358 |
2825 } // namespace internal | 3359 } // namespace internal |
2826 } // namespace v8 | 3360 } // namespace v8 |
OLD | NEW |