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 // 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 1216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1227 } | 1227 } |
| 1228 } | 1228 } |
| 1229 | 1229 |
| 1230 | 1230 |
| 1231 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 1231 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 1232 // Nothing to do. | 1232 // Nothing to do. |
| 1233 } | 1233 } |
| 1234 | 1234 |
| 1235 | 1235 |
| 1236 void LCodeGen::DoModI(LModI* instr) { | 1236 void LCodeGen::DoModI(LModI* instr) { |
| 1237 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 1237 HMod* hmod = instr->hydrogen(); |
| 1238 Register dividend = ToRegister(instr->left()); | 1238 HValue* left = hmod->left(); |
| 1239 HValue* right = hmod->right(); | |
| 1240 if (hmod->HasPowerOf2Divisor()) { | |
| 1241 // TODO(svenpanne) We should really do the strength reduction on the | |
|
Jakob Kummerow
2013/06/07 16:50:07
I'm not sure this comment adds value either.
Sven Panne
2013/06/10 11:05:39
Actually it does: This part of DoModI is basically
| |
| 1242 // Hydrogen level. | |
| 1243 Register left_reg = ToRegister(instr->left()); | |
| 1244 ASSERT(left_reg.is(ToRegister(instr->result()))); | |
| 1239 | 1245 |
| 1240 int32_t divisor = | 1246 int32_t divisor = Abs(right->GetInteger32Constant()); |
|
Jakob Kummerow
2013/06/07 16:50:07
This just works by accident for right->GetInteger3
Sven Panne
2013/06/10 11:05:39
Yep, this clever handling has been there before, b
| |
| 1241 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | |
| 1242 | 1247 |
| 1243 if (divisor < 0) divisor = -divisor; | 1248 Label left_is_not_negative, done; |
| 1244 | 1249 if (left->CanBeNegative()) { |
| 1245 Label positive_dividend, done; | 1250 __ test(left_reg, Operand(left_reg)); |
| 1246 __ test(dividend, Operand(dividend)); | 1251 __ j(not_sign, &left_is_not_negative, Label::kNear); |
| 1247 __ j(not_sign, &positive_dividend, Label::kNear); | 1252 __ neg(left_reg); |
| 1248 __ neg(dividend); | 1253 __ and_(left_reg, divisor - 1); |
| 1249 __ and_(dividend, divisor - 1); | 1254 __ neg(left_reg); |
| 1250 __ neg(dividend); | 1255 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1251 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1256 DeoptimizeIf(zero, instr->environment()); |
| 1252 __ j(not_zero, &done, Label::kNear); | 1257 } |
| 1253 DeoptimizeIf(no_condition, instr->environment()); | |
| 1254 } else { | |
| 1255 __ jmp(&done, Label::kNear); | 1258 __ jmp(&done, Label::kNear); |
| 1256 } | 1259 } |
| 1257 __ bind(&positive_dividend); | 1260 |
| 1258 __ and_(dividend, divisor - 1); | 1261 __ bind(&left_is_not_negative); |
| 1262 __ and_(left_reg, divisor - 1); | |
| 1259 __ bind(&done); | 1263 __ bind(&done); |
| 1264 | |
| 1265 } else if (hmod->has_fixed_right_arg()) { | |
| 1266 Register left_reg = ToRegister(instr->left()); | |
| 1267 ASSERT(left_reg.is(ToRegister(instr->result()))); | |
| 1268 Register right_reg = ToRegister(instr->right()); | |
| 1269 | |
| 1270 int32_t divisor = hmod->fixed_right_arg_value(); | |
| 1271 ASSERT(IsPowerOf2(divisor)); | |
| 1272 | |
| 1273 // Check if our assumption of a fixed right operand still holds. | |
| 1274 __ cmp(right_reg, Immediate(divisor)); | |
| 1275 DeoptimizeIf(not_equal, instr->environment()); | |
| 1276 | |
| 1277 Label left_is_not_negative, done; | |
| 1278 if (left->CanBeNegative()) { | |
| 1279 __ test(left_reg, Operand(left_reg)); | |
| 1280 __ j(not_sign, &left_is_not_negative, Label::kNear); | |
| 1281 __ neg(left_reg); | |
| 1282 __ and_(left_reg, divisor - 1); | |
| 1283 __ neg(left_reg); | |
| 1284 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
| 1285 DeoptimizeIf(zero, instr->environment()); | |
| 1286 } | |
| 1287 __ jmp(&done, Label::kNear); | |
| 1288 } | |
| 1289 | |
| 1290 __ bind(&left_is_not_negative); | |
| 1291 __ and_(left_reg, divisor - 1); | |
| 1292 __ bind(&done); | |
| 1293 | |
| 1260 } else { | 1294 } else { |
| 1261 Label done, remainder_eq_dividend, slow, both_positive; | |
| 1262 Register left_reg = ToRegister(instr->left()); | 1295 Register left_reg = ToRegister(instr->left()); |
| 1296 ASSERT(left_reg.is(eax)); | |
| 1263 Register right_reg = ToRegister(instr->right()); | 1297 Register right_reg = ToRegister(instr->right()); |
| 1264 Register result_reg = ToRegister(instr->result()); | |
| 1265 | |
| 1266 ASSERT(left_reg.is(eax)); | |
| 1267 ASSERT(result_reg.is(edx)); | |
| 1268 ASSERT(!right_reg.is(eax)); | 1298 ASSERT(!right_reg.is(eax)); |
| 1269 ASSERT(!right_reg.is(edx)); | 1299 ASSERT(!right_reg.is(edx)); |
| 1300 Register result_reg = ToRegister(instr->result()); | |
| 1301 ASSERT(result_reg.is(edx)); | |
| 1270 | 1302 |
| 1271 // Check for x % 0. | 1303 Label done; |
| 1272 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1304 // Check for x % 0, idiv would signal a divide error. We have to |
| 1305 // deopt in this case because we can't return a NaN. | |
| 1306 if (right->CanBeZero()) { | |
| 1273 __ test(right_reg, Operand(right_reg)); | 1307 __ test(right_reg, Operand(right_reg)); |
| 1274 DeoptimizeIf(zero, instr->environment()); | 1308 DeoptimizeIf(zero, instr->environment()); |
| 1275 } | 1309 } |
| 1276 | 1310 |
| 1277 __ test(left_reg, Operand(left_reg)); | 1311 // Check for kMinInt % -1, idiv would signal a divide error. We |
| 1278 __ j(zero, &remainder_eq_dividend, Label::kNear); | 1312 // have to deopt if we care about -0, because we can't return that. |
| 1279 __ j(sign, &slow, Label::kNear); | 1313 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) { |
| 1280 | 1314 Label no_overflow_possible; |
| 1281 __ test(right_reg, Operand(right_reg)); | |
| 1282 __ j(not_sign, &both_positive, Label::kNear); | |
| 1283 // The sign of the divisor doesn't matter. | |
| 1284 __ neg(right_reg); | |
| 1285 | |
| 1286 __ bind(&both_positive); | |
| 1287 // If the dividend is smaller than the nonnegative | |
| 1288 // divisor, the dividend is the result. | |
| 1289 __ cmp(left_reg, Operand(right_reg)); | |
| 1290 __ j(less, &remainder_eq_dividend, Label::kNear); | |
| 1291 | |
| 1292 // Check if the divisor is a PowerOfTwo integer. | |
| 1293 Register scratch = ToRegister(instr->temp()); | |
| 1294 __ mov(scratch, right_reg); | |
| 1295 __ sub(Operand(scratch), Immediate(1)); | |
| 1296 __ test(scratch, Operand(right_reg)); | |
| 1297 __ j(not_zero, &slow, Label::kNear); | |
| 1298 __ and_(left_reg, Operand(scratch)); | |
| 1299 __ jmp(&remainder_eq_dividend, Label::kNear); | |
| 1300 | |
| 1301 // Slow case, using idiv instruction. | |
| 1302 __ bind(&slow); | |
| 1303 | |
| 1304 // Check for (kMinInt % -1). | |
| 1305 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | |
| 1306 Label left_not_min_int; | |
| 1307 __ cmp(left_reg, kMinInt); | 1315 __ cmp(left_reg, kMinInt); |
| 1308 __ j(not_zero, &left_not_min_int, Label::kNear); | 1316 __ j(not_equal, &no_overflow_possible, Label::kNear); |
| 1309 __ cmp(right_reg, -1); | 1317 __ cmp(right_reg, -1); |
| 1310 DeoptimizeIf(zero, instr->environment()); | 1318 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1311 __ bind(&left_not_min_int); | 1319 DeoptimizeIf(equal, instr->environment()); |
| 1320 } else { | |
| 1321 __ j(not_equal, &no_overflow_possible, Label::kNear); | |
| 1322 __ Set(result_reg, Immediate(0)); | |
| 1323 __ jmp(&done, Label::kNear); | |
| 1324 } | |
| 1325 __ bind(&no_overflow_possible); | |
| 1312 } | 1326 } |
| 1313 | 1327 |
| 1314 // Sign extend to edx. | 1328 // Sign extend dividend in eax into edx:eax. |
| 1315 __ cdq(); | 1329 __ cdq(); |
| 1316 | 1330 |
| 1317 // Check for (0 % -x) that will produce negative zero. | 1331 // If we care about -0, test if the dividend is <0 and the result is 0. |
| 1318 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1332 if (left->CanBeNegative() && |
| 1333 hmod->CanBeZero() && | |
| 1334 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
| 1319 Label positive_left; | 1335 Label positive_left; |
| 1320 Label done; | |
| 1321 __ test(left_reg, Operand(left_reg)); | 1336 __ test(left_reg, Operand(left_reg)); |
| 1322 __ j(not_sign, &positive_left, Label::kNear); | 1337 __ j(not_sign, &positive_left, Label::kNear); |
| 1323 __ idiv(right_reg); | 1338 __ idiv(right_reg); |
| 1324 | |
| 1325 // Test the remainder for 0, because then the result would be -0. | |
| 1326 __ test(result_reg, Operand(result_reg)); | 1339 __ test(result_reg, Operand(result_reg)); |
| 1327 __ j(not_zero, &done, Label::kNear); | 1340 DeoptimizeIf(zero, instr->environment()); |
| 1328 | 1341 __ jmp(&done, Label::kNear); |
| 1329 DeoptimizeIf(no_condition, instr->environment()); | |
| 1330 __ bind(&positive_left); | 1342 __ bind(&positive_left); |
| 1331 __ idiv(right_reg); | |
| 1332 __ bind(&done); | |
| 1333 } else { | |
| 1334 __ idiv(right_reg); | |
| 1335 } | 1343 } |
| 1336 __ jmp(&done, Label::kNear); | 1344 __ idiv(right_reg); |
| 1337 | |
| 1338 __ bind(&remainder_eq_dividend); | |
| 1339 __ mov(result_reg, left_reg); | |
| 1340 | |
| 1341 __ bind(&done); | 1345 __ bind(&done); |
| 1342 } | 1346 } |
| 1343 } | 1347 } |
| 1344 | 1348 |
| 1345 | 1349 |
| 1346 void LCodeGen::DoDivI(LDivI* instr) { | 1350 void LCodeGen::DoDivI(LDivI* instr) { |
| 1347 if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) { | 1351 if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) { |
| 1348 Register dividend = ToRegister(instr->left()); | 1352 Register dividend = ToRegister(instr->left()); |
| 1349 int32_t divisor = | 1353 int32_t divisor = |
| 1350 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 1354 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
| (...skipping 5163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6514 FixedArray::kHeaderSize - kPointerSize)); | 6518 FixedArray::kHeaderSize - kPointerSize)); |
| 6515 __ bind(&done); | 6519 __ bind(&done); |
| 6516 } | 6520 } |
| 6517 | 6521 |
| 6518 | 6522 |
| 6519 #undef __ | 6523 #undef __ |
| 6520 | 6524 |
| 6521 } } // namespace v8::internal | 6525 } } // namespace v8::internal |
| 6522 | 6526 |
| 6523 #endif // V8_TARGET_ARCH_IA32 | 6527 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |