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 892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
903 assembler->Goto(&end); | 903 assembler->Goto(&end); |
904 } | 904 } |
905 assembler->Bind(&end); | 905 assembler->Bind(&end); |
906 return var_result.value(); | 906 return var_result.value(); |
907 } | 907 } |
908 | 908 |
909 // static | 909 // static |
910 compiler::Node* SubtractStub::Generate(CodeStubAssembler* assembler, | 910 compiler::Node* SubtractStub::Generate(CodeStubAssembler* assembler, |
911 compiler::Node* left, | 911 compiler::Node* left, |
912 compiler::Node* right, | 912 compiler::Node* right, |
913 compiler::Node* context) { | 913 compiler::Node* context, |
914 compiler::Node* type_feedback_vector, | |
915 compiler::Node* slot_id) { | |
914 typedef CodeStubAssembler::Label Label; | 916 typedef CodeStubAssembler::Label Label; |
915 typedef compiler::Node Node; | 917 typedef compiler::Node Node; |
916 typedef CodeStubAssembler::Variable Variable; | 918 typedef CodeStubAssembler::Variable Variable; |
917 | 919 |
920 bool collect_type_feedback = (type_feedback_vector != NULL); | |
921 | |
918 // Shared entry for floating point subtraction. | 922 // Shared entry for floating point subtraction. |
919 Label do_fsub(assembler), end(assembler); | 923 Label do_fsub(assembler), end(assembler); |
920 Variable var_fsub_lhs(assembler, MachineRepresentation::kFloat64), | 924 Variable var_fsub_lhs(assembler, MachineRepresentation::kFloat64), |
921 var_fsub_rhs(assembler, MachineRepresentation::kFloat64); | 925 var_fsub_rhs(assembler, MachineRepresentation::kFloat64); |
926 Variable var_type_feedback(assembler, MachineRepresentation::kWord32); | |
Benedikt Meurer
2016/08/08 04:56:13
I'm not sure if this will scale, because
(a) it'l
mythria
2016/08/08 07:17:36
Thanks Benedikt, I add a subtract stub that deals
| |
922 | 927 |
923 // We might need to loop several times due to ToPrimitive and/or ToNumber | 928 // We might need to loop several times due to ToPrimitive and/or ToNumber |
924 // conversions. | 929 // conversions. |
925 Variable var_lhs(assembler, MachineRepresentation::kTagged), | 930 Variable var_lhs(assembler, MachineRepresentation::kTagged), |
926 var_rhs(assembler, MachineRepresentation::kTagged), | 931 var_rhs(assembler, MachineRepresentation::kTagged), |
927 var_result(assembler, MachineRepresentation::kTagged); | 932 var_result(assembler, MachineRepresentation::kTagged); |
928 Variable* loop_vars[2] = {&var_lhs, &var_rhs}; | 933 Variable* loop_vars[3] = {&var_lhs, &var_rhs, &var_type_feedback}; |
929 Label loop(assembler, 2, loop_vars); | 934 Label loop(assembler, 3, loop_vars); |
930 var_lhs.Bind(left); | 935 var_lhs.Bind(left); |
931 var_rhs.Bind(right); | 936 var_rhs.Bind(right); |
937 // Start with Smi and keep growing up the lattice. This would avoid | |
938 // incorrectly collecting Smi type after the ToNumber conversion. | |
939 var_type_feedback.Bind( | |
940 assembler->Int32Constant(BinaryOpTypeFeedback::SmiType::encode(1))); | |
932 assembler->Goto(&loop); | 941 assembler->Goto(&loop); |
942 | |
933 assembler->Bind(&loop); | 943 assembler->Bind(&loop); |
934 { | 944 { |
935 // Load the current {lhs} and {rhs} values. | 945 // Load the current {lhs} and {rhs} values. |
936 Node* lhs = var_lhs.value(); | 946 Node* lhs = var_lhs.value(); |
937 Node* rhs = var_rhs.value(); | 947 Node* rhs = var_rhs.value(); |
948 Node* type_feedback = var_type_feedback.value(); | |
938 | 949 |
939 // Check if the {lhs} is a Smi or a HeapObject. | 950 // Check if the {lhs} is a Smi or a HeapObject. |
940 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); | 951 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); |
941 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); | 952 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); |
942 | 953 |
943 assembler->Bind(&if_lhsissmi); | 954 assembler->Bind(&if_lhsissmi); |
944 { | 955 { |
945 // Check if the {rhs} is also a Smi. | 956 // Check if the {rhs} is also a Smi. |
946 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); | 957 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
947 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, | 958 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
948 &if_rhsisnotsmi); | 959 &if_rhsisnotsmi); |
949 | 960 |
950 assembler->Bind(&if_rhsissmi); | 961 assembler->Bind(&if_rhsissmi); |
951 { | 962 { |
952 // Try a fast Smi subtraction first. | 963 // Try a fast Smi subtraction first. |
953 Node* pair = assembler->SmiSubWithOverflow(lhs, rhs); | 964 Node* pair = assembler->SmiSubWithOverflow(lhs, rhs); |
954 Node* overflow = assembler->Projection(1, pair); | 965 Node* overflow = assembler->Projection(1, pair); |
955 | 966 |
956 // Check if the Smi subtraction overflowed. | 967 // Check if the Smi subtraction overflowed. |
957 Label if_overflow(assembler), if_notoverflow(assembler); | 968 Label if_overflow(assembler), if_notoverflow(assembler); |
958 assembler->Branch(overflow, &if_overflow, &if_notoverflow); | 969 assembler->Branch(overflow, &if_overflow, &if_notoverflow); |
959 | 970 |
960 assembler->Bind(&if_overflow); | 971 assembler->Bind(&if_overflow); |
961 { | 972 { |
973 // lhs, rhs - smi and result - number. combined - number. | |
962 // The result doesn't fit into Smi range. | 974 // The result doesn't fit into Smi range. |
975 Node* current_feedback = assembler->Int32Constant( | |
976 BinaryOpTypeFeedback::NumberType::encode(1)); | |
977 var_type_feedback.Bind( | |
978 assembler->Word32Or(type_feedback, current_feedback)); | |
963 var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs)); | 979 var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs)); |
964 var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs)); | 980 var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs)); |
965 assembler->Goto(&do_fsub); | 981 assembler->Goto(&do_fsub); |
966 } | 982 } |
967 | 983 |
968 assembler->Bind(&if_notoverflow); | 984 assembler->Bind(&if_notoverflow); |
985 // lhs, rhs, result smi. combined - smi. | |
986 Node* smi_feedback = | |
987 assembler->Int32Constant(BinaryOpTypeFeedback::SmiType::encode(1)); | |
988 var_type_feedback.Bind( | |
989 assembler->Word32Or(type_feedback, smi_feedback)); | |
969 var_result.Bind(assembler->Projection(0, pair)); | 990 var_result.Bind(assembler->Projection(0, pair)); |
970 assembler->Goto(&end); | 991 assembler->Goto(&end); |
971 } | 992 } |
972 | 993 |
973 assembler->Bind(&if_rhsisnotsmi); | 994 assembler->Bind(&if_rhsisnotsmi); |
974 { | 995 { |
975 // Load the map of the {rhs}. | 996 // Load the map of the {rhs}. |
976 Node* rhs_map = assembler->LoadMap(rhs); | 997 Node* rhs_map = assembler->LoadMap(rhs); |
977 | 998 |
978 // Check if {rhs} is a HeapNumber. | 999 // Check if {rhs} is a HeapNumber. |
979 Label if_rhsisnumber(assembler), | 1000 Label if_rhsisnumber(assembler), |
980 if_rhsisnotnumber(assembler, Label::kDeferred); | 1001 if_rhsisnotnumber(assembler, Label::kDeferred); |
981 Node* number_map = assembler->HeapNumberMapConstant(); | 1002 Node* number_map = assembler->HeapNumberMapConstant(); |
982 assembler->Branch(assembler->WordEqual(rhs_map, number_map), | 1003 assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
983 &if_rhsisnumber, &if_rhsisnotnumber); | 1004 &if_rhsisnumber, &if_rhsisnotnumber); |
984 | 1005 |
985 assembler->Bind(&if_rhsisnumber); | 1006 assembler->Bind(&if_rhsisnumber); |
986 { | 1007 { |
1008 Node* current_feedback = assembler->Int32Constant( | |
1009 BinaryOpTypeFeedback::NumberType::encode(1)); | |
1010 var_type_feedback.Bind( | |
1011 assembler->Word32Or(type_feedback, current_feedback)); | |
987 // Perform a floating point subtraction. | 1012 // Perform a floating point subtraction. |
988 var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs)); | 1013 var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs)); |
989 var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); | 1014 var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); |
990 assembler->Goto(&do_fsub); | 1015 assembler->Goto(&do_fsub); |
991 } | 1016 } |
992 | 1017 |
993 assembler->Bind(&if_rhsisnotnumber); | 1018 assembler->Bind(&if_rhsisnotnumber); |
994 { | 1019 { |
1020 Node* current_feedback = assembler->Int32Constant( | |
1021 BinaryOpTypeFeedback::AnyType::encode(1)); | |
1022 var_type_feedback.Bind( | |
1023 assembler->Word32Or(type_feedback, current_feedback)); | |
995 // Convert the {rhs} to a Number first. | 1024 // Convert the {rhs} to a Number first. |
996 Callable callable = | 1025 Callable callable = |
997 CodeFactory::NonNumberToNumber(assembler->isolate()); | 1026 CodeFactory::NonNumberToNumber(assembler->isolate()); |
998 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); | 1027 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
999 assembler->Goto(&loop); | 1028 assembler->Goto(&loop); |
1000 } | 1029 } |
1001 } | 1030 } |
1002 } | 1031 } |
1003 | 1032 |
1004 assembler->Bind(&if_lhsisnotsmi); | 1033 assembler->Bind(&if_lhsisnotsmi); |
(...skipping 10 matching lines...) Expand all Loading... | |
1015 | 1044 |
1016 assembler->Bind(&if_lhsisnumber); | 1045 assembler->Bind(&if_lhsisnumber); |
1017 { | 1046 { |
1018 // Check if the {rhs} is a Smi. | 1047 // Check if the {rhs} is a Smi. |
1019 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); | 1048 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); |
1020 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, | 1049 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, |
1021 &if_rhsisnotsmi); | 1050 &if_rhsisnotsmi); |
1022 | 1051 |
1023 assembler->Bind(&if_rhsissmi); | 1052 assembler->Bind(&if_rhsissmi); |
1024 { | 1053 { |
1054 Node* current_feedback = assembler->Int32Constant( | |
1055 BinaryOpTypeFeedback::NumberType::encode(1)); | |
1056 var_type_feedback.Bind( | |
1057 assembler->Word32Or(type_feedback, current_feedback)); | |
1025 // Perform a floating point subtraction. | 1058 // Perform a floating point subtraction. |
1026 var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); | 1059 var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); |
1027 var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs)); | 1060 var_fsub_rhs.Bind(assembler->SmiToFloat64(rhs)); |
1028 assembler->Goto(&do_fsub); | 1061 assembler->Goto(&do_fsub); |
1029 } | 1062 } |
1030 | 1063 |
1031 assembler->Bind(&if_rhsisnotsmi); | 1064 assembler->Bind(&if_rhsisnotsmi); |
1032 { | 1065 { |
1033 // Load the map of the {rhs}. | 1066 // Load the map of the {rhs}. |
1034 Node* rhs_map = assembler->LoadMap(rhs); | 1067 Node* rhs_map = assembler->LoadMap(rhs); |
1035 | 1068 |
1036 // Check if the {rhs} is a HeapNumber. | 1069 // Check if the {rhs} is a HeapNumber. |
1037 Label if_rhsisnumber(assembler), | 1070 Label if_rhsisnumber(assembler), |
1038 if_rhsisnotnumber(assembler, Label::kDeferred); | 1071 if_rhsisnotnumber(assembler, Label::kDeferred); |
1039 assembler->Branch(assembler->WordEqual(rhs_map, number_map), | 1072 assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
1040 &if_rhsisnumber, &if_rhsisnotnumber); | 1073 &if_rhsisnumber, &if_rhsisnotnumber); |
1041 | 1074 |
1042 assembler->Bind(&if_rhsisnumber); | 1075 assembler->Bind(&if_rhsisnumber); |
1043 { | 1076 { |
1077 Node* current_feedback = assembler->Int32Constant( | |
1078 BinaryOpTypeFeedback::NumberType::encode(1)); | |
1079 var_type_feedback.Bind( | |
1080 assembler->Word32Or(type_feedback, current_feedback)); | |
1044 // Perform a floating point subtraction. | 1081 // Perform a floating point subtraction. |
1045 var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); | 1082 var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); |
1046 var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); | 1083 var_fsub_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); |
1047 assembler->Goto(&do_fsub); | 1084 assembler->Goto(&do_fsub); |
1048 } | 1085 } |
1049 | 1086 |
1050 assembler->Bind(&if_rhsisnotnumber); | 1087 assembler->Bind(&if_rhsisnotnumber); |
1051 { | 1088 { |
1089 Node* current_feedback = assembler->Int32Constant( | |
1090 BinaryOpTypeFeedback::AnyType::encode(1)); | |
1091 var_type_feedback.Bind( | |
1092 assembler->Word32Or(type_feedback, current_feedback)); | |
1052 // Convert the {rhs} to a Number first. | 1093 // Convert the {rhs} to a Number first. |
1053 Callable callable = | 1094 Callable callable = |
1054 CodeFactory::NonNumberToNumber(assembler->isolate()); | 1095 CodeFactory::NonNumberToNumber(assembler->isolate()); |
1055 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); | 1096 var_rhs.Bind(assembler->CallStub(callable, context, rhs)); |
1056 assembler->Goto(&loop); | 1097 assembler->Goto(&loop); |
1057 } | 1098 } |
1058 } | 1099 } |
1059 } | 1100 } |
1060 | 1101 |
1061 assembler->Bind(&if_lhsisnotnumber); | 1102 assembler->Bind(&if_lhsisnotnumber); |
1062 { | 1103 { |
1104 Node* current_feedback = | |
1105 assembler->Int32Constant(BinaryOpTypeFeedback::AnyType::encode(1)); | |
1106 var_type_feedback.Bind( | |
1107 assembler->Word32Or(type_feedback, current_feedback)); | |
1063 // Convert the {lhs} to a Number first. | 1108 // Convert the {lhs} to a Number first. |
1064 Callable callable = | 1109 Callable callable = |
1065 CodeFactory::NonNumberToNumber(assembler->isolate()); | 1110 CodeFactory::NonNumberToNumber(assembler->isolate()); |
1066 var_lhs.Bind(assembler->CallStub(callable, context, lhs)); | 1111 var_lhs.Bind(assembler->CallStub(callable, context, lhs)); |
1067 assembler->Goto(&loop); | 1112 assembler->Goto(&loop); |
1068 } | 1113 } |
1069 } | 1114 } |
1070 } | 1115 } |
1071 | 1116 |
1072 assembler->Bind(&do_fsub); | 1117 assembler->Bind(&do_fsub); |
1073 { | 1118 { |
1074 Node* lhs_value = var_fsub_lhs.value(); | 1119 Node* lhs_value = var_fsub_lhs.value(); |
1075 Node* rhs_value = var_fsub_rhs.value(); | 1120 Node* rhs_value = var_fsub_rhs.value(); |
1076 Node* value = assembler->Float64Sub(lhs_value, rhs_value); | 1121 Node* value = assembler->Float64Sub(lhs_value, rhs_value); |
1077 var_result.Bind(assembler->ChangeFloat64ToTagged(value)); | 1122 var_result.Bind(assembler->ChangeFloat64ToTagged(value)); |
1078 assembler->Goto(&end); | 1123 assembler->Goto(&end); |
1079 } | 1124 } |
1125 | |
1080 assembler->Bind(&end); | 1126 assembler->Bind(&end); |
1127 if (collect_type_feedback) { | |
1128 // Combine the current type with previous feedback and store it into the | |
1129 // feedback slot. | |
1130 Node* previous_feedback_smi = | |
1131 assembler->LoadFixedArrayElement(type_feedback_vector, slot_id); | |
1132 // TODO(mythria): Add a DCHECK to verify the loaded value is an Smi. | |
1133 // ASSERT (WordIsSmi(previous_feedback)); | |
1134 Node* previous_feedback = assembler->SmiUntag(previous_feedback_smi); | |
1135 Node* combined_feedback = | |
1136 assembler->Word32Or(previous_feedback, var_type_feedback.value()); | |
1137 assembler->StoreFixedArrayElement(type_feedback_vector, slot_id, | |
1138 assembler->SmiTag(combined_feedback), | |
1139 SKIP_WRITE_BARRIER); | |
1140 } | |
1081 return var_result.value(); | 1141 return var_result.value(); |
1082 } | 1142 } |
1083 | 1143 |
1084 // static | 1144 // static |
1085 compiler::Node* MultiplyStub::Generate(CodeStubAssembler* assembler, | 1145 compiler::Node* MultiplyStub::Generate(CodeStubAssembler* assembler, |
1086 compiler::Node* left, | 1146 compiler::Node* left, |
1087 compiler::Node* right, | 1147 compiler::Node* right, |
1088 compiler::Node* context) { | 1148 compiler::Node* context) { |
1089 using compiler::Node; | 1149 using compiler::Node; |
1090 typedef CodeStubAssembler::Label Label; | 1150 typedef CodeStubAssembler::Label Label; |
(...skipping 3963 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5054 if (type->Is(Type::UntaggedPointer())) { | 5114 if (type->Is(Type::UntaggedPointer())) { |
5055 return Representation::External(); | 5115 return Representation::External(); |
5056 } | 5116 } |
5057 | 5117 |
5058 DCHECK(!type->Is(Type::Untagged())); | 5118 DCHECK(!type->Is(Type::Untagged())); |
5059 return Representation::Tagged(); | 5119 return Representation::Tagged(); |
5060 } | 5120 } |
5061 | 5121 |
5062 } // namespace internal | 5122 } // namespace internal |
5063 } // namespace v8 | 5123 } // namespace v8 |
OLD | NEW |