| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 1018 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1029 __ FlooringDiv(dividend, Abs(divisor)); | 1029 __ FlooringDiv(dividend, Abs(divisor)); |
| 1030 __ movl(rax, dividend); | 1030 __ movl(rax, dividend); |
| 1031 __ shrl(rax, Immediate(31)); | 1031 __ shrl(rax, Immediate(31)); |
| 1032 __ addl(rdx, rax); | 1032 __ addl(rdx, rax); |
| 1033 __ imull(rdx, rdx, Immediate(Abs(divisor))); | 1033 __ imull(rdx, rdx, Immediate(Abs(divisor))); |
| 1034 __ movl(rax, dividend); | 1034 __ movl(rax, dividend); |
| 1035 __ subl(rax, rdx); | 1035 __ subl(rax, rdx); |
| 1036 | 1036 |
| 1037 // Check for negative zero. | 1037 // Check for negative zero. |
| 1038 HMod* hmod = instr->hydrogen(); | 1038 HMod* hmod = instr->hydrogen(); |
| 1039 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero) && | 1039 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1040 hmod->left()->CanBeNegative()) { | |
| 1041 Label remainder_not_zero; | 1040 Label remainder_not_zero; |
| 1042 __ j(not_zero, &remainder_not_zero, Label::kNear); | 1041 __ j(not_zero, &remainder_not_zero, Label::kNear); |
| 1043 __ cmpl(dividend, Immediate(0)); | 1042 __ cmpl(dividend, Immediate(0)); |
| 1044 DeoptimizeIf(less, instr->environment()); | 1043 DeoptimizeIf(less, instr->environment()); |
| 1045 __ bind(&remainder_not_zero); | 1044 __ bind(&remainder_not_zero); |
| 1046 } | 1045 } |
| 1047 } | 1046 } |
| 1048 | 1047 |
| 1049 | 1048 |
| 1050 void LCodeGen::DoModI(LModI* instr) { | 1049 void LCodeGen::DoModI(LModI* instr) { |
| 1051 if (instr->hydrogen()->RightIsPowerOf2()) { | |
| 1052 return DoModByPowerOf2I(reinterpret_cast<LModByPowerOf2I*>(instr)); | |
| 1053 } | |
| 1054 HMod* hmod = instr->hydrogen(); | 1050 HMod* hmod = instr->hydrogen(); |
| 1055 HValue* left = hmod->left(); | |
| 1056 HValue* right = hmod->right(); | |
| 1057 | 1051 |
| 1058 Register left_reg = ToRegister(instr->left()); | 1052 Register left_reg = ToRegister(instr->left()); |
| 1059 ASSERT(left_reg.is(rax)); | 1053 ASSERT(left_reg.is(rax)); |
| 1060 Register right_reg = ToRegister(instr->right()); | 1054 Register right_reg = ToRegister(instr->right()); |
| 1061 ASSERT(!right_reg.is(rax)); | 1055 ASSERT(!right_reg.is(rax)); |
| 1062 ASSERT(!right_reg.is(rdx)); | 1056 ASSERT(!right_reg.is(rdx)); |
| 1063 Register result_reg = ToRegister(instr->result()); | 1057 Register result_reg = ToRegister(instr->result()); |
| 1064 ASSERT(result_reg.is(rdx)); | 1058 ASSERT(result_reg.is(rdx)); |
| 1065 | 1059 |
| 1066 Label done; | 1060 Label done; |
| 1067 // Check for x % 0, idiv would signal a divide error. We have to | 1061 // Check for x % 0, idiv would signal a divide error. We have to |
| 1068 // deopt in this case because we can't return a NaN. | 1062 // deopt in this case because we can't return a NaN. |
| 1069 if (right->CanBeZero()) { | 1063 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1070 __ testl(right_reg, right_reg); | 1064 __ testl(right_reg, right_reg); |
| 1071 DeoptimizeIf(zero, instr->environment()); | 1065 DeoptimizeIf(zero, instr->environment()); |
| 1072 } | 1066 } |
| 1073 | 1067 |
| 1074 // Check for kMinInt % -1, idiv would signal a divide error. We | 1068 // Check for kMinInt % -1, idiv would signal a divide error. We |
| 1075 // have to deopt if we care about -0, because we can't return that. | 1069 // have to deopt if we care about -0, because we can't return that. |
| 1076 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) { | 1070 if (hmod->CheckFlag(HValue::kCanOverflow)) { |
| 1077 Label no_overflow_possible; | 1071 Label no_overflow_possible; |
| 1078 __ cmpl(left_reg, Immediate(kMinInt)); | 1072 __ cmpl(left_reg, Immediate(kMinInt)); |
| 1079 __ j(not_zero, &no_overflow_possible, Label::kNear); | 1073 __ j(not_zero, &no_overflow_possible, Label::kNear); |
| 1080 __ cmpl(right_reg, Immediate(-1)); | 1074 __ cmpl(right_reg, Immediate(-1)); |
| 1081 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1075 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1082 DeoptimizeIf(equal, instr->environment()); | 1076 DeoptimizeIf(equal, instr->environment()); |
| 1083 } else { | 1077 } else { |
| 1084 __ j(not_equal, &no_overflow_possible, Label::kNear); | 1078 __ j(not_equal, &no_overflow_possible, Label::kNear); |
| 1085 __ Set(result_reg, 0); | 1079 __ Set(result_reg, 0); |
| 1086 __ jmp(&done, Label::kNear); | 1080 __ jmp(&done, Label::kNear); |
| 1087 } | 1081 } |
| 1088 __ bind(&no_overflow_possible); | 1082 __ bind(&no_overflow_possible); |
| 1089 } | 1083 } |
| 1090 | 1084 |
| 1091 // Sign extend dividend in eax into edx:eax, since we are using only the low | 1085 // Sign extend dividend in eax into edx:eax, since we are using only the low |
| 1092 // 32 bits of the values. | 1086 // 32 bits of the values. |
| 1093 __ cdq(); | 1087 __ cdq(); |
| 1094 | 1088 |
| 1095 // If we care about -0, test if the dividend is <0 and the result is 0. | 1089 // If we care about -0, test if the dividend is <0 and the result is 0. |
| 1096 if (left->CanBeNegative() && | 1090 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1097 hmod->CanBeZero() && | |
| 1098 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
| 1099 Label positive_left; | 1091 Label positive_left; |
| 1100 __ testl(left_reg, left_reg); | 1092 __ testl(left_reg, left_reg); |
| 1101 __ j(not_sign, &positive_left, Label::kNear); | 1093 __ j(not_sign, &positive_left, Label::kNear); |
| 1102 __ idivl(right_reg); | 1094 __ idivl(right_reg); |
| 1103 __ testl(result_reg, result_reg); | 1095 __ testl(result_reg, result_reg); |
| 1104 DeoptimizeIf(zero, instr->environment()); | 1096 DeoptimizeIf(zero, instr->environment()); |
| 1105 __ jmp(&done, Label::kNear); | 1097 __ jmp(&done, Label::kNear); |
| 1106 __ bind(&positive_left); | 1098 __ bind(&positive_left); |
| 1107 } | 1099 } |
| 1108 __ idivl(right_reg); | 1100 __ idivl(right_reg); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1152 int32_t divisor = instr->divisor(); | 1144 int32_t divisor = instr->divisor(); |
| 1153 ASSERT(ToRegister(instr->result()).is(rdx)); | 1145 ASSERT(ToRegister(instr->result()).is(rdx)); |
| 1154 | 1146 |
| 1155 if (divisor == 0) { | 1147 if (divisor == 0) { |
| 1156 DeoptimizeIf(no_condition, instr->environment()); | 1148 DeoptimizeIf(no_condition, instr->environment()); |
| 1157 return; | 1149 return; |
| 1158 } | 1150 } |
| 1159 | 1151 |
| 1160 // Check for (0 / -x) that will produce negative zero. | 1152 // Check for (0 / -x) that will produce negative zero. |
| 1161 HMathFloorOfDiv* hdiv = instr->hydrogen(); | 1153 HMathFloorOfDiv* hdiv = instr->hydrogen(); |
| 1162 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && | 1154 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1163 hdiv->left()->RangeCanInclude(0) && divisor < 0) { | |
| 1164 __ testl(dividend, dividend); | 1155 __ testl(dividend, dividend); |
| 1165 DeoptimizeIf(zero, instr->environment()); | 1156 DeoptimizeIf(zero, instr->environment()); |
| 1166 } | 1157 } |
| 1167 | 1158 |
| 1168 __ FlooringDiv(dividend, divisor); | 1159 __ FlooringDiv(dividend, divisor); |
| 1169 } | 1160 } |
| 1170 | 1161 |
| 1171 | 1162 |
| 1172 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 1163 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
| 1173 Register dividend = ToRegister(instr->dividend()); | 1164 Register dividend = ToRegister(instr->dividend()); |
| 1174 int32_t divisor = instr->divisor(); | 1165 int32_t divisor = instr->divisor(); |
| 1175 Register result = ToRegister(instr->result()); | 1166 Register result = ToRegister(instr->result()); |
| 1176 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor)))); | 1167 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor)))); |
| 1177 ASSERT(!result.is(dividend)); | 1168 ASSERT(!result.is(dividend)); |
| 1178 | 1169 |
| 1179 // Check for (0 / -x) that will produce negative zero. | 1170 // Check for (0 / -x) that will produce negative zero. |
| 1180 HDiv* hdiv = instr->hydrogen(); | 1171 HDiv* hdiv = instr->hydrogen(); |
| 1181 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && | 1172 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1182 hdiv->left()->RangeCanInclude(0) && divisor < 0) { | |
| 1183 __ testl(dividend, dividend); | 1173 __ testl(dividend, dividend); |
| 1184 DeoptimizeIf(zero, instr->environment()); | 1174 DeoptimizeIf(zero, instr->environment()); |
| 1185 } | 1175 } |
| 1186 // Check for (kMinInt / -1). | 1176 // Check for (kMinInt / -1). |
| 1187 if (hdiv->CheckFlag(HValue::kCanOverflow) && | 1177 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { |
| 1188 hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1) { | |
| 1189 __ cmpl(dividend, Immediate(kMinInt)); | 1178 __ cmpl(dividend, Immediate(kMinInt)); |
| 1190 DeoptimizeIf(zero, instr->environment()); | 1179 DeoptimizeIf(zero, instr->environment()); |
| 1191 } | 1180 } |
| 1192 // Deoptimize if remainder will not be 0. | 1181 // Deoptimize if remainder will not be 0. |
| 1193 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | 1182 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
| 1194 divisor != 1 && divisor != -1) { | 1183 divisor != 1 && divisor != -1) { |
| 1195 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1184 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
| 1196 __ testl(dividend, Immediate(mask)); | 1185 __ testl(dividend, Immediate(mask)); |
| 1197 DeoptimizeIf(not_zero, instr->environment()); | 1186 DeoptimizeIf(not_zero, instr->environment()); |
| 1198 } | 1187 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1214 int32_t divisor = instr->divisor(); | 1203 int32_t divisor = instr->divisor(); |
| 1215 ASSERT(ToRegister(instr->result()).is(rdx)); | 1204 ASSERT(ToRegister(instr->result()).is(rdx)); |
| 1216 | 1205 |
| 1217 if (divisor == 0) { | 1206 if (divisor == 0) { |
| 1218 DeoptimizeIf(no_condition, instr->environment()); | 1207 DeoptimizeIf(no_condition, instr->environment()); |
| 1219 return; | 1208 return; |
| 1220 } | 1209 } |
| 1221 | 1210 |
| 1222 // Check for (0 / -x) that will produce negative zero. | 1211 // Check for (0 / -x) that will produce negative zero. |
| 1223 HDiv* hdiv = instr->hydrogen(); | 1212 HDiv* hdiv = instr->hydrogen(); |
| 1224 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && | 1213 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1225 hdiv->left()->RangeCanInclude(0) && divisor < 0) { | |
| 1226 __ testl(dividend, dividend); | 1214 __ testl(dividend, dividend); |
| 1227 DeoptimizeIf(zero, instr->environment()); | 1215 DeoptimizeIf(zero, instr->environment()); |
| 1228 } | 1216 } |
| 1229 | 1217 |
| 1230 __ FlooringDiv(dividend, Abs(divisor)); | 1218 __ FlooringDiv(dividend, Abs(divisor)); |
| 1231 __ movl(rax, dividend); | 1219 __ movl(rax, dividend); |
| 1232 __ shrl(rax, Immediate(31)); | 1220 __ shrl(rax, Immediate(31)); |
| 1233 __ addl(rdx, rax); | 1221 __ addl(rdx, rax); |
| 1234 if (divisor < 0) __ neg(rdx); | 1222 if (divisor < 0) __ neg(rdx); |
| 1235 | 1223 |
| 1236 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1224 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
| 1237 __ movl(rax, rdx); | 1225 __ movl(rax, rdx); |
| 1238 __ imull(rax, rax, Immediate(divisor)); | 1226 __ imull(rax, rax, Immediate(divisor)); |
| 1239 __ subl(rax, dividend); | 1227 __ subl(rax, dividend); |
| 1240 DeoptimizeIf(not_equal, instr->environment()); | 1228 DeoptimizeIf(not_equal, instr->environment()); |
| 1241 } | 1229 } |
| 1242 } | 1230 } |
| 1243 | 1231 |
| 1244 | 1232 |
| 1245 void LCodeGen::DoDivI(LDivI* instr) { | 1233 void LCodeGen::DoDivI(LDivI* instr) { |
| 1234 HBinaryOperation* hdiv = instr->hydrogen(); |
| 1246 Register dividend = ToRegister(instr->left()); | 1235 Register dividend = ToRegister(instr->left()); |
| 1247 Register divisor = ToRegister(instr->right()); | 1236 Register divisor = ToRegister(instr->right()); |
| 1248 Register remainder = ToRegister(instr->temp()); | 1237 Register remainder = ToRegister(instr->temp()); |
| 1249 Register result = ToRegister(instr->result()); | 1238 Register result = ToRegister(instr->result()); |
| 1250 ASSERT(dividend.is(rax)); | 1239 ASSERT(dividend.is(rax)); |
| 1251 ASSERT(remainder.is(rdx)); | 1240 ASSERT(remainder.is(rdx)); |
| 1252 ASSERT(result.is(rax)); | 1241 ASSERT(result.is(rax)); |
| 1253 ASSERT(!divisor.is(rax)); | 1242 ASSERT(!divisor.is(rax)); |
| 1254 ASSERT(!divisor.is(rdx)); | 1243 ASSERT(!divisor.is(rdx)); |
| 1255 | 1244 |
| 1256 // Check for x / 0. | 1245 // Check for x / 0. |
| 1257 HBinaryOperation* hdiv = instr->hydrogen(); | |
| 1258 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1246 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1259 __ testl(divisor, divisor); | 1247 __ testl(divisor, divisor); |
| 1260 DeoptimizeIf(zero, instr->environment()); | 1248 DeoptimizeIf(zero, instr->environment()); |
| 1261 } | 1249 } |
| 1262 | 1250 |
| 1263 // Check for (0 / -x) that will produce negative zero. | 1251 // Check for (0 / -x) that will produce negative zero. |
| 1264 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1252 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1265 Label dividend_not_zero; | 1253 Label dividend_not_zero; |
| 1266 __ testl(dividend, dividend); | 1254 __ testl(dividend, dividend); |
| 1267 __ j(not_zero, ÷nd_not_zero, Label::kNear); | 1255 __ j(not_zero, ÷nd_not_zero, Label::kNear); |
| 1268 __ testl(divisor, divisor); | 1256 __ testl(divisor, divisor); |
| 1269 DeoptimizeIf(sign, instr->environment()); | 1257 DeoptimizeIf(sign, instr->environment()); |
| 1270 __ bind(÷nd_not_zero); | 1258 __ bind(÷nd_not_zero); |
| 1271 } | 1259 } |
| 1272 | 1260 |
| 1273 // Check for (kMinInt / -1). | 1261 // Check for (kMinInt / -1). |
| 1274 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 1262 if (hdiv->CheckFlag(HValue::kCanOverflow)) { |
| 1275 Label dividend_not_min_int; | 1263 Label dividend_not_min_int; |
| 1276 __ cmpl(dividend, Immediate(kMinInt)); | 1264 __ cmpl(dividend, Immediate(kMinInt)); |
| 1277 __ j(not_zero, ÷nd_not_min_int, Label::kNear); | 1265 __ j(not_zero, ÷nd_not_min_int, Label::kNear); |
| 1278 __ cmpl(divisor, Immediate(-1)); | 1266 __ cmpl(divisor, Immediate(-1)); |
| 1279 DeoptimizeIf(zero, instr->environment()); | 1267 DeoptimizeIf(zero, instr->environment()); |
| 1280 __ bind(÷nd_not_min_int); | 1268 __ bind(÷nd_not_min_int); |
| 1281 } | 1269 } |
| 1282 | 1270 |
| 1283 // Sign extend to rdx (= remainder). | 1271 // Sign extend to rdx (= remainder). |
| 1284 __ cdq(); | 1272 __ cdq(); |
| 1285 __ idivl(divisor); | 1273 __ idivl(divisor); |
| 1286 | 1274 |
| 1287 if (instr->is_flooring()) { | 1275 if (hdiv->IsMathFloorOfDiv()) { |
| 1288 Label done; | 1276 Label done; |
| 1289 __ testl(remainder, remainder); | 1277 __ testl(remainder, remainder); |
| 1290 __ j(zero, &done, Label::kNear); | 1278 __ j(zero, &done, Label::kNear); |
| 1291 __ xorl(remainder, divisor); | 1279 __ xorl(remainder, divisor); |
| 1292 __ sarl(remainder, Immediate(31)); | 1280 __ sarl(remainder, Immediate(31)); |
| 1293 __ addl(result, remainder); | 1281 __ addl(result, remainder); |
| 1294 __ bind(&done); | 1282 __ bind(&done); |
| 1295 } else if (!instr->hydrogen()->CheckFlag( | 1283 } else if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1296 HInstruction::kAllUsesTruncatingToInt32)) { | |
| 1297 // Deoptimize if remainder is not 0. | 1284 // Deoptimize if remainder is not 0. |
| 1298 __ testl(remainder, remainder); | 1285 __ testl(remainder, remainder); |
| 1299 DeoptimizeIf(not_zero, instr->environment()); | 1286 DeoptimizeIf(not_zero, instr->environment()); |
| 1300 } | 1287 } |
| 1301 } | 1288 } |
| 1302 | 1289 |
| 1303 | 1290 |
| 1304 void LCodeGen::DoMulI(LMulI* instr) { | 1291 void LCodeGen::DoMulI(LMulI* instr) { |
| 1305 Register left = ToRegister(instr->left()); | 1292 Register left = ToRegister(instr->left()); |
| 1306 LOperand* right = instr->right(); | 1293 LOperand* right = instr->right(); |
| (...skipping 4359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5666 FixedArray::kHeaderSize - kPointerSize)); | 5653 FixedArray::kHeaderSize - kPointerSize)); |
| 5667 __ bind(&done); | 5654 __ bind(&done); |
| 5668 } | 5655 } |
| 5669 | 5656 |
| 5670 | 5657 |
| 5671 #undef __ | 5658 #undef __ |
| 5672 | 5659 |
| 5673 } } // namespace v8::internal | 5660 } } // namespace v8::internal |
| 5674 | 5661 |
| 5675 #endif // V8_TARGET_ARCH_X64 | 5662 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |