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 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
568 case kGreaterThanOrEqual: | 568 case kGreaterThanOrEqual: |
569 assembler->BranchIfSmiLessThanOrEqual(rhs, lhs, &return_true, | 569 assembler->BranchIfSmiLessThanOrEqual(rhs, lhs, &return_true, |
570 &return_false); | 570 &return_false); |
571 break; | 571 break; |
572 } | 572 } |
573 } | 573 } |
574 | 574 |
575 assembler->Bind(&if_rhsisnotsmi); | 575 assembler->Bind(&if_rhsisnotsmi); |
576 { | 576 { |
577 // Load the map of {rhs}. | 577 // Load the map of {rhs}. |
578 Node* rhs_map = assembler->LoadObjectField(rhs, HeapObject::kMapOffset); | 578 Node* rhs_map = assembler->LoadMap(rhs); |
579 | 579 |
580 // Check if the {rhs} is a HeapNumber. | 580 // Check if the {rhs} is a HeapNumber. |
581 Node* number_map = assembler->HeapNumberMapConstant(); | 581 Node* number_map = assembler->HeapNumberMapConstant(); |
582 Label if_rhsisnumber(assembler), | 582 Label if_rhsisnumber(assembler), |
583 if_rhsisnotnumber(assembler, Label::kDeferred); | 583 if_rhsisnotnumber(assembler, Label::kDeferred); |
584 assembler->Branch(assembler->WordEqual(rhs_map, number_map), | 584 assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
585 &if_rhsisnumber, &if_rhsisnotnumber); | 585 &if_rhsisnumber, &if_rhsisnotnumber); |
586 | 586 |
587 assembler->Bind(&if_rhsisnumber); | 587 assembler->Bind(&if_rhsisnumber); |
588 { | 588 { |
(...skipping 16 matching lines...) Expand all Loading... | |
605 } | 605 } |
606 } | 606 } |
607 } | 607 } |
608 | 608 |
609 assembler->Bind(&if_lhsisnotsmi); | 609 assembler->Bind(&if_lhsisnotsmi); |
610 { | 610 { |
611 // Load the HeapNumber map for later comparisons. | 611 // Load the HeapNumber map for later comparisons. |
612 Node* number_map = assembler->HeapNumberMapConstant(); | 612 Node* number_map = assembler->HeapNumberMapConstant(); |
613 | 613 |
614 // Load the map of {lhs}. | 614 // Load the map of {lhs}. |
615 Node* lhs_map = assembler->LoadObjectField(lhs, HeapObject::kMapOffset); | 615 Node* lhs_map = assembler->LoadMap(lhs); |
616 | 616 |
617 // Check if {rhs} is a Smi or a HeapObject. | 617 // Check if {rhs} is a Smi or a HeapObject. |
618 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); | 618 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
619 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, | 619 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
620 &if_rhsisnotsmi); | 620 &if_rhsisnotsmi); |
621 | 621 |
622 assembler->Bind(&if_rhsissmi); | 622 assembler->Bind(&if_rhsissmi); |
623 { | 623 { |
624 // Check if the {lhs} is a HeapNumber. | 624 // Check if the {lhs} is a HeapNumber. |
625 Label if_lhsisnumber(assembler), | 625 Label if_lhsisnumber(assembler), |
(...skipping 18 matching lines...) Expand all Loading... | |
644 // a Number hint. | 644 // a Number hint. |
645 Callable callable = CodeFactory::ToNumber(assembler->isolate()); | 645 Callable callable = CodeFactory::ToNumber(assembler->isolate()); |
646 var_lhs.Bind(assembler->CallStub(callable, context, lhs)); | 646 var_lhs.Bind(assembler->CallStub(callable, context, lhs)); |
647 assembler->Goto(&loop); | 647 assembler->Goto(&loop); |
648 } | 648 } |
649 } | 649 } |
650 | 650 |
651 assembler->Bind(&if_rhsisnotsmi); | 651 assembler->Bind(&if_rhsisnotsmi); |
652 { | 652 { |
653 // Load the map of {rhs}. | 653 // Load the map of {rhs}. |
654 Node* rhs_map = assembler->LoadObjectField(rhs, HeapObject::kMapOffset); | 654 Node* rhs_map = assembler->LoadMap(rhs); |
655 | 655 |
656 // Check if {lhs} is a HeapNumber. | 656 // Check if {lhs} is a HeapNumber. |
657 Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler); | 657 Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler); |
658 assembler->Branch(assembler->WordEqual(lhs_map, number_map), | 658 assembler->Branch(assembler->WordEqual(lhs_map, number_map), |
659 &if_lhsisnumber, &if_lhsisnotnumber); | 659 &if_lhsisnumber, &if_lhsisnotnumber); |
660 | 660 |
661 assembler->Bind(&if_lhsisnumber); | 661 assembler->Bind(&if_lhsisnumber); |
662 { | 662 { |
663 // Check if {rhs} is also a HeapNumber. | 663 // Check if {rhs} is also a HeapNumber. |
664 Label if_rhsisnumber(assembler), | 664 Label if_rhsisnumber(assembler), |
(...skipping 18 matching lines...) Expand all Loading... | |
683 // a Number hint. | 683 // a Number hint. |
684 Callable callable = CodeFactory::ToNumber(assembler->isolate()); | 684 Callable callable = CodeFactory::ToNumber(assembler->isolate()); |
685 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); | 685 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
686 assembler->Goto(&loop); | 686 assembler->Goto(&loop); |
687 } | 687 } |
688 } | 688 } |
689 | 689 |
690 assembler->Bind(&if_lhsisnotnumber); | 690 assembler->Bind(&if_lhsisnotnumber); |
691 { | 691 { |
692 // Load the instance type of {lhs}. | 692 // Load the instance type of {lhs}. |
693 Node* lhs_instance_type = assembler->LoadMapInstanceType(lhs_map); | 693 Node* lhs_instancetype = assembler->LoadMapInstanceType(lhs_map); |
694 | 694 |
695 // Check if {lhs} is a String. | 695 // Check if {lhs} is a String. |
696 Label if_lhsisstring(assembler), | 696 Label if_lhsisstring(assembler), |
697 if_lhsisnotstring(assembler, Label::kDeferred); | 697 if_lhsisnotstring(assembler, Label::kDeferred); |
698 assembler->Branch(assembler->Int32LessThan( | 698 assembler->Branch(assembler->Int32LessThan( |
699 lhs_instance_type, | 699 lhs_instancetype, |
700 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), | 700 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), |
701 &if_lhsisstring, &if_lhsisnotstring); | 701 &if_lhsisstring, &if_lhsisnotstring); |
702 | 702 |
703 assembler->Bind(&if_lhsisstring); | 703 assembler->Bind(&if_lhsisstring); |
704 { | 704 { |
705 // Load the instance type of {rhs}. | 705 // Load the instance type of {rhs}. |
706 Node* rhs_instance_type = assembler->LoadMapInstanceType(rhs_map); | 706 Node* rhs_instancetype = assembler->LoadMapInstanceType(rhs_map); |
707 | 707 |
708 // Check if {rhs} is also a String. | 708 // Check if {rhs} is also a String. |
709 Label if_rhsisstring(assembler), | 709 Label if_rhsisstring(assembler), |
710 if_rhsisnotstring(assembler, Label::kDeferred); | 710 if_rhsisnotstring(assembler, Label::kDeferred); |
711 assembler->Branch(assembler->Int32LessThan( | 711 assembler->Branch(assembler->Int32LessThan( |
712 rhs_instance_type, assembler->Int32Constant( | 712 rhs_instancetype, assembler->Int32Constant( |
713 FIRST_NONSTRING_TYPE)), | 713 FIRST_NONSTRING_TYPE)), |
714 &if_rhsisstring, &if_rhsisnotstring); | 714 &if_rhsisstring, &if_rhsisnotstring); |
715 | 715 |
716 assembler->Bind(&if_rhsisstring); | 716 assembler->Bind(&if_rhsisstring); |
717 { | 717 { |
718 // Both {lhs} and {rhs} are strings. | 718 // Both {lhs} and {rhs} are strings. |
719 switch (mode) { | 719 switch (mode) { |
720 case kLessThan: | 720 case kLessThan: |
721 assembler->TailCallStub( | 721 assembler->TailCallStub( |
722 CodeFactory::StringLessThan(assembler->isolate()), | 722 CodeFactory::StringLessThan(assembler->isolate()), |
723 context, lhs, rhs); | 723 context, lhs, rhs); |
(...skipping 21 matching lines...) Expand all Loading... | |
745 // The {lhs} is a String, while {rhs} is neither a Number nor a | 745 // The {lhs} is a String, while {rhs} is neither a Number nor a |
746 // String, so we need to call ToPrimitive(rhs, hint Number) if | 746 // String, so we need to call ToPrimitive(rhs, hint Number) if |
747 // {rhs} is a receiver or ToNumber(lhs) and ToNumber(rhs) in the | 747 // {rhs} is a receiver or ToNumber(lhs) and ToNumber(rhs) in the |
748 // other cases. | 748 // other cases. |
749 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | 749 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
750 Label if_rhsisreceiver(assembler, Label::kDeferred), | 750 Label if_rhsisreceiver(assembler, Label::kDeferred), |
751 if_rhsisnotreceiver(assembler, Label::kDeferred); | 751 if_rhsisnotreceiver(assembler, Label::kDeferred); |
752 assembler->Branch( | 752 assembler->Branch( |
753 assembler->Int32LessThanOrEqual( | 753 assembler->Int32LessThanOrEqual( |
754 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE), | 754 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE), |
755 rhs_instance_type), | 755 rhs_instancetype), |
756 &if_rhsisreceiver, &if_rhsisnotreceiver); | 756 &if_rhsisreceiver, &if_rhsisnotreceiver); |
757 | 757 |
758 assembler->Bind(&if_rhsisreceiver); | 758 assembler->Bind(&if_rhsisreceiver); |
759 { | 759 { |
760 // Convert {rhs} to a primitive first passing Number hint. | 760 // Convert {rhs} to a primitive first passing Number hint. |
761 // TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there. | 761 // TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there. |
762 var_rhs.Bind(assembler->CallRuntime( | 762 var_rhs.Bind(assembler->CallRuntime( |
763 Runtime::kToPrimitive_Number, context, rhs)); | 763 Runtime::kToPrimitive_Number, context, rhs)); |
764 assembler->Goto(&loop); | 764 assembler->Goto(&loop); |
765 } | 765 } |
(...skipping 13 matching lines...) Expand all Loading... | |
779 { | 779 { |
780 // The {lhs} is neither a Number nor a String, so we need to call | 780 // The {lhs} is neither a Number nor a String, so we need to call |
781 // ToPrimitive(lhs, hint Number) if {lhs} is a receiver or | 781 // ToPrimitive(lhs, hint Number) if {lhs} is a receiver or |
782 // ToNumber(lhs) and ToNumber(rhs) in the other cases. | 782 // ToNumber(lhs) and ToNumber(rhs) in the other cases. |
783 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | 783 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
784 Label if_lhsisreceiver(assembler, Label::kDeferred), | 784 Label if_lhsisreceiver(assembler, Label::kDeferred), |
785 if_lhsisnotreceiver(assembler, Label::kDeferred); | 785 if_lhsisnotreceiver(assembler, Label::kDeferred); |
786 assembler->Branch( | 786 assembler->Branch( |
787 assembler->Int32LessThanOrEqual( | 787 assembler->Int32LessThanOrEqual( |
788 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE), | 788 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE), |
789 lhs_instance_type), | 789 lhs_instancetype), |
790 &if_lhsisreceiver, &if_lhsisnotreceiver); | 790 &if_lhsisreceiver, &if_lhsisnotreceiver); |
791 | 791 |
792 assembler->Bind(&if_lhsisreceiver); | 792 assembler->Bind(&if_lhsisreceiver); |
793 { | 793 { |
794 // Convert {lhs} to a primitive first passing Number hint. | 794 // Convert {lhs} to a primitive first passing Number hint. |
795 // TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there. | 795 // TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there. |
796 var_lhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive_Number, | 796 var_lhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive_Number, |
797 context, lhs)); | 797 context, lhs)); |
798 assembler->Goto(&loop); | 798 assembler->Goto(&loop); |
799 } | 799 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
841 | 841 |
842 assembler->Bind(&return_true); | 842 assembler->Bind(&return_true); |
843 assembler->Return(assembler->BooleanConstant(true)); | 843 assembler->Return(assembler->BooleanConstant(true)); |
844 | 844 |
845 assembler->Bind(&return_false); | 845 assembler->Bind(&return_false); |
846 assembler->Return(assembler->BooleanConstant(false)); | 846 assembler->Return(assembler->BooleanConstant(false)); |
847 } | 847 } |
848 | 848 |
849 enum ResultMode { kDontNegateResult, kNegateResult }; | 849 enum ResultMode { kDontNegateResult, kNegateResult }; |
850 | 850 |
851 void GenerateEqual_Same(compiler::CodeStubAssembler* assembler, | |
852 compiler::Node* value, | |
853 compiler::CodeStubAssembler::Label* if_equal, | |
854 compiler::CodeStubAssembler::Label* if_notequal) { | |
855 // In case of abstract or strict equality checks, we need additional checks | |
856 // for NaN values because they are not considered equal, even if both the | |
857 // left and the right hand side reference exactly the same value. | |
858 // TODO(bmeurer): This seems to violate the SIMD.js specification, but it | |
859 // seems to be what is tested in the current SIMD.js testsuite. | |
860 | |
861 typedef compiler::CodeStubAssembler::Label Label; | |
862 typedef compiler::Node Node; | |
863 | |
864 // Check if {value} is a Smi or a HeapObject. | |
865 Label if_valueissmi(assembler), if_valueisnotsmi(assembler); | |
866 assembler->Branch(assembler->WordIsSmi(value), &if_valueissmi, | |
867 &if_valueisnotsmi); | |
868 | |
869 assembler->Bind(&if_valueisnotsmi); | |
870 { | |
871 // Load the map of {value}. | |
872 Node* value_map = assembler->LoadMap(value); | |
873 | |
874 // Check if {value} (and therefore {rhs}) is a HeapNumber. | |
875 Node* number_map = assembler->HeapNumberMapConstant(); | |
876 Label if_valueisnumber(assembler), if_valueisnotnumber(assembler); | |
877 assembler->Branch(assembler->WordEqual(value_map, number_map), | |
878 &if_valueisnumber, &if_valueisnotnumber); | |
879 | |
880 assembler->Bind(&if_valueisnumber); | |
881 { | |
882 // Convert {value} (and therefore {rhs}) to floating point value. | |
883 Node* value_value = assembler->LoadHeapNumberValue(value); | |
884 | |
885 // Check if the HeapNumber value is a NaN. | |
886 assembler->BranchIfFloat64IsNaN(value_value, if_notequal, if_equal); | |
887 } | |
888 | |
889 assembler->Bind(&if_valueisnotnumber); | |
890 assembler->Goto(if_equal); | |
891 } | |
892 | |
893 assembler->Bind(&if_valueissmi); | |
894 assembler->Goto(if_equal); | |
895 } | |
896 | |
897 void GenerateEqual_Simd128Value_HeapObject( | |
898 compiler::CodeStubAssembler* assembler, compiler::Node* lhs, | |
899 compiler::Node* lhs_map, compiler::Node* rhs, compiler::Node* rhs_map, | |
900 compiler::CodeStubAssembler::Label* if_equal, | |
901 compiler::CodeStubAssembler::Label* if_notequal) { | |
902 typedef compiler::CodeStubAssembler::Label Label; | |
903 typedef compiler::Node Node; | |
904 | |
905 // Check if {lhs} and {rhs} have the same map. | |
906 Label if_mapsame(assembler), if_mapnotsame(assembler); | |
907 assembler->Branch(assembler->WordEqual(lhs_map, rhs_map), &if_mapsame, | |
908 &if_mapnotsame); | |
909 | |
910 assembler->Bind(&if_mapsame); | |
911 { | |
912 // Both {lhs} and {rhs} are Simd128Values with the same map, need special | |
913 // handling for Float32x4 because of NaN comparisons. | |
914 Label if_float32x4(assembler), if_notfloat32x4(assembler); | |
915 Node* float32x4_map = | |
916 assembler->HeapConstant(assembler->factory()->float32x4_map()); | |
917 assembler->Branch(assembler->WordEqual(lhs_map, float32x4_map), | |
918 &if_float32x4, &if_notfloat32x4); | |
919 | |
920 assembler->Bind(&if_float32x4); | |
921 { | |
922 // Both {lhs} and {rhs} are Float32x4, compare the lanes individually | |
923 // using a floating point comparison. | |
924 for (int offset = Float32x4::kValueOffset - kHeapObjectTag; | |
925 offset < Float32x4::kSize - kHeapObjectTag; | |
926 offset += sizeof(float)) { | |
927 // Load the floating point values for {lhs} and {rhs}. | |
928 Node* lhs_value = assembler->Load(MachineType::Float32(), lhs, | |
929 assembler->IntPtrConstant(offset)); | |
930 Node* rhs_value = assembler->Load(MachineType::Float32(), rhs, | |
931 assembler->IntPtrConstant(offset)); | |
932 | |
933 // Perform a floating point comparison. | |
934 Label if_valueequal(assembler), if_valuenotequal(assembler); | |
935 assembler->Branch(assembler->Float32Equal(lhs_value, rhs_value), | |
936 &if_valueequal, &if_valuenotequal); | |
937 assembler->Bind(&if_valuenotequal); | |
938 assembler->Goto(if_notequal); | |
939 assembler->Bind(&if_valueequal); | |
940 } | |
941 | |
942 // All 4 lanes match, {lhs} and {rhs} considered equal. | |
943 assembler->Goto(if_equal); | |
944 } | |
945 | |
946 assembler->Bind(&if_notfloat32x4); | |
947 { | |
948 // For other Simd128Values we just perform a bitwise comparison. | |
949 for (int offset = Simd128Value::kValueOffset - kHeapObjectTag; | |
950 offset < Simd128Value::kSize - kHeapObjectTag; | |
951 offset += kPointerSize) { | |
952 // Load the word values for {lhs} and {rhs}. | |
953 Node* lhs_value = assembler->Load(MachineType::Pointer(), lhs, | |
954 assembler->IntPtrConstant(offset)); | |
955 Node* rhs_value = assembler->Load(MachineType::Pointer(), rhs, | |
956 assembler->IntPtrConstant(offset)); | |
957 | |
958 // Perform a bitwise word-comparison. | |
959 Label if_valueequal(assembler), if_valuenotequal(assembler); | |
960 assembler->Branch(assembler->WordEqual(lhs_value, rhs_value), | |
961 &if_valueequal, &if_valuenotequal); | |
962 assembler->Bind(&if_valuenotequal); | |
963 assembler->Goto(if_notequal); | |
964 assembler->Bind(&if_valueequal); | |
965 } | |
966 | |
967 // Bitwise comparison succeeded, {lhs} and {rhs} considered equal. | |
968 assembler->Goto(if_equal); | |
969 } | |
970 } | |
971 | |
972 assembler->Bind(&if_mapnotsame); | |
973 assembler->Goto(if_notequal); | |
974 } | |
975 | |
976 // ES6 section 7.2.12 Abstract Equality Comparison | |
977 void GenerateEqual(compiler::CodeStubAssembler* assembler, ResultMode mode) { | |
978 // This is a slightly optimized version of Object::Equals represented as | |
979 // scheduled TurboFan graph utilizing the CodeStubAssembler. Whenever you | |
980 // change something functionality wise in here, remember to update the | |
981 // Object::Equals method as well. | |
982 typedef compiler::CodeStubAssembler::Label Label; | |
983 typedef compiler::Node Node; | |
984 typedef compiler::CodeStubAssembler::Variable Variable; | |
985 | |
986 Node* context = assembler->Parameter(2); | |
987 | |
988 Label if_equal(assembler), if_notequal(assembler); | |
989 | |
990 // Shared entry for floating point comparison. | |
991 Label do_fcmp(assembler); | |
992 Variable var_fcmp_lhs(assembler, MachineRepresentation::kFloat64), | |
993 var_fcmp_rhs(assembler, MachineRepresentation::kFloat64); | |
994 | |
995 // We might need to loop several times due to ToPrimitive and/or ToNumber | |
996 // conversions. | |
997 Variable var_lhs(assembler, MachineRepresentation::kTagged), | |
998 var_rhs(assembler, MachineRepresentation::kTagged); | |
999 Variable* loop_vars[2] = {&var_lhs, &var_rhs}; | |
1000 Label loop(assembler, 2, loop_vars); | |
1001 var_lhs.Bind(assembler->Parameter(0)); | |
1002 var_rhs.Bind(assembler->Parameter(1)); | |
1003 assembler->Goto(&loop); | |
1004 assembler->Bind(&loop); | |
1005 { | |
1006 // Load the current {lhs} and {rhs} values. | |
1007 Node* lhs = var_lhs.value(); | |
1008 Node* rhs = var_rhs.value(); | |
1009 | |
1010 // Check if {lhs} and {rhs} refer to the same object. | |
1011 Label if_same(assembler), if_notsame(assembler); | |
1012 assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame); | |
1013 | |
1014 assembler->Bind(&if_same); | |
1015 { | |
1016 // The {lhs} and {rhs} reference the exact same value, yet we need special | |
1017 // treatment for HeapNumber, as NaN is not equal to NaN. | |
1018 GenerateEqual_Same(assembler, lhs, &if_equal, &if_notequal); | |
1019 } | |
1020 | |
1021 assembler->Bind(&if_notsame); | |
1022 { | |
1023 // Check if {lhs} is a Smi or a HeapObject. | |
1024 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); | |
1025 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, | |
1026 &if_lhsisnotsmi); | |
1027 | |
1028 assembler->Bind(&if_lhsissmi); | |
1029 { | |
1030 // Check if {rhs} is a Smi or a HeapObject. | |
1031 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); | |
1032 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, | |
1033 &if_rhsisnotsmi); | |
1034 | |
1035 assembler->Bind(&if_rhsissmi); | |
1036 assembler->Goto(&if_notequal); | |
1037 | |
1038 assembler->Bind(&if_rhsisnotsmi); | |
1039 { | |
1040 // Load the map of {rhs}. | |
1041 Node* rhs_map = assembler->LoadMap(rhs); | |
1042 | |
1043 // Check if {rhs} is a HeapNumber. | |
1044 Node* number_map = assembler->HeapNumberMapConstant(); | |
1045 Label if_rhsisnumber(assembler), | |
1046 if_rhsisnotnumber(assembler, Label::kDeferred); | |
1047 assembler->Branch(assembler->WordEqual(rhs_map, number_map), | |
1048 &if_rhsisnumber, &if_rhsisnotnumber); | |
1049 | |
1050 assembler->Bind(&if_rhsisnumber); | |
1051 { | |
1052 // Convert {lhs} and {rhs} to floating point values, and | |
1053 // perform a floating point comparison. | |
1054 var_fcmp_lhs.Bind(assembler->SmiToFloat64(lhs)); | |
1055 var_fcmp_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); | |
1056 assembler->Goto(&do_fcmp); | |
1057 } | |
1058 | |
1059 assembler->Bind(&if_rhsisnotnumber); | |
1060 { | |
1061 // Load the instance type of the {rhs}. | |
1062 Node* rhs_instancetype = assembler->LoadMapInstanceType(rhs_map); | |
1063 | |
1064 // Check if the {rhs} is a String. | |
1065 Label if_rhsisstring(assembler, Label::kDeferred), | |
1066 if_rhsisnotstring(assembler, Label::kDeferred); | |
1067 assembler->Branch(assembler->Int32LessThan( | |
1068 rhs_instancetype, assembler->Int32Constant( | |
1069 FIRST_NONSTRING_TYPE)), | |
1070 &if_rhsisstring, &if_rhsisnotstring); | |
1071 | |
1072 assembler->Bind(&if_rhsisstring); | |
1073 { | |
1074 // Convert the {rhs} to a Number. | |
1075 Callable callable = CodeFactory::ToNumber(assembler->isolate()); | |
1076 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); | |
1077 assembler->Goto(&loop); | |
1078 } | |
1079 | |
1080 assembler->Bind(&if_rhsisnotstring); | |
1081 { | |
1082 // Check if the {rhs} is a Boolean. | |
1083 Node* boolean_map = assembler->BooleanMapConstant(); | |
1084 Label if_rhsisboolean(assembler, Label::kDeferred), | |
1085 if_rhsisnotboolean(assembler, Label::kDeferred); | |
1086 assembler->Branch(assembler->WordEqual(rhs_map, boolean_map), | |
1087 &if_rhsisboolean, &if_rhsisnotboolean); | |
1088 | |
1089 assembler->Bind(&if_rhsisboolean); | |
1090 { | |
1091 // The {rhs} is a Boolean, load its number value. | |
1092 var_rhs.Bind( | |
1093 assembler->LoadObjectField(rhs, Oddball::kToNumberOffset)); | |
1094 assembler->Goto(&loop); | |
1095 } | |
1096 | |
1097 assembler->Bind(&if_rhsisnotboolean); | |
1098 { | |
1099 // Check if the {rhs} is a Receiver. | |
1100 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | |
1101 Label if_rhsisreceiver(assembler, Label::kDeferred), | |
1102 if_rhsisnotreceiver(assembler, Label::kDeferred); | |
1103 assembler->Branch( | |
1104 assembler->Int32LessThanOrEqual( | |
1105 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE), | |
1106 rhs_instancetype), | |
1107 &if_rhsisreceiver, &if_rhsisnotreceiver); | |
1108 | |
1109 assembler->Bind(&if_rhsisreceiver); | |
1110 { | |
1111 // Convert {rhs} to a primitive first (passing no hint). | |
1112 // TODO(bmeurer): Hook up ToPrimitiveStub here once it exists. | |
1113 var_rhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive, | |
1114 context, rhs)); | |
1115 assembler->Goto(&loop); | |
1116 } | |
1117 | |
1118 assembler->Bind(&if_rhsisnotreceiver); | |
1119 assembler->Goto(&if_notequal); | |
1120 } | |
1121 } | |
1122 } | |
1123 } | |
1124 } | |
1125 | |
1126 assembler->Bind(&if_lhsisnotsmi); | |
1127 { | |
1128 // Check if {rhs} is a Smi or a HeapObject. | |
1129 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); | |
1130 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, | |
1131 &if_rhsisnotsmi); | |
1132 | |
1133 assembler->Bind(&if_rhsissmi); | |
1134 { | |
1135 // The {lhs} is a HeapObject and the {rhs} is a Smi; swapping {lhs} | |
1136 // and {rhs} is not observable and doesn't matter for the result, so | |
1137 // we can just swap them and use the Smi handling above (for {lhs} | |
1138 // being a Smi). | |
1139 var_lhs.Bind(rhs); | |
1140 var_rhs.Bind(lhs); | |
1141 assembler->Goto(&loop); | |
1142 } | |
1143 | |
1144 assembler->Bind(&if_rhsisnotsmi); | |
1145 { | |
1146 Label if_lhsisstring(assembler), if_lhsisnumber(assembler), | |
1147 if_lhsissymbol(assembler), if_lhsissimd128value(assembler), | |
1148 if_lhsisoddball(assembler), if_lhsisreceiver(assembler); | |
1149 | |
1150 // Both {lhs} and {rhs} are HeapObjects, load their maps | |
1151 // and their instance types. | |
1152 Node* lhs_map = assembler->LoadMap(lhs); | |
1153 Node* rhs_map = assembler->LoadMap(rhs); | |
1154 | |
1155 // Load the instance types of {lhs} and {rhs}. | |
1156 Node* lhs_instancetype = assembler->LoadMapInstanceType(lhs_map); | |
1157 Node* rhs_instancetype = assembler->LoadMapInstanceType(rhs_map); | |
1158 | |
1159 // Dispatch based on the instance type of {lhs}. | |
1160 size_t const kNumCases = FIRST_NONSTRING_TYPE + 4; | |
1161 Label* case_labels[kNumCases]; | |
1162 int32_t case_values[kNumCases]; | |
1163 for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) { | |
epertoso
2016/03/14 15:41:38
Can you just compare and branch to if_lhsisstring
Benedikt Meurer
2016/03/14 18:21:08
That way you'd need more conditional branches. Thi
| |
1164 case_labels[i] = new Label(assembler); | |
1165 case_values[i] = i; | |
1166 } | |
1167 case_labels[FIRST_NONSTRING_TYPE + 0] = &if_lhsisnumber; | |
1168 case_values[FIRST_NONSTRING_TYPE + 0] = HEAP_NUMBER_TYPE; | |
1169 case_labels[FIRST_NONSTRING_TYPE + 1] = &if_lhsissymbol; | |
1170 case_values[FIRST_NONSTRING_TYPE + 1] = SYMBOL_TYPE; | |
1171 case_labels[FIRST_NONSTRING_TYPE + 2] = &if_lhsissimd128value; | |
1172 case_values[FIRST_NONSTRING_TYPE + 2] = SIMD128_VALUE_TYPE; | |
1173 case_labels[FIRST_NONSTRING_TYPE + 3] = &if_lhsisoddball; | |
1174 case_values[FIRST_NONSTRING_TYPE + 3] = ODDBALL_TYPE; | |
1175 assembler->Switch(lhs_instancetype, &if_lhsisreceiver, case_values, | |
1176 case_labels, arraysize(case_values)); | |
1177 for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) { | |
1178 assembler->Bind(case_labels[i]); | |
1179 assembler->Goto(&if_lhsisstring); | |
1180 delete case_labels[i]; | |
1181 } | |
1182 | |
1183 assembler->Bind(&if_lhsisstring); | |
1184 { | |
1185 // Check if {rhs} is also a String. | |
1186 Label if_rhsisstring(assembler), | |
1187 if_rhsisnotstring(assembler, Label::kDeferred); | |
1188 assembler->Branch(assembler->Int32LessThan( | |
1189 rhs_instancetype, assembler->Int32Constant( | |
1190 FIRST_NONSTRING_TYPE)), | |
1191 &if_rhsisstring, &if_rhsisnotstring); | |
1192 | |
1193 assembler->Bind(&if_rhsisstring); | |
1194 { | |
1195 // Both {lhs} and {rhs} are of type String, just do the | |
1196 // string comparison then. | |
1197 Callable callable = | |
1198 (mode == kDontNegateResult) | |
1199 ? CodeFactory::StringEqual(assembler->isolate()) | |
1200 : CodeFactory::StringNotEqual(assembler->isolate()); | |
1201 assembler->TailCallStub(callable, context, lhs, rhs); | |
1202 } | |
1203 | |
1204 assembler->Bind(&if_rhsisnotstring); | |
1205 { | |
1206 // The {lhs} is a String and the {rhs} is some other HeapObject. | |
1207 // Swapping {lhs} and {rhs} is not observable and doesn't matter | |
1208 // for the result, so we can just swap them and use the String | |
1209 // handling below (for {rhs} being a String). | |
1210 var_lhs.Bind(rhs); | |
1211 var_rhs.Bind(lhs); | |
1212 assembler->Goto(&loop); | |
1213 } | |
1214 } | |
1215 | |
1216 assembler->Bind(&if_lhsisnumber); | |
1217 { | |
1218 // Check if {rhs} is also a HeapNumber. | |
1219 Label if_rhsisnumber(assembler), | |
1220 if_rhsisnotnumber(assembler, Label::kDeferred); | |
1221 assembler->Branch( | |
1222 assembler->Word32Equal(lhs_instancetype, rhs_instancetype), | |
1223 &if_rhsisnumber, &if_rhsisnotnumber); | |
1224 | |
1225 assembler->Bind(&if_rhsisnumber); | |
1226 { | |
1227 // Convert {lhs} and {rhs} to floating point values, and | |
1228 // perform a floating point comparison. | |
1229 var_fcmp_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); | |
1230 var_fcmp_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); | |
1231 assembler->Goto(&do_fcmp); | |
1232 } | |
1233 | |
1234 assembler->Bind(&if_rhsisnotnumber); | |
1235 { | |
1236 // The {lhs} is a Number, the {rhs} is some other HeapObject. | |
1237 Label if_rhsisstring(assembler, Label::kDeferred), | |
1238 if_rhsisnotstring(assembler); | |
1239 assembler->Branch( | |
1240 assembler->Int32LessThan( | |
1241 rhs_instancetype, | |
1242 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), | |
1243 &if_rhsisstring, &if_rhsisnotstring); | |
1244 | |
1245 assembler->Bind(&if_rhsisstring); | |
1246 { | |
1247 // The {rhs} is a String and the {lhs} is a HeapNumber; we need | |
1248 // to convert the {rhs} to a Number and compare the output to | |
1249 // the Number on the {lhs}. | |
1250 Callable callable = CodeFactory::ToNumber(assembler->isolate()); | |
1251 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); | |
1252 assembler->Goto(&loop); | |
1253 } | |
1254 | |
1255 assembler->Bind(&if_rhsisnotstring); | |
1256 { | |
1257 // Check if the {rhs} is a JSReceiver. | |
1258 Label if_rhsisreceiver(assembler, Label::kDeferred), | |
1259 if_rhsisnotreceiver(assembler); | |
1260 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); | |
1261 assembler->Branch( | |
1262 assembler->Int32LessThanOrEqual( | |
1263 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE), | |
1264 rhs_instancetype), | |
1265 &if_rhsisreceiver, &if_rhsisnotreceiver); | |
1266 | |
1267 assembler->Bind(&if_rhsisreceiver); | |
1268 { | |
1269 // The {lhs} is a Primitive and the {rhs} is a JSReceiver. | |
1270 // Swapping {lhs} and {rhs} is not observable and doesn't | |
1271 // matter for the result, so we can just swap them and use | |
1272 // the JSReceiver handling below (for {lhs} being a | |
1273 // JSReceiver). | |
1274 var_lhs.Bind(rhs); | |
1275 var_rhs.Bind(lhs); | |
1276 assembler->Goto(&loop); | |
1277 } | |
1278 | |
1279 assembler->Bind(&if_rhsisnotreceiver); | |
1280 { | |
1281 // Check if {rhs} is a Boolean. | |
1282 Label if_rhsisboolean(assembler), | |
1283 if_rhsisnotboolean(assembler); | |
1284 Node* boolean_map = assembler->BooleanMapConstant(); | |
1285 assembler->Branch(assembler->WordEqual(rhs_map, boolean_map), | |
1286 &if_rhsisboolean, &if_rhsisnotboolean); | |
1287 | |
1288 assembler->Bind(&if_rhsisboolean); | |
1289 { | |
1290 // The {rhs} is a Boolean, convert it to a Smi first. | |
1291 var_rhs.Bind(assembler->LoadObjectField( | |
1292 rhs, Oddball::kToNumberOffset)); | |
1293 assembler->Goto(&loop); | |
1294 } | |
1295 | |
1296 assembler->Bind(&if_rhsisnotboolean); | |
1297 assembler->Goto(&if_notequal); | |
1298 } | |
1299 } | |
1300 } | |
1301 } | |
1302 | |
1303 assembler->Bind(&if_lhsisoddball); | |
1304 { | |
1305 // The {lhs} is an Oddball and {rhs} is some other HeapObject. | |
1306 Label if_lhsisboolean(assembler), if_lhsisnotboolean(assembler); | |
1307 Node* boolean_map = assembler->BooleanMapConstant(); | |
1308 assembler->Branch(assembler->WordEqual(lhs_map, boolean_map), | |
1309 &if_lhsisboolean, &if_lhsisnotboolean); | |
1310 | |
1311 assembler->Bind(&if_lhsisboolean); | |
1312 { | |
1313 // The {lhs} is a Boolean, check if {rhs} is also a Boolean. | |
1314 Label if_rhsisboolean(assembler), if_rhsisnotboolean(assembler); | |
1315 assembler->Branch(assembler->WordEqual(rhs_map, boolean_map), | |
1316 &if_rhsisboolean, &if_rhsisnotboolean); | |
1317 | |
1318 assembler->Bind(&if_rhsisboolean); | |
1319 { | |
1320 // Both {lhs} and {rhs} are distinct Boolean values. | |
1321 assembler->Goto(&if_notequal); | |
1322 } | |
1323 | |
1324 assembler->Bind(&if_rhsisnotboolean); | |
1325 { | |
1326 // Convert the {lhs} to a Number first. | |
1327 var_lhs.Bind( | |
1328 assembler->LoadObjectField(lhs, Oddball::kToNumberOffset)); | |
1329 assembler->Goto(&loop); | |
1330 } | |
1331 } | |
1332 | |
1333 assembler->Bind(&if_lhsisnotboolean); | |
1334 { | |
1335 // The {lhs} is either Null or Undefined; check if the {rhs} is | |
1336 // undetectable (i.e. either also Null or Undefined or some | |
1337 // undetectable JSReceiver). | |
1338 Node* rhs_bitfield = assembler->LoadMapBitField(rhs_map); | |
1339 assembler->BranchIfWord32Equal( | |
1340 assembler->Word32And( | |
1341 rhs_bitfield, | |
1342 assembler->Int32Constant(1 << Map::kIsUndetectable)), | |
1343 assembler->Int32Constant(0), &if_notequal, &if_equal); | |
1344 } | |
1345 } | |
1346 | |
1347 assembler->Bind(&if_lhsissymbol); | |
1348 { | |
1349 // Check if the {rhs} is a JSReceiver. | |
1350 Label if_rhsisreceiver(assembler, Label::kDeferred), | |
1351 if_rhsisnotreceiver(assembler); | |
1352 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); | |
1353 assembler->Branch( | |
1354 assembler->Int32LessThanOrEqual( | |
1355 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE), | |
1356 rhs_instancetype), | |
1357 &if_rhsisreceiver, &if_rhsisnotreceiver); | |
1358 | |
1359 assembler->Bind(&if_rhsisreceiver); | |
1360 { | |
1361 // The {lhs} is a Primitive and the {rhs} is a JSReceiver. | |
1362 // Swapping {lhs} and {rhs} is not observable and doesn't | |
1363 // matter for the result, so we can just swap them and use | |
1364 // the JSReceiver handling below (for {lhs} being a JSReceiver). | |
1365 var_lhs.Bind(rhs); | |
1366 var_rhs.Bind(lhs); | |
1367 assembler->Goto(&loop); | |
1368 } | |
1369 | |
1370 assembler->Bind(&if_rhsisnotreceiver); | |
1371 { | |
1372 // The {rhs} is not a JSReceiver and also not the same Symbol | |
1373 // as the {lhs}, so this is equality check is considered false. | |
1374 assembler->Goto(&if_notequal); | |
1375 } | |
1376 } | |
1377 | |
1378 assembler->Bind(&if_lhsissimd128value); | |
1379 { | |
1380 // Check if the {rhs} is also a Simd128Value. | |
1381 Label if_rhsissimd128value(assembler), | |
1382 if_rhsisnotsimd128value(assembler); | |
1383 assembler->Branch( | |
1384 assembler->Word32Equal(lhs_instancetype, rhs_instancetype), | |
1385 &if_rhsissimd128value, &if_rhsisnotsimd128value); | |
1386 | |
1387 assembler->Bind(&if_rhsissimd128value); | |
1388 { | |
1389 // Both {lhs} and {rhs} is a Simd128Value. | |
1390 GenerateEqual_Simd128Value_HeapObject(assembler, lhs, lhs_map, | |
1391 rhs, rhs_map, &if_equal, | |
1392 &if_notequal); | |
1393 } | |
1394 | |
1395 assembler->Bind(&if_rhsisnotsimd128value); | |
1396 { | |
1397 // Check if the {rhs} is a JSReceiver. | |
1398 Label if_rhsisreceiver(assembler, Label::kDeferred), | |
1399 if_rhsisnotreceiver(assembler); | |
1400 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); | |
1401 assembler->Branch( | |
1402 assembler->Int32LessThanOrEqual( | |
1403 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE), | |
1404 rhs_instancetype), | |
1405 &if_rhsisreceiver, &if_rhsisnotreceiver); | |
1406 | |
1407 assembler->Bind(&if_rhsisreceiver); | |
1408 { | |
1409 // The {lhs} is a Primitive and the {rhs} is a JSReceiver. | |
1410 // Swapping {lhs} and {rhs} is not observable and doesn't | |
1411 // matter for the result, so we can just swap them and use | |
1412 // the JSReceiver handling below (for {lhs} being a JSReceiver). | |
1413 var_lhs.Bind(rhs); | |
1414 var_rhs.Bind(lhs); | |
1415 assembler->Goto(&loop); | |
1416 } | |
1417 | |
1418 assembler->Bind(&if_rhsisnotreceiver); | |
1419 { | |
1420 // The {rhs} is some other Primitive. | |
1421 assembler->Goto(&if_notequal); | |
1422 } | |
1423 } | |
1424 } | |
1425 | |
1426 assembler->Bind(&if_lhsisreceiver); | |
1427 { | |
1428 // Check if the {rhs} is also a JSReceiver. | |
1429 Label if_rhsisreceiver(assembler), if_rhsisnotreceiver(assembler); | |
1430 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE); | |
1431 assembler->Branch( | |
1432 assembler->Int32LessThanOrEqual( | |
1433 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE), | |
1434 rhs_instancetype), | |
1435 &if_rhsisreceiver, &if_rhsisnotreceiver); | |
1436 | |
1437 assembler->Bind(&if_rhsisreceiver); | |
1438 { | |
1439 // Both {lhs} and {rhs} are different JSReceiver references, so | |
1440 // this cannot be considered equal. | |
1441 assembler->Goto(&if_notequal); | |
1442 } | |
1443 | |
1444 assembler->Bind(&if_rhsisnotreceiver); | |
1445 { | |
1446 // Check if {rhs} is Null or Undefined (an undetectable check | |
1447 // is sufficient here, since we already know that {rhs} is not | |
1448 // a JSReceiver). | |
1449 Label if_rhsisundetectable(assembler), | |
1450 if_rhsisnotundetectable(assembler, Label::kDeferred); | |
1451 Node* rhs_bitfield = assembler->LoadMapBitField(rhs_map); | |
1452 assembler->BranchIfWord32Equal( | |
1453 assembler->Word32And( | |
1454 rhs_bitfield, | |
1455 assembler->Int32Constant(1 << Map::kIsUndetectable)), | |
1456 assembler->Int32Constant(0), &if_rhsisnotundetectable, | |
1457 &if_rhsisundetectable); | |
1458 | |
1459 assembler->Bind(&if_rhsisundetectable); | |
1460 { | |
1461 // Check if {lhs} is an undetectable JSReceiver. | |
1462 Node* lhs_bitfield = assembler->LoadMapBitField(lhs_map); | |
1463 assembler->BranchIfWord32Equal( | |
1464 assembler->Word32And( | |
1465 lhs_bitfield, | |
1466 assembler->Int32Constant(1 << Map::kIsUndetectable)), | |
1467 assembler->Int32Constant(0), &if_notequal, &if_equal); | |
1468 } | |
1469 | |
1470 assembler->Bind(&if_rhsisnotundetectable); | |
1471 { | |
1472 // The {rhs} is some Primitive different from Null and | |
1473 // Undefined, need to convert {lhs} to Primitive first. | |
1474 // TODO(bmeurer): Hook up ToPrimitiveStub here once it exists. | |
1475 var_lhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive, | |
1476 context, lhs)); | |
1477 assembler->Goto(&loop); | |
1478 } | |
1479 } | |
1480 } | |
1481 } | |
1482 } | |
1483 } | |
1484 } | |
1485 | |
1486 assembler->Bind(&do_fcmp); | |
1487 { | |
1488 // Load the {lhs} and {rhs} floating point values. | |
1489 Node* lhs = var_fcmp_lhs.value(); | |
1490 Node* rhs = var_fcmp_rhs.value(); | |
1491 | |
1492 // Perform a fast floating point comparison. | |
1493 assembler->BranchIfFloat64Equal(lhs, rhs, &if_equal, &if_notequal); | |
1494 } | |
1495 | |
1496 assembler->Bind(&if_equal); | |
1497 assembler->Return(assembler->BooleanConstant(mode == kDontNegateResult)); | |
1498 | |
1499 assembler->Bind(&if_notequal); | |
1500 assembler->Return(assembler->BooleanConstant(mode == kNegateResult)); | |
1501 } | |
1502 | |
851 void GenerateStrictEqual(compiler::CodeStubAssembler* assembler, | 1503 void GenerateStrictEqual(compiler::CodeStubAssembler* assembler, |
852 ResultMode mode) { | 1504 ResultMode mode) { |
853 // Here's pseudo-code for the algorithm below in case of kDontNegateResult | 1505 // Here's pseudo-code for the algorithm below in case of kDontNegateResult |
854 // mode; for kNegateResult mode we properly negate the result. | 1506 // mode; for kNegateResult mode we properly negate the result. |
855 // | 1507 // |
856 // if (lhs == rhs) { | 1508 // if (lhs == rhs) { |
857 // if (lhs->IsHeapNumber()) return HeapNumber::cast(lhs)->value() != NaN; | 1509 // if (lhs->IsHeapNumber()) return HeapNumber::cast(lhs)->value() != NaN; |
858 // return true; | 1510 // return true; |
859 // } | 1511 // } |
860 // if (!lhs->IsSmi()) { | 1512 // if (!lhs->IsSmi()) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
908 Label if_equal(assembler), if_notequal(assembler); | 1560 Label if_equal(assembler), if_notequal(assembler); |
909 | 1561 |
910 // Check if {lhs} and {rhs} refer to the same object. | 1562 // Check if {lhs} and {rhs} refer to the same object. |
911 Label if_same(assembler), if_notsame(assembler); | 1563 Label if_same(assembler), if_notsame(assembler); |
912 assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame); | 1564 assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame); |
913 | 1565 |
914 assembler->Bind(&if_same); | 1566 assembler->Bind(&if_same); |
915 { | 1567 { |
916 // The {lhs} and {rhs} reference the exact same value, yet we need special | 1568 // The {lhs} and {rhs} reference the exact same value, yet we need special |
917 // treatment for HeapNumber, as NaN is not equal to NaN. | 1569 // treatment for HeapNumber, as NaN is not equal to NaN. |
918 // TODO(bmeurer): This seems to violate the SIMD.js specification, but it | 1570 GenerateEqual_Same(assembler, lhs, &if_equal, &if_notequal); |
919 // seems to be what is tested in the current SIMD.js testsuite. | |
920 | |
921 // Check if {lhs} (and therefore {rhs}) is a Smi or a HeapObject. | |
922 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); | |
923 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); | |
924 | |
925 assembler->Bind(&if_lhsisnotsmi); | |
926 { | |
927 // Load the map of {lhs}. | |
928 Node* lhs_map = assembler->LoadObjectField(lhs, HeapObject::kMapOffset); | |
929 | |
930 // Check if {lhs} (and therefore {rhs}) is a HeapNumber. | |
931 Node* number_map = assembler->HeapNumberMapConstant(); | |
932 Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler); | |
933 assembler->Branch(assembler->WordEqual(lhs_map, number_map), | |
934 &if_lhsisnumber, &if_lhsisnotnumber); | |
935 | |
936 assembler->Bind(&if_lhsisnumber); | |
937 { | |
938 // Convert {lhs} (and therefore {rhs}) to floating point value. | |
939 Node* lhs_value = assembler->LoadHeapNumberValue(lhs); | |
940 | |
941 // Check if the HeapNumber value is a NaN. | |
942 assembler->BranchIfFloat64IsNaN(lhs_value, &if_notequal, &if_equal); | |
943 } | |
944 | |
945 assembler->Bind(&if_lhsisnotnumber); | |
946 assembler->Goto(&if_equal); | |
947 } | |
948 | |
949 assembler->Bind(&if_lhsissmi); | |
950 assembler->Goto(&if_equal); | |
951 } | 1571 } |
952 | 1572 |
953 assembler->Bind(&if_notsame); | 1573 assembler->Bind(&if_notsame); |
954 { | 1574 { |
955 // The {lhs} and {rhs} reference different objects, yet for Smi, HeapNumber, | 1575 // The {lhs} and {rhs} reference different objects, yet for Smi, HeapNumber, |
956 // String and Simd128Value they can still be considered equal. | 1576 // String and Simd128Value they can still be considered equal. |
957 Node* number_map = assembler->HeapNumberMapConstant(); | 1577 Node* number_map = assembler->HeapNumberMapConstant(); |
958 | 1578 |
959 // Check if {lhs} is a Smi or a HeapObject. | 1579 // Check if {lhs} is a Smi or a HeapObject. |
960 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); | 1580 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); |
961 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); | 1581 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); |
962 | 1582 |
963 assembler->Bind(&if_lhsisnotsmi); | 1583 assembler->Bind(&if_lhsisnotsmi); |
964 { | 1584 { |
965 // Load the map of {lhs}. | 1585 // Load the map of {lhs}. |
966 Node* lhs_map = assembler->LoadObjectField(lhs, HeapObject::kMapOffset); | 1586 Node* lhs_map = assembler->LoadMap(lhs); |
967 | 1587 |
968 // Check if {lhs} is a HeapNumber. | 1588 // Check if {lhs} is a HeapNumber. |
969 Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler); | 1589 Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler); |
970 assembler->Branch(assembler->WordEqual(lhs_map, number_map), | 1590 assembler->Branch(assembler->WordEqual(lhs_map, number_map), |
971 &if_lhsisnumber, &if_lhsisnotnumber); | 1591 &if_lhsisnumber, &if_lhsisnotnumber); |
972 | 1592 |
973 assembler->Bind(&if_lhsisnumber); | 1593 assembler->Bind(&if_lhsisnumber); |
974 { | 1594 { |
975 // Check if {rhs} is a Smi or a HeapObject. | 1595 // Check if {rhs} is a Smi or a HeapObject. |
976 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); | 1596 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
977 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, | 1597 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
978 &if_rhsisnotsmi); | 1598 &if_rhsisnotsmi); |
979 | 1599 |
980 assembler->Bind(&if_rhsissmi); | 1600 assembler->Bind(&if_rhsissmi); |
981 { | 1601 { |
982 // Convert {lhs} and {rhs} to floating point values. | 1602 // Convert {lhs} and {rhs} to floating point values. |
983 Node* lhs_value = assembler->LoadHeapNumberValue(lhs); | 1603 Node* lhs_value = assembler->LoadHeapNumberValue(lhs); |
984 Node* rhs_value = assembler->SmiToFloat64(rhs); | 1604 Node* rhs_value = assembler->SmiToFloat64(rhs); |
985 | 1605 |
986 // Perform a floating point comparison of {lhs} and {rhs}. | 1606 // Perform a floating point comparison of {lhs} and {rhs}. |
987 assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_equal, | 1607 assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_equal, |
988 &if_notequal); | 1608 &if_notequal); |
989 } | 1609 } |
990 | 1610 |
991 assembler->Bind(&if_rhsisnotsmi); | 1611 assembler->Bind(&if_rhsisnotsmi); |
992 { | 1612 { |
993 // Load the map of {rhs}. | 1613 // Load the map of {rhs}. |
994 Node* rhs_map = | 1614 Node* rhs_map = assembler->LoadMap(rhs); |
995 assembler->LoadObjectField(rhs, HeapObject::kMapOffset); | |
996 | 1615 |
997 // Check if {rhs} is also a HeapNumber. | 1616 // Check if {rhs} is also a HeapNumber. |
998 Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler); | 1617 Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler); |
999 assembler->Branch(assembler->WordEqual(rhs_map, number_map), | 1618 assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
1000 &if_rhsisnumber, &if_rhsisnotnumber); | 1619 &if_rhsisnumber, &if_rhsisnotnumber); |
1001 | 1620 |
1002 assembler->Bind(&if_rhsisnumber); | 1621 assembler->Bind(&if_rhsisnumber); |
1003 { | 1622 { |
1004 // Convert {lhs} and {rhs} to floating point values. | 1623 // Convert {lhs} and {rhs} to floating point values. |
1005 Node* lhs_value = assembler->LoadHeapNumberValue(lhs); | 1624 Node* lhs_value = assembler->LoadHeapNumberValue(lhs); |
(...skipping 15 matching lines...) Expand all Loading... | |
1021 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); | 1640 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
1022 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, | 1641 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
1023 &if_rhsisnotsmi); | 1642 &if_rhsisnotsmi); |
1024 | 1643 |
1025 assembler->Bind(&if_rhsissmi); | 1644 assembler->Bind(&if_rhsissmi); |
1026 assembler->Goto(&if_notequal); | 1645 assembler->Goto(&if_notequal); |
1027 | 1646 |
1028 assembler->Bind(&if_rhsisnotsmi); | 1647 assembler->Bind(&if_rhsisnotsmi); |
1029 { | 1648 { |
1030 // Load the instance type of {lhs}. | 1649 // Load the instance type of {lhs}. |
1031 Node* lhs_instance_type = assembler->LoadMapInstanceType(lhs_map); | 1650 Node* lhs_instancetype = assembler->LoadMapInstanceType(lhs_map); |
1032 | 1651 |
1033 // Check if {lhs} is a String. | 1652 // Check if {lhs} is a String. |
1034 Label if_lhsisstring(assembler), if_lhsisnotstring(assembler); | 1653 Label if_lhsisstring(assembler), if_lhsisnotstring(assembler); |
1035 assembler->Branch(assembler->Int32LessThan( | 1654 assembler->Branch(assembler->Int32LessThan( |
1036 lhs_instance_type, | 1655 lhs_instancetype, |
1037 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), | 1656 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), |
1038 &if_lhsisstring, &if_lhsisnotstring); | 1657 &if_lhsisstring, &if_lhsisnotstring); |
1039 | 1658 |
1040 assembler->Bind(&if_lhsisstring); | 1659 assembler->Bind(&if_lhsisstring); |
1041 { | 1660 { |
1042 // Load the instance type of {rhs}. | 1661 // Load the instance type of {rhs}. |
1043 Node* rhs_instance_type = assembler->LoadInstanceType(rhs); | 1662 Node* rhs_instancetype = assembler->LoadInstanceType(rhs); |
1044 | 1663 |
1045 // Check if {rhs} is also a String. | 1664 // Check if {rhs} is also a String. |
1046 Label if_rhsisstring(assembler), if_rhsisnotstring(assembler); | 1665 Label if_rhsisstring(assembler), if_rhsisnotstring(assembler); |
1047 assembler->Branch(assembler->Int32LessThan( | 1666 assembler->Branch(assembler->Int32LessThan( |
1048 rhs_instance_type, assembler->Int32Constant( | 1667 rhs_instancetype, assembler->Int32Constant( |
1049 FIRST_NONSTRING_TYPE)), | 1668 FIRST_NONSTRING_TYPE)), |
1050 &if_rhsisstring, &if_rhsisnotstring); | 1669 &if_rhsisstring, &if_rhsisnotstring); |
1051 | 1670 |
1052 assembler->Bind(&if_rhsisstring); | 1671 assembler->Bind(&if_rhsisstring); |
1053 { | 1672 { |
1054 Callable callable = | 1673 Callable callable = |
1055 (mode == kDontNegateResult) | 1674 (mode == kDontNegateResult) |
1056 ? CodeFactory::StringEqual(assembler->isolate()) | 1675 ? CodeFactory::StringEqual(assembler->isolate()) |
1057 : CodeFactory::StringNotEqual(assembler->isolate()); | 1676 : CodeFactory::StringNotEqual(assembler->isolate()); |
1058 assembler->TailCallStub(callable, context, lhs, rhs); | 1677 assembler->TailCallStub(callable, context, lhs, rhs); |
1059 } | 1678 } |
1060 | 1679 |
1061 assembler->Bind(&if_rhsisnotstring); | 1680 assembler->Bind(&if_rhsisnotstring); |
1062 assembler->Goto(&if_notequal); | 1681 assembler->Goto(&if_notequal); |
1063 } | 1682 } |
1064 | 1683 |
1065 assembler->Bind(&if_lhsisnotstring); | 1684 assembler->Bind(&if_lhsisnotstring); |
1066 { | 1685 { |
1067 // Check if {lhs} is a Simd128Value. | 1686 // Check if {lhs} is a Simd128Value. |
1068 Label if_lhsissimd128value(assembler), | 1687 Label if_lhsissimd128value(assembler), |
1069 if_lhsisnotsimd128value(assembler); | 1688 if_lhsisnotsimd128value(assembler); |
1070 assembler->Branch(assembler->Word32Equal( | 1689 assembler->Branch(assembler->Word32Equal( |
1071 lhs_instance_type, | 1690 lhs_instancetype, |
1072 assembler->Int32Constant(SIMD128_VALUE_TYPE)), | 1691 assembler->Int32Constant(SIMD128_VALUE_TYPE)), |
1073 &if_lhsissimd128value, &if_lhsisnotsimd128value); | 1692 &if_lhsissimd128value, &if_lhsisnotsimd128value); |
1074 | 1693 |
1075 assembler->Bind(&if_lhsissimd128value); | 1694 assembler->Bind(&if_lhsissimd128value); |
1076 { | 1695 { |
1077 // TODO(bmeurer): Inline the Simd128Value equality check. | 1696 // Load the map of {rhs}. |
1078 Runtime::FunctionId function_id = (mode == kDontNegateResult) | 1697 Node* rhs_map = assembler->LoadMap(rhs); |
1079 ? Runtime::kStrictEqual | 1698 |
1080 : Runtime::kStrictNotEqual; | 1699 // Check if {rhs} is also a Simd128Value that is equal to {lhs}. |
1081 assembler->TailCallRuntime(function_id, context, lhs, rhs); | 1700 GenerateEqual_Simd128Value_HeapObject(assembler, lhs, lhs_map, |
1701 rhs, rhs_map, &if_equal, | |
1702 &if_notequal); | |
1082 } | 1703 } |
1083 | 1704 |
1084 assembler->Bind(&if_lhsisnotsimd128value); | 1705 assembler->Bind(&if_lhsisnotsimd128value); |
1085 assembler->Goto(&if_notequal); | 1706 assembler->Goto(&if_notequal); |
1086 } | 1707 } |
1087 } | 1708 } |
1088 } | 1709 } |
1089 } | 1710 } |
1090 | 1711 |
1091 assembler->Bind(&if_lhsissmi); | 1712 assembler->Bind(&if_lhsissmi); |
1092 { | 1713 { |
1093 // We already know that {lhs} and {rhs} are not reference equal, and {lhs} | 1714 // We already know that {lhs} and {rhs} are not reference equal, and {lhs} |
1094 // is a Smi; so {lhs} and {rhs} can only be strictly equal if {rhs} is a | 1715 // is a Smi; so {lhs} and {rhs} can only be strictly equal if {rhs} is a |
1095 // HeapNumber with an equal floating point value. | 1716 // HeapNumber with an equal floating point value. |
1096 | 1717 |
1097 // Check if {rhs} is a Smi or a HeapObject. | 1718 // Check if {rhs} is a Smi or a HeapObject. |
1098 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); | 1719 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
1099 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, | 1720 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
1100 &if_rhsisnotsmi); | 1721 &if_rhsisnotsmi); |
1101 | 1722 |
1102 assembler->Bind(&if_rhsissmi); | 1723 assembler->Bind(&if_rhsissmi); |
1103 assembler->Goto(&if_notequal); | 1724 assembler->Goto(&if_notequal); |
1104 | 1725 |
1105 assembler->Bind(&if_rhsisnotsmi); | 1726 assembler->Bind(&if_rhsisnotsmi); |
1106 { | 1727 { |
1107 // Load the map of the {rhs}. | 1728 // Load the map of the {rhs}. |
1108 Node* rhs_map = assembler->LoadObjectField(rhs, HeapObject::kMapOffset); | 1729 Node* rhs_map = assembler->LoadMap(rhs); |
1109 | 1730 |
1110 // The {rhs} could be a HeapNumber with the same value as {lhs}. | 1731 // The {rhs} could be a HeapNumber with the same value as {lhs}. |
1111 Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler); | 1732 Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler); |
1112 assembler->Branch(assembler->WordEqual(rhs_map, number_map), | 1733 assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
1113 &if_rhsisnumber, &if_rhsisnotnumber); | 1734 &if_rhsisnumber, &if_rhsisnotnumber); |
1114 | 1735 |
1115 assembler->Bind(&if_rhsisnumber); | 1736 assembler->Bind(&if_rhsisnumber); |
1116 { | 1737 { |
1117 // Convert {lhs} and {rhs} to floating point values. | 1738 // Convert {lhs} and {rhs} to floating point values. |
1118 Node* lhs_value = assembler->SmiToFloat64(lhs); | 1739 Node* lhs_value = assembler->SmiToFloat64(lhs); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1151 // Fast check to see if {lhs} and {rhs} refer to the same String object. | 1772 // Fast check to see if {lhs} and {rhs} refer to the same String object. |
1152 Label if_same(assembler), if_notsame(assembler); | 1773 Label if_same(assembler), if_notsame(assembler); |
1153 assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame); | 1774 assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame); |
1154 | 1775 |
1155 assembler->Bind(&if_same); | 1776 assembler->Bind(&if_same); |
1156 assembler->Goto(&if_equal); | 1777 assembler->Goto(&if_equal); |
1157 | 1778 |
1158 assembler->Bind(&if_notsame); | 1779 assembler->Bind(&if_notsame); |
1159 { | 1780 { |
1160 // Load instance types of {lhs} and {rhs}. | 1781 // Load instance types of {lhs} and {rhs}. |
1161 Node* lhs_instance_type = assembler->LoadInstanceType(lhs); | 1782 Node* lhs_instancetype = assembler->LoadInstanceType(lhs); |
1162 Node* rhs_instance_type = assembler->LoadInstanceType(rhs); | 1783 Node* rhs_instancetype = assembler->LoadInstanceType(rhs); |
1163 | 1784 |
1164 // Combine the instance types into a single 16-bit value, so we can check | 1785 // Combine the instance types into a single 16-bit value, so we can check |
1165 // both of them at once. | 1786 // both of them at once. |
1166 Node* both_instance_types = assembler->Word32Or( | 1787 Node* both_instance_types = assembler->Word32Or( |
1167 lhs_instance_type, | 1788 lhs_instancetype, |
1168 assembler->Word32Shl(rhs_instance_type, assembler->Int32Constant(8))); | 1789 assembler->Word32Shl(rhs_instancetype, assembler->Int32Constant(8))); |
1169 | 1790 |
1170 // Check that both {lhs} and {rhs} are flat one-byte strings. | 1791 // Check that both {lhs} and {rhs} are flat one-byte strings. |
1171 int const kBothSeqOneByteStringMask = | 1792 int const kBothSeqOneByteStringMask = |
1172 kStringEncodingMask | kStringRepresentationMask | | 1793 kStringEncodingMask | kStringRepresentationMask | |
1173 ((kStringEncodingMask | kStringRepresentationMask) << 8); | 1794 ((kStringEncodingMask | kStringRepresentationMask) << 8); |
1174 int const kBothSeqOneByteStringTag = | 1795 int const kBothSeqOneByteStringTag = |
1175 kOneByteStringTag | kSeqStringTag | | 1796 kOneByteStringTag | kSeqStringTag | |
1176 ((kOneByteStringTag | kSeqStringTag) << 8); | 1797 ((kOneByteStringTag | kSeqStringTag) << 8); |
1177 Label if_bothonebyteseqstrings(assembler), | 1798 Label if_bothonebyteseqstrings(assembler), |
1178 if_notbothonebyteseqstrings(assembler); | 1799 if_notbothonebyteseqstrings(assembler); |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1363 Node* rhs_length = assembler->LoadObjectField(rhs, String::kLengthOffset); | 1984 Node* rhs_length = assembler->LoadObjectField(rhs, String::kLengthOffset); |
1364 | 1985 |
1365 // Check if the lengths of {lhs} and {rhs} are equal. | 1986 // Check if the lengths of {lhs} and {rhs} are equal. |
1366 Label if_lengthisequal(assembler), if_lengthisnotequal(assembler); | 1987 Label if_lengthisequal(assembler), if_lengthisnotequal(assembler); |
1367 assembler->Branch(assembler->WordEqual(lhs_length, rhs_length), | 1988 assembler->Branch(assembler->WordEqual(lhs_length, rhs_length), |
1368 &if_lengthisequal, &if_lengthisnotequal); | 1989 &if_lengthisequal, &if_lengthisnotequal); |
1369 | 1990 |
1370 assembler->Bind(&if_lengthisequal); | 1991 assembler->Bind(&if_lengthisequal); |
1371 { | 1992 { |
1372 // Load instance types of {lhs} and {rhs}. | 1993 // Load instance types of {lhs} and {rhs}. |
1373 Node* lhs_instance_type = assembler->LoadInstanceType(lhs); | 1994 Node* lhs_instancetype = assembler->LoadInstanceType(lhs); |
1374 Node* rhs_instance_type = assembler->LoadInstanceType(rhs); | 1995 Node* rhs_instancetype = assembler->LoadInstanceType(rhs); |
1375 | 1996 |
1376 // Combine the instance types into a single 16-bit value, so we can check | 1997 // Combine the instance types into a single 16-bit value, so we can check |
1377 // both of them at once. | 1998 // both of them at once. |
1378 Node* both_instance_types = assembler->Word32Or( | 1999 Node* both_instance_types = assembler->Word32Or( |
1379 lhs_instance_type, | 2000 lhs_instancetype, |
1380 assembler->Word32Shl(rhs_instance_type, assembler->Int32Constant(8))); | 2001 assembler->Word32Shl(rhs_instancetype, assembler->Int32Constant(8))); |
1381 | 2002 |
1382 // Check if both {lhs} and {rhs} are internalized. | 2003 // Check if both {lhs} and {rhs} are internalized. |
1383 int const kBothInternalizedMask = | 2004 int const kBothInternalizedMask = |
1384 kIsNotInternalizedMask | (kIsNotInternalizedMask << 8); | 2005 kIsNotInternalizedMask | (kIsNotInternalizedMask << 8); |
1385 int const kBothInternalizedTag = | 2006 int const kBothInternalizedTag = |
1386 kInternalizedTag | (kInternalizedTag << 8); | 2007 kInternalizedTag | (kInternalizedTag << 8); |
1387 Label if_bothinternalized(assembler), if_notbothinternalized(assembler); | 2008 Label if_bothinternalized(assembler), if_notbothinternalized(assembler); |
1388 assembler->Branch(assembler->Word32Equal( | 2009 assembler->Branch(assembler->Word32Equal( |
1389 assembler->Word32And(both_instance_types, | 2010 assembler->Word32And(both_instance_types, |
1390 assembler->Int32Constant( | 2011 assembler->Int32Constant( |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1511 void GreaterThanStub::GenerateAssembly( | 2132 void GreaterThanStub::GenerateAssembly( |
1512 compiler::CodeStubAssembler* assembler) const { | 2133 compiler::CodeStubAssembler* assembler) const { |
1513 GenerateAbstractRelationalComparison(assembler, kGreaterThan); | 2134 GenerateAbstractRelationalComparison(assembler, kGreaterThan); |
1514 } | 2135 } |
1515 | 2136 |
1516 void GreaterThanOrEqualStub::GenerateAssembly( | 2137 void GreaterThanOrEqualStub::GenerateAssembly( |
1517 compiler::CodeStubAssembler* assembler) const { | 2138 compiler::CodeStubAssembler* assembler) const { |
1518 GenerateAbstractRelationalComparison(assembler, kGreaterThanOrEqual); | 2139 GenerateAbstractRelationalComparison(assembler, kGreaterThanOrEqual); |
1519 } | 2140 } |
1520 | 2141 |
2142 void EqualStub::GenerateAssembly(compiler::CodeStubAssembler* assembler) const { | |
2143 GenerateEqual(assembler, kDontNegateResult); | |
2144 } | |
2145 | |
2146 void NotEqualStub::GenerateAssembly( | |
2147 compiler::CodeStubAssembler* assembler) const { | |
2148 GenerateEqual(assembler, kNegateResult); | |
2149 } | |
2150 | |
1521 void StrictEqualStub::GenerateAssembly( | 2151 void StrictEqualStub::GenerateAssembly( |
1522 compiler::CodeStubAssembler* assembler) const { | 2152 compiler::CodeStubAssembler* assembler) const { |
1523 GenerateStrictEqual(assembler, kDontNegateResult); | 2153 GenerateStrictEqual(assembler, kDontNegateResult); |
1524 } | 2154 } |
1525 | 2155 |
1526 void StrictNotEqualStub::GenerateAssembly( | 2156 void StrictNotEqualStub::GenerateAssembly( |
1527 compiler::CodeStubAssembler* assembler) const { | 2157 compiler::CodeStubAssembler* assembler) const { |
1528 GenerateStrictEqual(assembler, kNegateResult); | 2158 GenerateStrictEqual(assembler, kNegateResult); |
1529 } | 2159 } |
1530 | 2160 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1583 assembler->Bind(&if_valueisnotzero); | 2213 assembler->Bind(&if_valueisnotzero); |
1584 assembler->Return(assembler->BooleanConstant(true)); | 2214 assembler->Return(assembler->BooleanConstant(true)); |
1585 } | 2215 } |
1586 | 2216 |
1587 assembler->Bind(&if_valueisnotsmi); | 2217 assembler->Bind(&if_valueisnotsmi); |
1588 { | 2218 { |
1589 Label if_valueisstring(assembler), if_valueisheapnumber(assembler), | 2219 Label if_valueisstring(assembler), if_valueisheapnumber(assembler), |
1590 if_valueisoddball(assembler), if_valueisother(assembler); | 2220 if_valueisoddball(assembler), if_valueisother(assembler); |
1591 | 2221 |
1592 // The {value} is a HeapObject, load its map. | 2222 // The {value} is a HeapObject, load its map. |
1593 Node* value_map = assembler->LoadObjectField(value, HeapObject::kMapOffset); | 2223 Node* value_map = assembler->LoadMap(value); |
1594 | 2224 |
1595 // Load the {value}s instance type. | 2225 // Load the {value}s instance type. |
1596 Node* value_instancetype = assembler->Load( | 2226 Node* value_instancetype = assembler->Load( |
1597 MachineType::Uint8(), value_map, | 2227 MachineType::Uint8(), value_map, |
1598 assembler->IntPtrConstant(Map::kInstanceTypeOffset - kHeapObjectTag)); | 2228 assembler->IntPtrConstant(Map::kInstanceTypeOffset - kHeapObjectTag)); |
1599 | 2229 |
1600 // Dispatch based on the instance type; we distinguish all String instance | 2230 // Dispatch based on the instance type; we distinguish all String instance |
1601 // types, the HeapNumber type and the Oddball type. | 2231 // types, the HeapNumber type and the Oddball type. |
1602 size_t const kNumCases = FIRST_NONSTRING_TYPE + 2; | 2232 size_t const kNumCases = FIRST_NONSTRING_TYPE + 2; |
1603 Label* case_labels[kNumCases]; | 2233 Label* case_labels[kNumCases]; |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2126 if (type->Is(Type::UntaggedPointer())) { | 2756 if (type->Is(Type::UntaggedPointer())) { |
2127 return Representation::External(); | 2757 return Representation::External(); |
2128 } | 2758 } |
2129 | 2759 |
2130 DCHECK(!type->Is(Type::Untagged())); | 2760 DCHECK(!type->Is(Type::Untagged())); |
2131 return Representation::Tagged(); | 2761 return Representation::Tagged(); |
2132 } | 2762 } |
2133 | 2763 |
2134 } // namespace internal | 2764 } // namespace internal |
2135 } // namespace v8 | 2765 } // namespace v8 |
OLD | NEW |