OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1214 } | 1214 } |
1215 } | 1215 } |
1216 | 1216 |
1217 | 1217 |
1218 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 1218 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
1219 // Nothing to do. | 1219 // Nothing to do. |
1220 } | 1220 } |
1221 | 1221 |
1222 | 1222 |
1223 void LCodeGen::DoModI(LModI* instr) { | 1223 void LCodeGen::DoModI(LModI* instr) { |
1224 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 1224 HMod* hmod = instr->hydrogen(); |
1225 Register dividend = ToRegister(instr->left()); | 1225 HValue* left = hmod->left(); |
| 1226 HValue* right = hmod->right(); |
| 1227 if (hmod->HasPowerOf2Divisor()) { |
| 1228 // TODO(svenpanne) We should really do the strength reduction on the |
| 1229 // Hydrogen level. |
| 1230 Register left_reg = ToRegister(instr->left()); |
| 1231 ASSERT(left_reg.is(ToRegister(instr->result()))); |
1226 | 1232 |
1227 int32_t divisor = | 1233 // Note: The code below even works when right contains kMinInt. |
1228 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 1234 int32_t divisor = Abs(right->GetInteger32Constant()); |
1229 | 1235 |
1230 if (divisor < 0) divisor = -divisor; | 1236 Label left_is_not_negative, done; |
1231 | 1237 if (left->CanBeNegative()) { |
1232 Label positive_dividend, done; | 1238 __ test(left_reg, Operand(left_reg)); |
1233 __ test(dividend, Operand(dividend)); | 1239 __ j(not_sign, &left_is_not_negative, Label::kNear); |
1234 __ j(not_sign, &positive_dividend, Label::kNear); | 1240 __ neg(left_reg); |
1235 __ neg(dividend); | 1241 __ and_(left_reg, divisor - 1); |
1236 __ and_(dividend, divisor - 1); | 1242 __ neg(left_reg); |
1237 __ neg(dividend); | 1243 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1238 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1244 DeoptimizeIf(zero, instr->environment()); |
1239 __ j(not_zero, &done, Label::kNear); | 1245 } |
1240 DeoptimizeIf(no_condition, instr->environment()); | |
1241 } else { | |
1242 __ jmp(&done, Label::kNear); | 1246 __ jmp(&done, Label::kNear); |
1243 } | 1247 } |
1244 __ bind(&positive_dividend); | 1248 |
1245 __ and_(dividend, divisor - 1); | 1249 __ bind(&left_is_not_negative); |
| 1250 __ and_(left_reg, divisor - 1); |
1246 __ bind(&done); | 1251 __ bind(&done); |
| 1252 |
| 1253 } else if (hmod->has_fixed_right_arg()) { |
| 1254 Register left_reg = ToRegister(instr->left()); |
| 1255 ASSERT(left_reg.is(ToRegister(instr->result()))); |
| 1256 Register right_reg = ToRegister(instr->right()); |
| 1257 |
| 1258 int32_t divisor = hmod->fixed_right_arg_value(); |
| 1259 ASSERT(IsPowerOf2(divisor)); |
| 1260 |
| 1261 // Check if our assumption of a fixed right operand still holds. |
| 1262 __ cmp(right_reg, Immediate(divisor)); |
| 1263 DeoptimizeIf(not_equal, instr->environment()); |
| 1264 |
| 1265 Label left_is_not_negative, done; |
| 1266 if (left->CanBeNegative()) { |
| 1267 __ test(left_reg, Operand(left_reg)); |
| 1268 __ j(not_sign, &left_is_not_negative, Label::kNear); |
| 1269 __ neg(left_reg); |
| 1270 __ and_(left_reg, divisor - 1); |
| 1271 __ neg(left_reg); |
| 1272 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1273 DeoptimizeIf(zero, instr->environment()); |
| 1274 } |
| 1275 __ jmp(&done, Label::kNear); |
| 1276 } |
| 1277 |
| 1278 __ bind(&left_is_not_negative); |
| 1279 __ and_(left_reg, divisor - 1); |
| 1280 __ bind(&done); |
| 1281 |
1247 } else { | 1282 } else { |
1248 Label done, remainder_eq_dividend, slow, both_positive; | |
1249 Register left_reg = ToRegister(instr->left()); | 1283 Register left_reg = ToRegister(instr->left()); |
| 1284 ASSERT(left_reg.is(eax)); |
1250 Register right_reg = ToRegister(instr->right()); | 1285 Register right_reg = ToRegister(instr->right()); |
1251 Register result_reg = ToRegister(instr->result()); | |
1252 | |
1253 ASSERT(left_reg.is(eax)); | |
1254 ASSERT(result_reg.is(edx)); | |
1255 ASSERT(!right_reg.is(eax)); | 1286 ASSERT(!right_reg.is(eax)); |
1256 ASSERT(!right_reg.is(edx)); | 1287 ASSERT(!right_reg.is(edx)); |
| 1288 Register result_reg = ToRegister(instr->result()); |
| 1289 ASSERT(result_reg.is(edx)); |
1257 | 1290 |
1258 // Check for x % 0. | 1291 Label done; |
1259 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1292 // Check for x % 0, idiv would signal a divide error. We have to |
| 1293 // deopt in this case because we can't return a NaN. |
| 1294 if (right->CanBeZero()) { |
1260 __ test(right_reg, Operand(right_reg)); | 1295 __ test(right_reg, Operand(right_reg)); |
1261 DeoptimizeIf(zero, instr->environment()); | 1296 DeoptimizeIf(zero, instr->environment()); |
1262 } | 1297 } |
1263 | 1298 |
1264 __ test(left_reg, Operand(left_reg)); | 1299 // Check for kMinInt % -1, idiv would signal a divide error. We |
1265 __ j(zero, &remainder_eq_dividend, Label::kNear); | 1300 // have to deopt if we care about -0, because we can't return that. |
1266 __ j(sign, &slow, Label::kNear); | 1301 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) { |
1267 | 1302 Label no_overflow_possible; |
1268 __ test(right_reg, Operand(right_reg)); | |
1269 __ j(not_sign, &both_positive, Label::kNear); | |
1270 // The sign of the divisor doesn't matter. | |
1271 __ neg(right_reg); | |
1272 | |
1273 __ bind(&both_positive); | |
1274 // If the dividend is smaller than the nonnegative | |
1275 // divisor, the dividend is the result. | |
1276 __ cmp(left_reg, Operand(right_reg)); | |
1277 __ j(less, &remainder_eq_dividend, Label::kNear); | |
1278 | |
1279 // Check if the divisor is a PowerOfTwo integer. | |
1280 Register scratch = ToRegister(instr->temp()); | |
1281 __ mov(scratch, right_reg); | |
1282 __ sub(Operand(scratch), Immediate(1)); | |
1283 __ test(scratch, Operand(right_reg)); | |
1284 __ j(not_zero, &slow, Label::kNear); | |
1285 __ and_(left_reg, Operand(scratch)); | |
1286 __ jmp(&remainder_eq_dividend, Label::kNear); | |
1287 | |
1288 // Slow case, using idiv instruction. | |
1289 __ bind(&slow); | |
1290 | |
1291 // Check for (kMinInt % -1). | |
1292 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | |
1293 Label left_not_min_int; | |
1294 __ cmp(left_reg, kMinInt); | 1303 __ cmp(left_reg, kMinInt); |
1295 __ j(not_zero, &left_not_min_int, Label::kNear); | 1304 __ j(not_equal, &no_overflow_possible, Label::kNear); |
1296 __ cmp(right_reg, -1); | 1305 __ cmp(right_reg, -1); |
1297 DeoptimizeIf(zero, instr->environment()); | 1306 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1298 __ bind(&left_not_min_int); | 1307 DeoptimizeIf(equal, instr->environment()); |
| 1308 } else { |
| 1309 __ j(not_equal, &no_overflow_possible, Label::kNear); |
| 1310 __ Set(result_reg, Immediate(0)); |
| 1311 __ jmp(&done, Label::kNear); |
| 1312 } |
| 1313 __ bind(&no_overflow_possible); |
1299 } | 1314 } |
1300 | 1315 |
1301 // Sign extend to edx. | 1316 // Sign extend dividend in eax into edx:eax. |
1302 __ cdq(); | 1317 __ cdq(); |
1303 | 1318 |
1304 // Check for (0 % -x) that will produce negative zero. | 1319 // If we care about -0, test if the dividend is <0 and the result is 0. |
1305 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1320 if (left->CanBeNegative() && |
| 1321 hmod->CanBeZero() && |
| 1322 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1306 Label positive_left; | 1323 Label positive_left; |
1307 Label done; | |
1308 __ test(left_reg, Operand(left_reg)); | 1324 __ test(left_reg, Operand(left_reg)); |
1309 __ j(not_sign, &positive_left, Label::kNear); | 1325 __ j(not_sign, &positive_left, Label::kNear); |
1310 __ idiv(right_reg); | 1326 __ idiv(right_reg); |
1311 | |
1312 // Test the remainder for 0, because then the result would be -0. | |
1313 __ test(result_reg, Operand(result_reg)); | 1327 __ test(result_reg, Operand(result_reg)); |
1314 __ j(not_zero, &done, Label::kNear); | 1328 DeoptimizeIf(zero, instr->environment()); |
1315 | 1329 __ jmp(&done, Label::kNear); |
1316 DeoptimizeIf(no_condition, instr->environment()); | |
1317 __ bind(&positive_left); | 1330 __ bind(&positive_left); |
1318 __ idiv(right_reg); | |
1319 __ bind(&done); | |
1320 } else { | |
1321 __ idiv(right_reg); | |
1322 } | 1331 } |
1323 __ jmp(&done, Label::kNear); | 1332 __ idiv(right_reg); |
1324 | |
1325 __ bind(&remainder_eq_dividend); | |
1326 __ mov(result_reg, left_reg); | |
1327 | |
1328 __ bind(&done); | 1333 __ bind(&done); |
1329 } | 1334 } |
1330 } | 1335 } |
1331 | 1336 |
1332 | 1337 |
1333 void LCodeGen::DoDivI(LDivI* instr) { | 1338 void LCodeGen::DoDivI(LDivI* instr) { |
1334 if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) { | 1339 if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) { |
1335 Register dividend = ToRegister(instr->left()); | 1340 Register dividend = ToRegister(instr->left()); |
1336 int32_t divisor = | 1341 int32_t divisor = |
1337 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 1342 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
(...skipping 5156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6494 FixedArray::kHeaderSize - kPointerSize)); | 6499 FixedArray::kHeaderSize - kPointerSize)); |
6495 __ bind(&done); | 6500 __ bind(&done); |
6496 } | 6501 } |
6497 | 6502 |
6498 | 6503 |
6499 #undef __ | 6504 #undef __ |
6500 | 6505 |
6501 } } // namespace v8::internal | 6506 } } // namespace v8::internal |
6502 | 6507 |
6503 #endif // V8_TARGET_ARCH_IA32 | 6508 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |