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 1048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1059 // static | 1059 // static |
1060 compiler::Node* MultiplyStub::Generate(CodeStubAssembler* assembler, | 1060 compiler::Node* MultiplyStub::Generate(CodeStubAssembler* assembler, |
1061 compiler::Node* left, | 1061 compiler::Node* left, |
1062 compiler::Node* right, | 1062 compiler::Node* right, |
1063 compiler::Node* context) { | 1063 compiler::Node* context) { |
1064 using compiler::Node; | 1064 using compiler::Node; |
1065 typedef CodeStubAssembler::Label Label; | 1065 typedef CodeStubAssembler::Label Label; |
1066 typedef CodeStubAssembler::Variable Variable; | 1066 typedef CodeStubAssembler::Variable Variable; |
1067 | 1067 |
1068 // Shared entry point for floating point multiplication. | 1068 // Shared entry point for floating point multiplication. |
1069 Label do_fmul(assembler); | 1069 Label do_fmul(assembler), return_result(assembler); |
1070 Variable var_lhs_float64(assembler, MachineRepresentation::kFloat64), | 1070 Variable var_lhs_float64(assembler, MachineRepresentation::kFloat64), |
1071 var_rhs_float64(assembler, MachineRepresentation::kFloat64); | 1071 var_rhs_float64(assembler, MachineRepresentation::kFloat64); |
1072 | 1072 |
1073 Node* number_map = assembler->HeapNumberMapConstant(); | 1073 Node* number_map = assembler->HeapNumberMapConstant(); |
1074 | 1074 |
1075 // We might need to loop one or two times due to ToNumber conversions. | 1075 // We might need to loop one or two times due to ToNumber conversions. |
1076 Variable var_lhs(assembler, MachineRepresentation::kTagged), | 1076 Variable var_lhs(assembler, MachineRepresentation::kTagged), |
1077 var_rhs(assembler, MachineRepresentation::kTagged); | 1077 var_rhs(assembler, MachineRepresentation::kTagged), |
| 1078 var_result(assembler, MachineRepresentation::kTagged); |
1078 Variable* loop_variables[] = {&var_lhs, &var_rhs}; | 1079 Variable* loop_variables[] = {&var_lhs, &var_rhs}; |
1079 Label loop(assembler, 2, loop_variables); | 1080 Label loop(assembler, 2, loop_variables); |
1080 var_lhs.Bind(left); | 1081 var_lhs.Bind(left); |
1081 var_rhs.Bind(right); | 1082 var_rhs.Bind(right); |
1082 assembler->Goto(&loop); | 1083 assembler->Goto(&loop); |
1083 assembler->Bind(&loop); | 1084 assembler->Bind(&loop); |
1084 { | 1085 { |
1085 Node* lhs = var_lhs.value(); | 1086 Node* lhs = var_lhs.value(); |
1086 Node* rhs = var_rhs.value(); | 1087 Node* rhs = var_rhs.value(); |
1087 | 1088 |
1088 Label lhs_is_smi(assembler), lhs_is_not_smi(assembler); | 1089 Label lhs_is_smi(assembler), lhs_is_not_smi(assembler); |
1089 assembler->Branch(assembler->WordIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi); | 1090 assembler->Branch(assembler->WordIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi); |
1090 | 1091 |
1091 assembler->Bind(&lhs_is_smi); | 1092 assembler->Bind(&lhs_is_smi); |
1092 { | 1093 { |
1093 Label rhs_is_smi(assembler), rhs_is_not_smi(assembler); | 1094 Label rhs_is_smi(assembler), rhs_is_not_smi(assembler); |
1094 assembler->Branch(assembler->WordIsSmi(rhs), &rhs_is_smi, | 1095 assembler->Branch(assembler->WordIsSmi(rhs), &rhs_is_smi, |
1095 &rhs_is_not_smi); | 1096 &rhs_is_not_smi); |
1096 | 1097 |
1097 assembler->Bind(&rhs_is_smi); | 1098 assembler->Bind(&rhs_is_smi); |
1098 { | 1099 { |
1099 // Both {lhs} and {rhs} are Smis. Convert them to double and multiply. | 1100 // Both {lhs} and {rhs} are Smis. Convert them to integers and multiply. |
1100 // TODO(epertoso): use SmiMulWithOverflow once available. | 1101 Node* lhs32 = assembler->SmiToWord32(lhs); |
1101 var_lhs_float64.Bind(assembler->SmiToFloat64(lhs)); | 1102 Node* rhs32 = assembler->SmiToWord32(rhs); |
1102 var_rhs_float64.Bind(assembler->SmiToFloat64(rhs)); | 1103 Node* pair = assembler->Int32MulWithOverflow(lhs32, rhs32); |
1103 assembler->Goto(&do_fmul); | 1104 |
| 1105 Node* overflow = assembler->Projection(1, pair); |
| 1106 |
| 1107 // Check if the multiplication overflowed. |
| 1108 Label if_overflow(assembler, Label::kDeferred), |
| 1109 if_notoverflow(assembler); |
| 1110 assembler->Branch(overflow, &if_overflow, &if_notoverflow); |
| 1111 assembler->Bind(&if_notoverflow); |
| 1112 { |
| 1113 // If the answer is zero, we may need to return -0.0, depending on the |
| 1114 // input. |
| 1115 Label answer_zero(assembler), answer_not_zero(assembler); |
| 1116 Node* answer = assembler->Projection(0, pair); |
| 1117 Node* zero = assembler->Int32Constant(0); |
| 1118 assembler->Branch(assembler->WordEqual(answer, zero), &answer_zero, |
| 1119 &answer_not_zero); |
| 1120 assembler->Bind(&answer_not_zero); |
| 1121 { |
| 1122 var_result.Bind(assembler->ChangeInt32ToTagged(answer)); |
| 1123 assembler->Goto(&return_result); |
| 1124 } |
| 1125 assembler->Bind(&answer_zero); |
| 1126 { |
| 1127 Node* or_result = assembler->Word32Or(lhs32, rhs32); |
| 1128 Label if_should_be_negative_zero(assembler), |
| 1129 if_should_be_zero(assembler); |
| 1130 assembler->Branch(assembler->Int32LessThan(or_result, zero), |
| 1131 &if_should_be_negative_zero, &if_should_be_zero); |
| 1132 assembler->Bind(&if_should_be_negative_zero); |
| 1133 { |
| 1134 var_result.Bind(assembler->MinusZeroConstant()); |
| 1135 assembler->Goto(&return_result); |
| 1136 } |
| 1137 assembler->Bind(&if_should_be_zero); |
| 1138 { |
| 1139 var_result.Bind(zero); |
| 1140 assembler->Goto(&return_result); |
| 1141 } |
| 1142 } |
| 1143 } |
| 1144 assembler->Bind(&if_overflow); |
| 1145 { |
| 1146 var_lhs_float64.Bind(assembler->SmiToFloat64(lhs)); |
| 1147 var_rhs_float64.Bind(assembler->SmiToFloat64(rhs)); |
| 1148 assembler->Goto(&do_fmul); |
| 1149 } |
1104 } | 1150 } |
1105 | 1151 |
1106 assembler->Bind(&rhs_is_not_smi); | 1152 assembler->Bind(&rhs_is_not_smi); |
1107 { | 1153 { |
1108 Node* rhs_map = assembler->LoadMap(rhs); | 1154 Node* rhs_map = assembler->LoadMap(rhs); |
1109 | 1155 |
1110 // Check if {rhs} is a HeapNumber. | 1156 // Check if {rhs} is a HeapNumber. |
1111 Label rhs_is_number(assembler), | 1157 Label rhs_is_number(assembler), |
1112 rhs_is_not_number(assembler, Label::kDeferred); | 1158 rhs_is_not_number(assembler, Label::kDeferred); |
1113 assembler->Branch(assembler->WordEqual(rhs_map, number_map), | 1159 assembler->Branch(assembler->WordEqual(rhs_map, number_map), |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1194 assembler->Goto(&loop); | 1240 assembler->Goto(&loop); |
1195 } | 1241 } |
1196 } | 1242 } |
1197 } | 1243 } |
1198 | 1244 |
1199 assembler->Bind(&do_fmul); | 1245 assembler->Bind(&do_fmul); |
1200 { | 1246 { |
1201 Node* value = | 1247 Node* value = |
1202 assembler->Float64Mul(var_lhs_float64.value(), var_rhs_float64.value()); | 1248 assembler->Float64Mul(var_lhs_float64.value(), var_rhs_float64.value()); |
1203 Node* result = assembler->ChangeFloat64ToTagged(value); | 1249 Node* result = assembler->ChangeFloat64ToTagged(value); |
1204 return result; | 1250 var_result.Bind(result); |
| 1251 assembler->Goto(&return_result); |
1205 } | 1252 } |
| 1253 |
| 1254 assembler->Bind(&return_result); |
| 1255 return var_result.value(); |
1206 } | 1256 } |
1207 | 1257 |
1208 // static | 1258 // static |
1209 compiler::Node* DivideStub::Generate(CodeStubAssembler* assembler, | 1259 compiler::Node* DivideStub::Generate(CodeStubAssembler* assembler, |
1210 compiler::Node* left, | 1260 compiler::Node* left, |
1211 compiler::Node* right, | 1261 compiler::Node* right, |
1212 compiler::Node* context) { | 1262 compiler::Node* context) { |
1213 using compiler::Node; | 1263 using compiler::Node; |
1214 typedef CodeStubAssembler::Label Label; | 1264 typedef CodeStubAssembler::Label Label; |
1215 typedef CodeStubAssembler::Variable Variable; | 1265 typedef CodeStubAssembler::Variable Variable; |
(...skipping 3714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4930 if (type->Is(Type::UntaggedPointer())) { | 4980 if (type->Is(Type::UntaggedPointer())) { |
4931 return Representation::External(); | 4981 return Representation::External(); |
4932 } | 4982 } |
4933 | 4983 |
4934 DCHECK(!type->Is(Type::Untagged())); | 4984 DCHECK(!type->Is(Type::Untagged())); |
4935 return Representation::Tagged(); | 4985 return Representation::Tagged(); |
4936 } | 4986 } |
4937 | 4987 |
4938 } // namespace internal | 4988 } // namespace internal |
4939 } // namespace v8 | 4989 } // namespace v8 |
OLD | NEW |