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 | |
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 = HConstant::cast(right)->Integer32Value(); |
Jakob Kummerow
2013/06/05 17:08:41
even shorter: right->GetInteger32Constant()
Sven Panne
2013/06/06 06:50:23
Done. Lame excuse: It has been there before. ;-) F
| |
1241 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | |
1242 | |
1243 if (divisor < 0) divisor = -divisor; | 1247 if (divisor < 0) divisor = -divisor; |
1244 | 1248 |
1245 Label positive_dividend, done; | 1249 Label left_is_not_negative, done; |
1246 __ test(dividend, Operand(dividend)); | 1250 if (left->CanBeNegative()) { |
1247 __ j(not_sign, &positive_dividend, Label::kNear); | 1251 __ test(left_reg, Operand(left_reg)); |
1248 __ neg(dividend); | 1252 __ j(not_sign, &left_is_not_negative, Label::kNear); |
1249 __ and_(dividend, divisor - 1); | 1253 __ neg(left_reg); |
1250 __ neg(dividend); | 1254 __ and_(left_reg, divisor - 1); |
1251 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1255 __ neg(left_reg); |
1252 __ j(not_zero, &done, Label::kNear); | 1256 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1253 DeoptimizeIf(no_condition, instr->environment()); | 1257 DeoptimizeIf(zero, instr->environment()); |
1254 } else { | 1258 } |
1255 __ jmp(&done, Label::kNear); | 1259 __ jmp(&done, Label::kNear); |
1256 } | 1260 } |
1257 __ bind(&positive_dividend); | 1261 |
1258 __ and_(dividend, divisor - 1); | 1262 __ bind(&left_is_not_negative); |
1263 __ and_(left_reg, divisor - 1); | |
1259 __ bind(&done); | 1264 __ bind(&done); |
1265 | |
1266 } else if (hmod->has_fixed_right_arg()) { | |
1267 Register left_reg = ToRegister(instr->left()); | |
1268 ASSERT(left_reg.is(ToRegister(instr->result()))); | |
1269 Register right_reg = ToRegister(instr->right()); | |
1270 | |
1271 int32_t divisor = hmod->fixed_right_arg_value(); | |
1272 ASSERT(IsPowerOf2(divisor)); | |
1273 | |
1274 // Check if our assumption of a fixed right operand still holds. | |
1275 __ cmp(right_reg, Immediate(divisor)); | |
1276 DeoptimizeIf(not_equal, instr->environment()); | |
1277 | |
1278 Label left_is_not_negative, done; | |
1279 if (left->CanBeNegative()) { | |
1280 __ test(left_reg, Operand(left_reg)); | |
1281 __ j(not_sign, &left_is_not_negative, Label::kNear); | |
1282 __ neg(left_reg); | |
1283 __ and_(left_reg, divisor - 1); | |
1284 __ neg(left_reg); | |
1285 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
1286 DeoptimizeIf(zero, instr->environment()); | |
1287 } | |
1288 __ jmp(&done, Label::kNear); | |
1289 } | |
1290 | |
1291 __ bind(&left_is_not_negative); | |
1292 __ and_(left_reg, divisor - 1); | |
1293 __ bind(&done); | |
1294 | |
1260 } else { | 1295 } else { |
1261 Label done, remainder_eq_dividend, slow, both_positive; | |
1262 Register left_reg = ToRegister(instr->left()); | 1296 Register left_reg = ToRegister(instr->left()); |
1297 ASSERT(left_reg.is(eax)); | |
1263 Register right_reg = ToRegister(instr->right()); | 1298 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)); | 1299 ASSERT(!right_reg.is(eax)); |
1269 ASSERT(!right_reg.is(edx)); | 1300 ASSERT(!right_reg.is(edx)); |
1301 Register result_reg = ToRegister(instr->result()); | |
1302 ASSERT(result_reg.is(edx)); | |
1270 | 1303 |
1271 // Check for x % 0. | 1304 Label done; |
1272 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1305 // Check for x % 0, idiv would signal a divide error. We have to |
1306 // deopt in this case because we can't return a NaN. | |
1307 if (right->CanBeZero()) { | |
1273 __ test(right_reg, Operand(right_reg)); | 1308 __ test(right_reg, Operand(right_reg)); |
1274 DeoptimizeIf(zero, instr->environment()); | 1309 DeoptimizeIf(zero, instr->environment()); |
1275 } | 1310 } |
1276 | 1311 |
1277 __ test(left_reg, Operand(left_reg)); | 1312 // Check for kMinInt % -1, idiv would signal a divide error. We |
1278 __ j(zero, &remainder_eq_dividend, Label::kNear); | 1313 // have to deopt if we care about -0, because we can't return that. |
1279 __ j(sign, &slow, Label::kNear); | 1314 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) { |
1280 | 1315 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); | 1316 __ cmp(left_reg, kMinInt); |
1308 __ j(not_zero, &left_not_min_int, Label::kNear); | 1317 __ j(not_equal, &no_overflow_possible, Label::kNear); |
1309 __ cmp(right_reg, -1); | 1318 __ cmp(right_reg, -1); |
1310 DeoptimizeIf(zero, instr->environment()); | 1319 __ j(not_equal, &no_overflow_possible, Label::kNear); |
1311 __ bind(&left_not_min_int); | 1320 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1321 __ test(left_reg, Operand(left_reg)); | |
Jakob Kummerow
2013/06/05 17:08:41
Why this test? You already know that left_reg == k
Sven Panne
2013/06/06 06:50:23
Ooops, this is a remnant of several iterations of
| |
1322 DeoptimizeIf(sign, instr->environment()); | |
1323 } | |
1324 __ Set(result_reg, Immediate(0)); | |
1325 __ jmp(&done); | |
1326 __ bind(&no_overflow_possible); | |
1312 } | 1327 } |
1313 | 1328 |
1314 // Sign extend to edx. | 1329 // Sign extend dividend in eax into edx:eax. |
1315 __ cdq(); | 1330 __ cdq(); |
1316 | 1331 |
1317 // Check for (0 % -x) that will produce negative zero. | 1332 // If we care about -0, test if the dividend is <0 and the result is 0. |
1318 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1333 if (left->CanBeNegative() && |
1334 hmod->CanBeZero() && | |
1335 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
1319 Label positive_left; | 1336 Label positive_left; |
1320 Label done; | |
1321 __ test(left_reg, Operand(left_reg)); | 1337 __ test(left_reg, Operand(left_reg)); |
1322 __ j(not_sign, &positive_left, Label::kNear); | 1338 __ j(not_sign, &positive_left, Label::kNear); |
1339 | |
1323 __ idiv(right_reg); | 1340 __ idiv(right_reg); |
1341 __ test(result_reg, Operand(result_reg)); | |
1342 DeoptimizeIf(zero, instr->environment()); | |
1343 __ jmp(&done, Label::kNear); | |
1324 | 1344 |
1325 // Test the remainder for 0, because then the result would be -0. | |
1326 __ test(result_reg, Operand(result_reg)); | |
1327 __ j(not_zero, &done, Label::kNear); | |
1328 | |
1329 DeoptimizeIf(no_condition, instr->environment()); | |
1330 __ bind(&positive_left); | 1345 __ bind(&positive_left); |
1331 __ idiv(right_reg); | 1346 __ idiv(right_reg); |
1332 __ bind(&done); | |
1333 } else { | 1347 } else { |
1334 __ idiv(right_reg); | 1348 __ idiv(right_reg); |
1335 } | 1349 } |
1336 __ jmp(&done, Label::kNear); | |
1337 | |
1338 __ bind(&remainder_eq_dividend); | |
1339 __ mov(result_reg, left_reg); | |
1340 | |
1341 __ bind(&done); | 1350 __ bind(&done); |
1342 } | 1351 } |
1343 } | 1352 } |
1344 | 1353 |
1345 | 1354 |
1346 void LCodeGen::DoDivI(LDivI* instr) { | 1355 void LCodeGen::DoDivI(LDivI* instr) { |
1347 if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) { | 1356 if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) { |
1348 Register dividend = ToRegister(instr->left()); | 1357 Register dividend = ToRegister(instr->left()); |
1349 int32_t divisor = | 1358 int32_t divisor = |
1350 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 1359 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
(...skipping 5163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6514 FixedArray::kHeaderSize - kPointerSize)); | 6523 FixedArray::kHeaderSize - kPointerSize)); |
6515 __ bind(&done); | 6524 __ bind(&done); |
6516 } | 6525 } |
6517 | 6526 |
6518 | 6527 |
6519 #undef __ | 6528 #undef __ |
6520 | 6529 |
6521 } } // namespace v8::internal | 6530 } } // namespace v8::internal |
6522 | 6531 |
6523 #endif // V8_TARGET_ARCH_IA32 | 6532 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |