Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: src/code-stubs.cc

Issue 1795793002: [compiler] Introduce code stubs for abstract equality. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: instancetype -> instance_type Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/code-stubs.h ('k') | src/compiler/code-stub-assembler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/code-stubs.h ('k') | src/compiler/code-stub-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698