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 176 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_instance_type = 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_instance_type, 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_instance_type), |
| 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_instance_type = assembler->LoadMapInstanceType(lhs_map); |
| 1157 Node* rhs_instance_type = 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) { |
| 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_instance_type, &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_instance_type, 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_instance_type, rhs_instance_type), |
| 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_instance_type, |
| 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_instance_type), |
| 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_instance_type), |
| 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_instance_type, rhs_instance_type), |
| 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_instance_type), |
| 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_instance_type), |
| 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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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_instance_type, |
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 392 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_instance_type = 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]; |
1604 int32_t case_values[kNumCases]; | 2234 int32_t case_values[kNumCases]; |
1605 for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) { | 2235 for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) { |
1606 case_labels[i] = new Label(assembler); | 2236 case_labels[i] = new Label(assembler); |
1607 case_values[i] = i; | 2237 case_values[i] = i; |
1608 } | 2238 } |
1609 case_labels[FIRST_NONSTRING_TYPE + 0] = &if_valueisheapnumber; | 2239 case_labels[FIRST_NONSTRING_TYPE + 0] = &if_valueisheapnumber; |
1610 case_values[FIRST_NONSTRING_TYPE + 0] = HEAP_NUMBER_TYPE; | 2240 case_values[FIRST_NONSTRING_TYPE + 0] = HEAP_NUMBER_TYPE; |
1611 case_labels[FIRST_NONSTRING_TYPE + 1] = &if_valueisoddball; | 2241 case_labels[FIRST_NONSTRING_TYPE + 1] = &if_valueisoddball; |
1612 case_values[FIRST_NONSTRING_TYPE + 1] = ODDBALL_TYPE; | 2242 case_values[FIRST_NONSTRING_TYPE + 1] = ODDBALL_TYPE; |
1613 assembler->Switch(value_instancetype, &if_valueisother, case_values, | 2243 assembler->Switch(value_instance_type, &if_valueisother, case_values, |
1614 case_labels, arraysize(case_values)); | 2244 case_labels, arraysize(case_values)); |
1615 for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) { | 2245 for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) { |
1616 assembler->Bind(case_labels[i]); | 2246 assembler->Bind(case_labels[i]); |
1617 assembler->Goto(&if_valueisstring); | 2247 assembler->Goto(&if_valueisstring); |
1618 delete case_labels[i]; | 2248 delete case_labels[i]; |
1619 } | 2249 } |
1620 | 2250 |
1621 assembler->Bind(&if_valueisstring); | 2251 assembler->Bind(&if_valueisstring); |
1622 { | 2252 { |
1623 // Load the string length field of the {value}. | 2253 // Load the string length field of the {value}. |
(...skipping 502 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 |