Chromium Code Reviews| 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 |