| 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1000 int deoptimization_index = deoptimizations_.length(); | 1000 int deoptimization_index = deoptimizations_.length(); |
| 1001 int pc_offset = masm()->pc_offset(); | 1001 int pc_offset = masm()->pc_offset(); |
| 1002 environment->Register(deoptimization_index, | 1002 environment->Register(deoptimization_index, |
| 1003 translation.index(), | 1003 translation.index(), |
| 1004 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 1004 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
| 1005 deoptimizations_.Add(environment, zone()); | 1005 deoptimizations_.Add(environment, zone()); |
| 1006 } | 1006 } |
| 1007 } | 1007 } |
| 1008 | 1008 |
| 1009 | 1009 |
| 1010 void LCodeGen::DeoptimizeIf(Condition cc, | 1010 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr, |
| 1011 LEnvironment* environment, | |
| 1012 Deoptimizer::BailoutType bailout_type) { | 1011 Deoptimizer::BailoutType bailout_type) { |
| 1012 LEnvironment* environment = instr->environment(); |
| 1013 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 1013 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 1014 DCHECK(environment->HasBeenRegistered()); | 1014 DCHECK(environment->HasBeenRegistered()); |
| 1015 int id = environment->deoptimization_index(); | 1015 int id = environment->deoptimization_index(); |
| 1016 DCHECK(info()->IsOptimizing() || info()->IsStub()); | 1016 DCHECK(info()->IsOptimizing() || info()->IsStub()); |
| 1017 Address entry = | 1017 Address entry = |
| 1018 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 1018 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
| 1019 if (entry == NULL) { | 1019 if (entry == NULL) { |
| 1020 Abort(kBailoutWasNotPrepared); | 1020 Abort(kBailoutWasNotPrepared); |
| 1021 return; | 1021 return; |
| 1022 } | 1022 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1077 } | 1077 } |
| 1078 if (cc == no_condition) { | 1078 if (cc == no_condition) { |
| 1079 __ jmp(&jump_table_.last().label); | 1079 __ jmp(&jump_table_.last().label); |
| 1080 } else { | 1080 } else { |
| 1081 __ j(cc, &jump_table_.last().label); | 1081 __ j(cc, &jump_table_.last().label); |
| 1082 } | 1082 } |
| 1083 } | 1083 } |
| 1084 } | 1084 } |
| 1085 | 1085 |
| 1086 | 1086 |
| 1087 void LCodeGen::DeoptimizeIf(Condition cc, | 1087 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr) { |
| 1088 LEnvironment* environment) { | |
| 1089 Deoptimizer::BailoutType bailout_type = info()->IsStub() | 1088 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
| 1090 ? Deoptimizer::LAZY | 1089 ? Deoptimizer::LAZY |
| 1091 : Deoptimizer::EAGER; | 1090 : Deoptimizer::EAGER; |
| 1092 DeoptimizeIf(cc, environment, bailout_type); | 1091 DeoptimizeIf(cc, instr, bailout_type); |
| 1093 } | 1092 } |
| 1094 | 1093 |
| 1095 | 1094 |
| 1096 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 1095 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 1097 int length = deoptimizations_.length(); | 1096 int length = deoptimizations_.length(); |
| 1098 if (length == 0) return; | 1097 if (length == 0) return; |
| 1099 Handle<DeoptimizationInputData> data = | 1098 Handle<DeoptimizationInputData> data = |
| 1100 DeoptimizationInputData::New(isolate(), length, TENURED); | 1099 DeoptimizationInputData::New(isolate(), length, TENURED); |
| 1101 | 1100 |
| 1102 Handle<ByteArray> translations = | 1101 Handle<ByteArray> translations = |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1311 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1310 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
| 1312 Label dividend_is_not_negative, done; | 1311 Label dividend_is_not_negative, done; |
| 1313 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { | 1312 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { |
| 1314 __ test(dividend, dividend); | 1313 __ test(dividend, dividend); |
| 1315 __ j(not_sign, ÷nd_is_not_negative, Label::kNear); | 1314 __ j(not_sign, ÷nd_is_not_negative, Label::kNear); |
| 1316 // Note that this is correct even for kMinInt operands. | 1315 // Note that this is correct even for kMinInt operands. |
| 1317 __ neg(dividend); | 1316 __ neg(dividend); |
| 1318 __ and_(dividend, mask); | 1317 __ and_(dividend, mask); |
| 1319 __ neg(dividend); | 1318 __ neg(dividend); |
| 1320 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1319 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1321 DeoptimizeIf(zero, instr->environment()); | 1320 DeoptimizeIf(zero, instr); |
| 1322 } | 1321 } |
| 1323 __ jmp(&done, Label::kNear); | 1322 __ jmp(&done, Label::kNear); |
| 1324 } | 1323 } |
| 1325 | 1324 |
| 1326 __ bind(÷nd_is_not_negative); | 1325 __ bind(÷nd_is_not_negative); |
| 1327 __ and_(dividend, mask); | 1326 __ and_(dividend, mask); |
| 1328 __ bind(&done); | 1327 __ bind(&done); |
| 1329 } | 1328 } |
| 1330 | 1329 |
| 1331 | 1330 |
| 1332 void LCodeGen::DoModByConstI(LModByConstI* instr) { | 1331 void LCodeGen::DoModByConstI(LModByConstI* instr) { |
| 1333 Register dividend = ToRegister(instr->dividend()); | 1332 Register dividend = ToRegister(instr->dividend()); |
| 1334 int32_t divisor = instr->divisor(); | 1333 int32_t divisor = instr->divisor(); |
| 1335 DCHECK(ToRegister(instr->result()).is(eax)); | 1334 DCHECK(ToRegister(instr->result()).is(eax)); |
| 1336 | 1335 |
| 1337 if (divisor == 0) { | 1336 if (divisor == 0) { |
| 1338 DeoptimizeIf(no_condition, instr->environment()); | 1337 DeoptimizeIf(no_condition, instr); |
| 1339 return; | 1338 return; |
| 1340 } | 1339 } |
| 1341 | 1340 |
| 1342 __ TruncatingDiv(dividend, Abs(divisor)); | 1341 __ TruncatingDiv(dividend, Abs(divisor)); |
| 1343 __ imul(edx, edx, Abs(divisor)); | 1342 __ imul(edx, edx, Abs(divisor)); |
| 1344 __ mov(eax, dividend); | 1343 __ mov(eax, dividend); |
| 1345 __ sub(eax, edx); | 1344 __ sub(eax, edx); |
| 1346 | 1345 |
| 1347 // Check for negative zero. | 1346 // Check for negative zero. |
| 1348 HMod* hmod = instr->hydrogen(); | 1347 HMod* hmod = instr->hydrogen(); |
| 1349 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1348 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1350 Label remainder_not_zero; | 1349 Label remainder_not_zero; |
| 1351 __ j(not_zero, &remainder_not_zero, Label::kNear); | 1350 __ j(not_zero, &remainder_not_zero, Label::kNear); |
| 1352 __ cmp(dividend, Immediate(0)); | 1351 __ cmp(dividend, Immediate(0)); |
| 1353 DeoptimizeIf(less, instr->environment()); | 1352 DeoptimizeIf(less, instr); |
| 1354 __ bind(&remainder_not_zero); | 1353 __ bind(&remainder_not_zero); |
| 1355 } | 1354 } |
| 1356 } | 1355 } |
| 1357 | 1356 |
| 1358 | 1357 |
| 1359 void LCodeGen::DoModI(LModI* instr) { | 1358 void LCodeGen::DoModI(LModI* instr) { |
| 1360 HMod* hmod = instr->hydrogen(); | 1359 HMod* hmod = instr->hydrogen(); |
| 1361 | 1360 |
| 1362 Register left_reg = ToRegister(instr->left()); | 1361 Register left_reg = ToRegister(instr->left()); |
| 1363 DCHECK(left_reg.is(eax)); | 1362 DCHECK(left_reg.is(eax)); |
| 1364 Register right_reg = ToRegister(instr->right()); | 1363 Register right_reg = ToRegister(instr->right()); |
| 1365 DCHECK(!right_reg.is(eax)); | 1364 DCHECK(!right_reg.is(eax)); |
| 1366 DCHECK(!right_reg.is(edx)); | 1365 DCHECK(!right_reg.is(edx)); |
| 1367 Register result_reg = ToRegister(instr->result()); | 1366 Register result_reg = ToRegister(instr->result()); |
| 1368 DCHECK(result_reg.is(edx)); | 1367 DCHECK(result_reg.is(edx)); |
| 1369 | 1368 |
| 1370 Label done; | 1369 Label done; |
| 1371 // Check for x % 0, idiv would signal a divide error. We have to | 1370 // Check for x % 0, idiv would signal a divide error. We have to |
| 1372 // deopt in this case because we can't return a NaN. | 1371 // deopt in this case because we can't return a NaN. |
| 1373 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { | 1372 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1374 __ test(right_reg, Operand(right_reg)); | 1373 __ test(right_reg, Operand(right_reg)); |
| 1375 DeoptimizeIf(zero, instr->environment()); | 1374 DeoptimizeIf(zero, instr); |
| 1376 } | 1375 } |
| 1377 | 1376 |
| 1378 // Check for kMinInt % -1, idiv would signal a divide error. We | 1377 // Check for kMinInt % -1, idiv would signal a divide error. We |
| 1379 // have to deopt if we care about -0, because we can't return that. | 1378 // have to deopt if we care about -0, because we can't return that. |
| 1380 if (hmod->CheckFlag(HValue::kCanOverflow)) { | 1379 if (hmod->CheckFlag(HValue::kCanOverflow)) { |
| 1381 Label no_overflow_possible; | 1380 Label no_overflow_possible; |
| 1382 __ cmp(left_reg, kMinInt); | 1381 __ cmp(left_reg, kMinInt); |
| 1383 __ j(not_equal, &no_overflow_possible, Label::kNear); | 1382 __ j(not_equal, &no_overflow_possible, Label::kNear); |
| 1384 __ cmp(right_reg, -1); | 1383 __ cmp(right_reg, -1); |
| 1385 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1384 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1386 DeoptimizeIf(equal, instr->environment()); | 1385 DeoptimizeIf(equal, instr); |
| 1387 } else { | 1386 } else { |
| 1388 __ j(not_equal, &no_overflow_possible, Label::kNear); | 1387 __ j(not_equal, &no_overflow_possible, Label::kNear); |
| 1389 __ Move(result_reg, Immediate(0)); | 1388 __ Move(result_reg, Immediate(0)); |
| 1390 __ jmp(&done, Label::kNear); | 1389 __ jmp(&done, Label::kNear); |
| 1391 } | 1390 } |
| 1392 __ bind(&no_overflow_possible); | 1391 __ bind(&no_overflow_possible); |
| 1393 } | 1392 } |
| 1394 | 1393 |
| 1395 // Sign extend dividend in eax into edx:eax. | 1394 // Sign extend dividend in eax into edx:eax. |
| 1396 __ cdq(); | 1395 __ cdq(); |
| 1397 | 1396 |
| 1398 // If we care about -0, test if the dividend is <0 and the result is 0. | 1397 // If we care about -0, test if the dividend is <0 and the result is 0. |
| 1399 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1398 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1400 Label positive_left; | 1399 Label positive_left; |
| 1401 __ test(left_reg, Operand(left_reg)); | 1400 __ test(left_reg, Operand(left_reg)); |
| 1402 __ j(not_sign, &positive_left, Label::kNear); | 1401 __ j(not_sign, &positive_left, Label::kNear); |
| 1403 __ idiv(right_reg); | 1402 __ idiv(right_reg); |
| 1404 __ test(result_reg, Operand(result_reg)); | 1403 __ test(result_reg, Operand(result_reg)); |
| 1405 DeoptimizeIf(zero, instr->environment()); | 1404 DeoptimizeIf(zero, instr); |
| 1406 __ jmp(&done, Label::kNear); | 1405 __ jmp(&done, Label::kNear); |
| 1407 __ bind(&positive_left); | 1406 __ bind(&positive_left); |
| 1408 } | 1407 } |
| 1409 __ idiv(right_reg); | 1408 __ idiv(right_reg); |
| 1410 __ bind(&done); | 1409 __ bind(&done); |
| 1411 } | 1410 } |
| 1412 | 1411 |
| 1413 | 1412 |
| 1414 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 1413 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
| 1415 Register dividend = ToRegister(instr->dividend()); | 1414 Register dividend = ToRegister(instr->dividend()); |
| 1416 int32_t divisor = instr->divisor(); | 1415 int32_t divisor = instr->divisor(); |
| 1417 Register result = ToRegister(instr->result()); | 1416 Register result = ToRegister(instr->result()); |
| 1418 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); | 1417 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); |
| 1419 DCHECK(!result.is(dividend)); | 1418 DCHECK(!result.is(dividend)); |
| 1420 | 1419 |
| 1421 // Check for (0 / -x) that will produce negative zero. | 1420 // Check for (0 / -x) that will produce negative zero. |
| 1422 HDiv* hdiv = instr->hydrogen(); | 1421 HDiv* hdiv = instr->hydrogen(); |
| 1423 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1422 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1424 __ test(dividend, dividend); | 1423 __ test(dividend, dividend); |
| 1425 DeoptimizeIf(zero, instr->environment()); | 1424 DeoptimizeIf(zero, instr); |
| 1426 } | 1425 } |
| 1427 // Check for (kMinInt / -1). | 1426 // Check for (kMinInt / -1). |
| 1428 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { | 1427 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { |
| 1429 __ cmp(dividend, kMinInt); | 1428 __ cmp(dividend, kMinInt); |
| 1430 DeoptimizeIf(zero, instr->environment()); | 1429 DeoptimizeIf(zero, instr); |
| 1431 } | 1430 } |
| 1432 // Deoptimize if remainder will not be 0. | 1431 // Deoptimize if remainder will not be 0. |
| 1433 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | 1432 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
| 1434 divisor != 1 && divisor != -1) { | 1433 divisor != 1 && divisor != -1) { |
| 1435 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1434 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
| 1436 __ test(dividend, Immediate(mask)); | 1435 __ test(dividend, Immediate(mask)); |
| 1437 DeoptimizeIf(not_zero, instr->environment()); | 1436 DeoptimizeIf(not_zero, instr); |
| 1438 } | 1437 } |
| 1439 __ Move(result, dividend); | 1438 __ Move(result, dividend); |
| 1440 int32_t shift = WhichPowerOf2Abs(divisor); | 1439 int32_t shift = WhichPowerOf2Abs(divisor); |
| 1441 if (shift > 0) { | 1440 if (shift > 0) { |
| 1442 // The arithmetic shift is always OK, the 'if' is an optimization only. | 1441 // The arithmetic shift is always OK, the 'if' is an optimization only. |
| 1443 if (shift > 1) __ sar(result, 31); | 1442 if (shift > 1) __ sar(result, 31); |
| 1444 __ shr(result, 32 - shift); | 1443 __ shr(result, 32 - shift); |
| 1445 __ add(result, dividend); | 1444 __ add(result, dividend); |
| 1446 __ sar(result, shift); | 1445 __ sar(result, shift); |
| 1447 } | 1446 } |
| 1448 if (divisor < 0) __ neg(result); | 1447 if (divisor < 0) __ neg(result); |
| 1449 } | 1448 } |
| 1450 | 1449 |
| 1451 | 1450 |
| 1452 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { | 1451 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { |
| 1453 Register dividend = ToRegister(instr->dividend()); | 1452 Register dividend = ToRegister(instr->dividend()); |
| 1454 int32_t divisor = instr->divisor(); | 1453 int32_t divisor = instr->divisor(); |
| 1455 DCHECK(ToRegister(instr->result()).is(edx)); | 1454 DCHECK(ToRegister(instr->result()).is(edx)); |
| 1456 | 1455 |
| 1457 if (divisor == 0) { | 1456 if (divisor == 0) { |
| 1458 DeoptimizeIf(no_condition, instr->environment()); | 1457 DeoptimizeIf(no_condition, instr); |
| 1459 return; | 1458 return; |
| 1460 } | 1459 } |
| 1461 | 1460 |
| 1462 // Check for (0 / -x) that will produce negative zero. | 1461 // Check for (0 / -x) that will produce negative zero. |
| 1463 HDiv* hdiv = instr->hydrogen(); | 1462 HDiv* hdiv = instr->hydrogen(); |
| 1464 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1463 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1465 __ test(dividend, dividend); | 1464 __ test(dividend, dividend); |
| 1466 DeoptimizeIf(zero, instr->environment()); | 1465 DeoptimizeIf(zero, instr); |
| 1467 } | 1466 } |
| 1468 | 1467 |
| 1469 __ TruncatingDiv(dividend, Abs(divisor)); | 1468 __ TruncatingDiv(dividend, Abs(divisor)); |
| 1470 if (divisor < 0) __ neg(edx); | 1469 if (divisor < 0) __ neg(edx); |
| 1471 | 1470 |
| 1472 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1471 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
| 1473 __ mov(eax, edx); | 1472 __ mov(eax, edx); |
| 1474 __ imul(eax, eax, divisor); | 1473 __ imul(eax, eax, divisor); |
| 1475 __ sub(eax, dividend); | 1474 __ sub(eax, dividend); |
| 1476 DeoptimizeIf(not_equal, instr->environment()); | 1475 DeoptimizeIf(not_equal, instr); |
| 1477 } | 1476 } |
| 1478 } | 1477 } |
| 1479 | 1478 |
| 1480 | 1479 |
| 1481 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. | 1480 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. |
| 1482 void LCodeGen::DoDivI(LDivI* instr) { | 1481 void LCodeGen::DoDivI(LDivI* instr) { |
| 1483 HBinaryOperation* hdiv = instr->hydrogen(); | 1482 HBinaryOperation* hdiv = instr->hydrogen(); |
| 1484 Register dividend = ToRegister(instr->dividend()); | 1483 Register dividend = ToRegister(instr->dividend()); |
| 1485 Register divisor = ToRegister(instr->divisor()); | 1484 Register divisor = ToRegister(instr->divisor()); |
| 1486 Register remainder = ToRegister(instr->temp()); | 1485 Register remainder = ToRegister(instr->temp()); |
| 1487 DCHECK(dividend.is(eax)); | 1486 DCHECK(dividend.is(eax)); |
| 1488 DCHECK(remainder.is(edx)); | 1487 DCHECK(remainder.is(edx)); |
| 1489 DCHECK(ToRegister(instr->result()).is(eax)); | 1488 DCHECK(ToRegister(instr->result()).is(eax)); |
| 1490 DCHECK(!divisor.is(eax)); | 1489 DCHECK(!divisor.is(eax)); |
| 1491 DCHECK(!divisor.is(edx)); | 1490 DCHECK(!divisor.is(edx)); |
| 1492 | 1491 |
| 1493 // Check for x / 0. | 1492 // Check for x / 0. |
| 1494 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1493 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1495 __ test(divisor, divisor); | 1494 __ test(divisor, divisor); |
| 1496 DeoptimizeIf(zero, instr->environment()); | 1495 DeoptimizeIf(zero, instr); |
| 1497 } | 1496 } |
| 1498 | 1497 |
| 1499 // Check for (0 / -x) that will produce negative zero. | 1498 // Check for (0 / -x) that will produce negative zero. |
| 1500 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1499 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1501 Label dividend_not_zero; | 1500 Label dividend_not_zero; |
| 1502 __ test(dividend, dividend); | 1501 __ test(dividend, dividend); |
| 1503 __ j(not_zero, ÷nd_not_zero, Label::kNear); | 1502 __ j(not_zero, ÷nd_not_zero, Label::kNear); |
| 1504 __ test(divisor, divisor); | 1503 __ test(divisor, divisor); |
| 1505 DeoptimizeIf(sign, instr->environment()); | 1504 DeoptimizeIf(sign, instr); |
| 1506 __ bind(÷nd_not_zero); | 1505 __ bind(÷nd_not_zero); |
| 1507 } | 1506 } |
| 1508 | 1507 |
| 1509 // Check for (kMinInt / -1). | 1508 // Check for (kMinInt / -1). |
| 1510 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 1509 if (hdiv->CheckFlag(HValue::kCanOverflow)) { |
| 1511 Label dividend_not_min_int; | 1510 Label dividend_not_min_int; |
| 1512 __ cmp(dividend, kMinInt); | 1511 __ cmp(dividend, kMinInt); |
| 1513 __ j(not_zero, ÷nd_not_min_int, Label::kNear); | 1512 __ j(not_zero, ÷nd_not_min_int, Label::kNear); |
| 1514 __ cmp(divisor, -1); | 1513 __ cmp(divisor, -1); |
| 1515 DeoptimizeIf(zero, instr->environment()); | 1514 DeoptimizeIf(zero, instr); |
| 1516 __ bind(÷nd_not_min_int); | 1515 __ bind(÷nd_not_min_int); |
| 1517 } | 1516 } |
| 1518 | 1517 |
| 1519 // Sign extend to edx (= remainder). | 1518 // Sign extend to edx (= remainder). |
| 1520 __ cdq(); | 1519 __ cdq(); |
| 1521 __ idiv(divisor); | 1520 __ idiv(divisor); |
| 1522 | 1521 |
| 1523 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1522 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1524 // Deoptimize if remainder is not 0. | 1523 // Deoptimize if remainder is not 0. |
| 1525 __ test(remainder, remainder); | 1524 __ test(remainder, remainder); |
| 1526 DeoptimizeIf(not_zero, instr->environment()); | 1525 DeoptimizeIf(not_zero, instr); |
| 1527 } | 1526 } |
| 1528 } | 1527 } |
| 1529 | 1528 |
| 1530 | 1529 |
| 1531 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { | 1530 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { |
| 1532 Register dividend = ToRegister(instr->dividend()); | 1531 Register dividend = ToRegister(instr->dividend()); |
| 1533 int32_t divisor = instr->divisor(); | 1532 int32_t divisor = instr->divisor(); |
| 1534 DCHECK(dividend.is(ToRegister(instr->result()))); | 1533 DCHECK(dividend.is(ToRegister(instr->result()))); |
| 1535 | 1534 |
| 1536 // If the divisor is positive, things are easy: There can be no deopts and we | 1535 // If the divisor is positive, things are easy: There can be no deopts and we |
| 1537 // can simply do an arithmetic right shift. | 1536 // can simply do an arithmetic right shift. |
| 1538 if (divisor == 1) return; | 1537 if (divisor == 1) return; |
| 1539 int32_t shift = WhichPowerOf2Abs(divisor); | 1538 int32_t shift = WhichPowerOf2Abs(divisor); |
| 1540 if (divisor > 1) { | 1539 if (divisor > 1) { |
| 1541 __ sar(dividend, shift); | 1540 __ sar(dividend, shift); |
| 1542 return; | 1541 return; |
| 1543 } | 1542 } |
| 1544 | 1543 |
| 1545 // If the divisor is negative, we have to negate and handle edge cases. | 1544 // If the divisor is negative, we have to negate and handle edge cases. |
| 1546 __ neg(dividend); | 1545 __ neg(dividend); |
| 1547 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1546 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1548 DeoptimizeIf(zero, instr->environment()); | 1547 DeoptimizeIf(zero, instr); |
| 1549 } | 1548 } |
| 1550 | 1549 |
| 1551 // Dividing by -1 is basically negation, unless we overflow. | 1550 // Dividing by -1 is basically negation, unless we overflow. |
| 1552 if (divisor == -1) { | 1551 if (divisor == -1) { |
| 1553 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1552 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
| 1554 DeoptimizeIf(overflow, instr->environment()); | 1553 DeoptimizeIf(overflow, instr); |
| 1555 } | 1554 } |
| 1556 return; | 1555 return; |
| 1557 } | 1556 } |
| 1558 | 1557 |
| 1559 // If the negation could not overflow, simply shifting is OK. | 1558 // If the negation could not overflow, simply shifting is OK. |
| 1560 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1559 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
| 1561 __ sar(dividend, shift); | 1560 __ sar(dividend, shift); |
| 1562 return; | 1561 return; |
| 1563 } | 1562 } |
| 1564 | 1563 |
| 1565 Label not_kmin_int, done; | 1564 Label not_kmin_int, done; |
| 1566 __ j(no_overflow, ¬_kmin_int, Label::kNear); | 1565 __ j(no_overflow, ¬_kmin_int, Label::kNear); |
| 1567 __ mov(dividend, Immediate(kMinInt / divisor)); | 1566 __ mov(dividend, Immediate(kMinInt / divisor)); |
| 1568 __ jmp(&done, Label::kNear); | 1567 __ jmp(&done, Label::kNear); |
| 1569 __ bind(¬_kmin_int); | 1568 __ bind(¬_kmin_int); |
| 1570 __ sar(dividend, shift); | 1569 __ sar(dividend, shift); |
| 1571 __ bind(&done); | 1570 __ bind(&done); |
| 1572 } | 1571 } |
| 1573 | 1572 |
| 1574 | 1573 |
| 1575 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { | 1574 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
| 1576 Register dividend = ToRegister(instr->dividend()); | 1575 Register dividend = ToRegister(instr->dividend()); |
| 1577 int32_t divisor = instr->divisor(); | 1576 int32_t divisor = instr->divisor(); |
| 1578 DCHECK(ToRegister(instr->result()).is(edx)); | 1577 DCHECK(ToRegister(instr->result()).is(edx)); |
| 1579 | 1578 |
| 1580 if (divisor == 0) { | 1579 if (divisor == 0) { |
| 1581 DeoptimizeIf(no_condition, instr->environment()); | 1580 DeoptimizeIf(no_condition, instr); |
| 1582 return; | 1581 return; |
| 1583 } | 1582 } |
| 1584 | 1583 |
| 1585 // Check for (0 / -x) that will produce negative zero. | 1584 // Check for (0 / -x) that will produce negative zero. |
| 1586 HMathFloorOfDiv* hdiv = instr->hydrogen(); | 1585 HMathFloorOfDiv* hdiv = instr->hydrogen(); |
| 1587 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1586 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1588 __ test(dividend, dividend); | 1587 __ test(dividend, dividend); |
| 1589 DeoptimizeIf(zero, instr->environment()); | 1588 DeoptimizeIf(zero, instr); |
| 1590 } | 1589 } |
| 1591 | 1590 |
| 1592 // Easy case: We need no dynamic check for the dividend and the flooring | 1591 // Easy case: We need no dynamic check for the dividend and the flooring |
| 1593 // division is the same as the truncating division. | 1592 // division is the same as the truncating division. |
| 1594 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || | 1593 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || |
| 1595 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { | 1594 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { |
| 1596 __ TruncatingDiv(dividend, Abs(divisor)); | 1595 __ TruncatingDiv(dividend, Abs(divisor)); |
| 1597 if (divisor < 0) __ neg(edx); | 1596 if (divisor < 0) __ neg(edx); |
| 1598 return; | 1597 return; |
| 1599 } | 1598 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1626 Register result = ToRegister(instr->result()); | 1625 Register result = ToRegister(instr->result()); |
| 1627 DCHECK(dividend.is(eax)); | 1626 DCHECK(dividend.is(eax)); |
| 1628 DCHECK(remainder.is(edx)); | 1627 DCHECK(remainder.is(edx)); |
| 1629 DCHECK(result.is(eax)); | 1628 DCHECK(result.is(eax)); |
| 1630 DCHECK(!divisor.is(eax)); | 1629 DCHECK(!divisor.is(eax)); |
| 1631 DCHECK(!divisor.is(edx)); | 1630 DCHECK(!divisor.is(edx)); |
| 1632 | 1631 |
| 1633 // Check for x / 0. | 1632 // Check for x / 0. |
| 1634 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1633 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1635 __ test(divisor, divisor); | 1634 __ test(divisor, divisor); |
| 1636 DeoptimizeIf(zero, instr->environment()); | 1635 DeoptimizeIf(zero, instr); |
| 1637 } | 1636 } |
| 1638 | 1637 |
| 1639 // Check for (0 / -x) that will produce negative zero. | 1638 // Check for (0 / -x) that will produce negative zero. |
| 1640 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1639 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1641 Label dividend_not_zero; | 1640 Label dividend_not_zero; |
| 1642 __ test(dividend, dividend); | 1641 __ test(dividend, dividend); |
| 1643 __ j(not_zero, ÷nd_not_zero, Label::kNear); | 1642 __ j(not_zero, ÷nd_not_zero, Label::kNear); |
| 1644 __ test(divisor, divisor); | 1643 __ test(divisor, divisor); |
| 1645 DeoptimizeIf(sign, instr->environment()); | 1644 DeoptimizeIf(sign, instr); |
| 1646 __ bind(÷nd_not_zero); | 1645 __ bind(÷nd_not_zero); |
| 1647 } | 1646 } |
| 1648 | 1647 |
| 1649 // Check for (kMinInt / -1). | 1648 // Check for (kMinInt / -1). |
| 1650 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 1649 if (hdiv->CheckFlag(HValue::kCanOverflow)) { |
| 1651 Label dividend_not_min_int; | 1650 Label dividend_not_min_int; |
| 1652 __ cmp(dividend, kMinInt); | 1651 __ cmp(dividend, kMinInt); |
| 1653 __ j(not_zero, ÷nd_not_min_int, Label::kNear); | 1652 __ j(not_zero, ÷nd_not_min_int, Label::kNear); |
| 1654 __ cmp(divisor, -1); | 1653 __ cmp(divisor, -1); |
| 1655 DeoptimizeIf(zero, instr->environment()); | 1654 DeoptimizeIf(zero, instr); |
| 1656 __ bind(÷nd_not_min_int); | 1655 __ bind(÷nd_not_min_int); |
| 1657 } | 1656 } |
| 1658 | 1657 |
| 1659 // Sign extend to edx (= remainder). | 1658 // Sign extend to edx (= remainder). |
| 1660 __ cdq(); | 1659 __ cdq(); |
| 1661 __ idiv(divisor); | 1660 __ idiv(divisor); |
| 1662 | 1661 |
| 1663 Label done; | 1662 Label done; |
| 1664 __ test(remainder, remainder); | 1663 __ test(remainder, remainder); |
| 1665 __ j(zero, &done, Label::kNear); | 1664 __ j(zero, &done, Label::kNear); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1723 __ imul(left, left, constant); | 1722 __ imul(left, left, constant); |
| 1724 } | 1723 } |
| 1725 } else { | 1724 } else { |
| 1726 if (instr->hydrogen()->representation().IsSmi()) { | 1725 if (instr->hydrogen()->representation().IsSmi()) { |
| 1727 __ SmiUntag(left); | 1726 __ SmiUntag(left); |
| 1728 } | 1727 } |
| 1729 __ imul(left, ToOperand(right)); | 1728 __ imul(left, ToOperand(right)); |
| 1730 } | 1729 } |
| 1731 | 1730 |
| 1732 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1731 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1733 DeoptimizeIf(overflow, instr->environment()); | 1732 DeoptimizeIf(overflow, instr); |
| 1734 } | 1733 } |
| 1735 | 1734 |
| 1736 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1735 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1737 // Bail out if the result is supposed to be negative zero. | 1736 // Bail out if the result is supposed to be negative zero. |
| 1738 Label done; | 1737 Label done; |
| 1739 __ test(left, Operand(left)); | 1738 __ test(left, Operand(left)); |
| 1740 __ j(not_zero, &done, Label::kNear); | 1739 __ j(not_zero, &done, Label::kNear); |
| 1741 if (right->IsConstantOperand()) { | 1740 if (right->IsConstantOperand()) { |
| 1742 if (ToInteger32(LConstantOperand::cast(right)) < 0) { | 1741 if (ToInteger32(LConstantOperand::cast(right)) < 0) { |
| 1743 DeoptimizeIf(no_condition, instr->environment()); | 1742 DeoptimizeIf(no_condition, instr); |
| 1744 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { | 1743 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { |
| 1745 __ cmp(ToRegister(instr->temp()), Immediate(0)); | 1744 __ cmp(ToRegister(instr->temp()), Immediate(0)); |
| 1746 DeoptimizeIf(less, instr->environment()); | 1745 DeoptimizeIf(less, instr); |
| 1747 } | 1746 } |
| 1748 } else { | 1747 } else { |
| 1749 // Test the non-zero operand for negative sign. | 1748 // Test the non-zero operand for negative sign. |
| 1750 __ or_(ToRegister(instr->temp()), ToOperand(right)); | 1749 __ or_(ToRegister(instr->temp()), ToOperand(right)); |
| 1751 DeoptimizeIf(sign, instr->environment()); | 1750 DeoptimizeIf(sign, instr); |
| 1752 } | 1751 } |
| 1753 __ bind(&done); | 1752 __ bind(&done); |
| 1754 } | 1753 } |
| 1755 } | 1754 } |
| 1756 | 1755 |
| 1757 | 1756 |
| 1758 void LCodeGen::DoBitI(LBitI* instr) { | 1757 void LCodeGen::DoBitI(LBitI* instr) { |
| 1759 LOperand* left = instr->left(); | 1758 LOperand* left = instr->left(); |
| 1760 LOperand* right = instr->right(); | 1759 LOperand* right = instr->right(); |
| 1761 DCHECK(left->Equals(instr->result())); | 1760 DCHECK(left->Equals(instr->result())); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1808 DCHECK(left->Equals(instr->result())); | 1807 DCHECK(left->Equals(instr->result())); |
| 1809 DCHECK(left->IsRegister()); | 1808 DCHECK(left->IsRegister()); |
| 1810 if (right->IsRegister()) { | 1809 if (right->IsRegister()) { |
| 1811 DCHECK(ToRegister(right).is(ecx)); | 1810 DCHECK(ToRegister(right).is(ecx)); |
| 1812 | 1811 |
| 1813 switch (instr->op()) { | 1812 switch (instr->op()) { |
| 1814 case Token::ROR: | 1813 case Token::ROR: |
| 1815 __ ror_cl(ToRegister(left)); | 1814 __ ror_cl(ToRegister(left)); |
| 1816 if (instr->can_deopt()) { | 1815 if (instr->can_deopt()) { |
| 1817 __ test(ToRegister(left), ToRegister(left)); | 1816 __ test(ToRegister(left), ToRegister(left)); |
| 1818 DeoptimizeIf(sign, instr->environment()); | 1817 DeoptimizeIf(sign, instr); |
| 1819 } | 1818 } |
| 1820 break; | 1819 break; |
| 1821 case Token::SAR: | 1820 case Token::SAR: |
| 1822 __ sar_cl(ToRegister(left)); | 1821 __ sar_cl(ToRegister(left)); |
| 1823 break; | 1822 break; |
| 1824 case Token::SHR: | 1823 case Token::SHR: |
| 1825 __ shr_cl(ToRegister(left)); | 1824 __ shr_cl(ToRegister(left)); |
| 1826 if (instr->can_deopt()) { | 1825 if (instr->can_deopt()) { |
| 1827 __ test(ToRegister(left), ToRegister(left)); | 1826 __ test(ToRegister(left), ToRegister(left)); |
| 1828 DeoptimizeIf(sign, instr->environment()); | 1827 DeoptimizeIf(sign, instr); |
| 1829 } | 1828 } |
| 1830 break; | 1829 break; |
| 1831 case Token::SHL: | 1830 case Token::SHL: |
| 1832 __ shl_cl(ToRegister(left)); | 1831 __ shl_cl(ToRegister(left)); |
| 1833 break; | 1832 break; |
| 1834 default: | 1833 default: |
| 1835 UNREACHABLE(); | 1834 UNREACHABLE(); |
| 1836 break; | 1835 break; |
| 1837 } | 1836 } |
| 1838 } else { | 1837 } else { |
| 1839 int value = ToInteger32(LConstantOperand::cast(right)); | 1838 int value = ToInteger32(LConstantOperand::cast(right)); |
| 1840 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); | 1839 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); |
| 1841 switch (instr->op()) { | 1840 switch (instr->op()) { |
| 1842 case Token::ROR: | 1841 case Token::ROR: |
| 1843 if (shift_count == 0 && instr->can_deopt()) { | 1842 if (shift_count == 0 && instr->can_deopt()) { |
| 1844 __ test(ToRegister(left), ToRegister(left)); | 1843 __ test(ToRegister(left), ToRegister(left)); |
| 1845 DeoptimizeIf(sign, instr->environment()); | 1844 DeoptimizeIf(sign, instr); |
| 1846 } else { | 1845 } else { |
| 1847 __ ror(ToRegister(left), shift_count); | 1846 __ ror(ToRegister(left), shift_count); |
| 1848 } | 1847 } |
| 1849 break; | 1848 break; |
| 1850 case Token::SAR: | 1849 case Token::SAR: |
| 1851 if (shift_count != 0) { | 1850 if (shift_count != 0) { |
| 1852 __ sar(ToRegister(left), shift_count); | 1851 __ sar(ToRegister(left), shift_count); |
| 1853 } | 1852 } |
| 1854 break; | 1853 break; |
| 1855 case Token::SHR: | 1854 case Token::SHR: |
| 1856 if (shift_count != 0) { | 1855 if (shift_count != 0) { |
| 1857 __ shr(ToRegister(left), shift_count); | 1856 __ shr(ToRegister(left), shift_count); |
| 1858 } else if (instr->can_deopt()) { | 1857 } else if (instr->can_deopt()) { |
| 1859 __ test(ToRegister(left), ToRegister(left)); | 1858 __ test(ToRegister(left), ToRegister(left)); |
| 1860 DeoptimizeIf(sign, instr->environment()); | 1859 DeoptimizeIf(sign, instr); |
| 1861 } | 1860 } |
| 1862 break; | 1861 break; |
| 1863 case Token::SHL: | 1862 case Token::SHL: |
| 1864 if (shift_count != 0) { | 1863 if (shift_count != 0) { |
| 1865 if (instr->hydrogen_value()->representation().IsSmi() && | 1864 if (instr->hydrogen_value()->representation().IsSmi() && |
| 1866 instr->can_deopt()) { | 1865 instr->can_deopt()) { |
| 1867 if (shift_count != 1) { | 1866 if (shift_count != 1) { |
| 1868 __ shl(ToRegister(left), shift_count - 1); | 1867 __ shl(ToRegister(left), shift_count - 1); |
| 1869 } | 1868 } |
| 1870 __ SmiTag(ToRegister(left)); | 1869 __ SmiTag(ToRegister(left)); |
| 1871 DeoptimizeIf(overflow, instr->environment()); | 1870 DeoptimizeIf(overflow, instr); |
| 1872 } else { | 1871 } else { |
| 1873 __ shl(ToRegister(left), shift_count); | 1872 __ shl(ToRegister(left), shift_count); |
| 1874 } | 1873 } |
| 1875 } | 1874 } |
| 1876 break; | 1875 break; |
| 1877 default: | 1876 default: |
| 1878 UNREACHABLE(); | 1877 UNREACHABLE(); |
| 1879 break; | 1878 break; |
| 1880 } | 1879 } |
| 1881 } | 1880 } |
| 1882 } | 1881 } |
| 1883 | 1882 |
| 1884 | 1883 |
| 1885 void LCodeGen::DoSubI(LSubI* instr) { | 1884 void LCodeGen::DoSubI(LSubI* instr) { |
| 1886 LOperand* left = instr->left(); | 1885 LOperand* left = instr->left(); |
| 1887 LOperand* right = instr->right(); | 1886 LOperand* right = instr->right(); |
| 1888 DCHECK(left->Equals(instr->result())); | 1887 DCHECK(left->Equals(instr->result())); |
| 1889 | 1888 |
| 1890 if (right->IsConstantOperand()) { | 1889 if (right->IsConstantOperand()) { |
| 1891 __ sub(ToOperand(left), | 1890 __ sub(ToOperand(left), |
| 1892 ToImmediate(right, instr->hydrogen()->representation())); | 1891 ToImmediate(right, instr->hydrogen()->representation())); |
| 1893 } else { | 1892 } else { |
| 1894 __ sub(ToRegister(left), ToOperand(right)); | 1893 __ sub(ToRegister(left), ToOperand(right)); |
| 1895 } | 1894 } |
| 1896 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1895 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1897 DeoptimizeIf(overflow, instr->environment()); | 1896 DeoptimizeIf(overflow, instr); |
| 1898 } | 1897 } |
| 1899 } | 1898 } |
| 1900 | 1899 |
| 1901 | 1900 |
| 1902 void LCodeGen::DoConstantI(LConstantI* instr) { | 1901 void LCodeGen::DoConstantI(LConstantI* instr) { |
| 1903 __ Move(ToRegister(instr->result()), Immediate(instr->value())); | 1902 __ Move(ToRegister(instr->result()), Immediate(instr->value())); |
| 1904 } | 1903 } |
| 1905 | 1904 |
| 1906 | 1905 |
| 1907 void LCodeGen::DoConstantS(LConstantS* instr) { | 1906 void LCodeGen::DoConstantS(LConstantS* instr) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1947 void LCodeGen::DoDateField(LDateField* instr) { | 1946 void LCodeGen::DoDateField(LDateField* instr) { |
| 1948 Register object = ToRegister(instr->date()); | 1947 Register object = ToRegister(instr->date()); |
| 1949 Register result = ToRegister(instr->result()); | 1948 Register result = ToRegister(instr->result()); |
| 1950 Register scratch = ToRegister(instr->temp()); | 1949 Register scratch = ToRegister(instr->temp()); |
| 1951 Smi* index = instr->index(); | 1950 Smi* index = instr->index(); |
| 1952 Label runtime, done; | 1951 Label runtime, done; |
| 1953 DCHECK(object.is(result)); | 1952 DCHECK(object.is(result)); |
| 1954 DCHECK(object.is(eax)); | 1953 DCHECK(object.is(eax)); |
| 1955 | 1954 |
| 1956 __ test(object, Immediate(kSmiTagMask)); | 1955 __ test(object, Immediate(kSmiTagMask)); |
| 1957 DeoptimizeIf(zero, instr->environment()); | 1956 DeoptimizeIf(zero, instr); |
| 1958 __ CmpObjectType(object, JS_DATE_TYPE, scratch); | 1957 __ CmpObjectType(object, JS_DATE_TYPE, scratch); |
| 1959 DeoptimizeIf(not_equal, instr->environment()); | 1958 DeoptimizeIf(not_equal, instr); |
| 1960 | 1959 |
| 1961 if (index->value() == 0) { | 1960 if (index->value() == 0) { |
| 1962 __ mov(result, FieldOperand(object, JSDate::kValueOffset)); | 1961 __ mov(result, FieldOperand(object, JSDate::kValueOffset)); |
| 1963 } else { | 1962 } else { |
| 1964 if (index->value() < JSDate::kFirstUncachedField) { | 1963 if (index->value() < JSDate::kFirstUncachedField) { |
| 1965 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); | 1964 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); |
| 1966 __ mov(scratch, Operand::StaticVariable(stamp)); | 1965 __ mov(scratch, Operand::StaticVariable(stamp)); |
| 1967 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); | 1966 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); |
| 1968 __ j(not_equal, &runtime, Label::kNear); | 1967 __ j(not_equal, &runtime, Label::kNear); |
| 1969 __ mov(result, FieldOperand(object, JSDate::kValueOffset + | 1968 __ mov(result, FieldOperand(object, JSDate::kValueOffset + |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2079 __ lea(ToRegister(instr->result()), address); | 2078 __ lea(ToRegister(instr->result()), address); |
| 2080 } | 2079 } |
| 2081 } else { | 2080 } else { |
| 2082 if (right->IsConstantOperand()) { | 2081 if (right->IsConstantOperand()) { |
| 2083 __ add(ToOperand(left), | 2082 __ add(ToOperand(left), |
| 2084 ToImmediate(right, instr->hydrogen()->representation())); | 2083 ToImmediate(right, instr->hydrogen()->representation())); |
| 2085 } else { | 2084 } else { |
| 2086 __ add(ToRegister(left), ToOperand(right)); | 2085 __ add(ToRegister(left), ToOperand(right)); |
| 2087 } | 2086 } |
| 2088 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 2087 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 2089 DeoptimizeIf(overflow, instr->environment()); | 2088 DeoptimizeIf(overflow, instr); |
| 2090 } | 2089 } |
| 2091 } | 2090 } |
| 2092 } | 2091 } |
| 2093 | 2092 |
| 2094 | 2093 |
| 2095 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 2094 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
| 2096 LOperand* left = instr->left(); | 2095 LOperand* left = instr->left(); |
| 2097 LOperand* right = instr->right(); | 2096 LOperand* right = instr->right(); |
| 2098 DCHECK(left->Equals(instr->result())); | 2097 DCHECK(left->Equals(instr->result())); |
| 2099 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 2098 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2263 } | 2262 } |
| 2264 | 2263 |
| 2265 if (expected.Contains(ToBooleanStub::SMI)) { | 2264 if (expected.Contains(ToBooleanStub::SMI)) { |
| 2266 // Smis: 0 -> false, all other -> true. | 2265 // Smis: 0 -> false, all other -> true. |
| 2267 __ test(reg, Operand(reg)); | 2266 __ test(reg, Operand(reg)); |
| 2268 __ j(equal, instr->FalseLabel(chunk_)); | 2267 __ j(equal, instr->FalseLabel(chunk_)); |
| 2269 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 2268 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
| 2270 } else if (expected.NeedsMap()) { | 2269 } else if (expected.NeedsMap()) { |
| 2271 // If we need a map later and have a Smi -> deopt. | 2270 // If we need a map later and have a Smi -> deopt. |
| 2272 __ test(reg, Immediate(kSmiTagMask)); | 2271 __ test(reg, Immediate(kSmiTagMask)); |
| 2273 DeoptimizeIf(zero, instr->environment()); | 2272 DeoptimizeIf(zero, instr); |
| 2274 } | 2273 } |
| 2275 | 2274 |
| 2276 Register map = no_reg; // Keep the compiler happy. | 2275 Register map = no_reg; // Keep the compiler happy. |
| 2277 if (expected.NeedsMap()) { | 2276 if (expected.NeedsMap()) { |
| 2278 map = ToRegister(instr->temp()); | 2277 map = ToRegister(instr->temp()); |
| 2279 DCHECK(!map.is(reg)); | 2278 DCHECK(!map.is(reg)); |
| 2280 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); | 2279 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); |
| 2281 | 2280 |
| 2282 if (expected.CanBeUndetectable()) { | 2281 if (expected.CanBeUndetectable()) { |
| 2283 // Undetectable -> false. | 2282 // Undetectable -> false. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2320 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 2319 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
| 2321 __ FCmp(); | 2320 __ FCmp(); |
| 2322 __ j(zero, instr->FalseLabel(chunk_)); | 2321 __ j(zero, instr->FalseLabel(chunk_)); |
| 2323 __ jmp(instr->TrueLabel(chunk_)); | 2322 __ jmp(instr->TrueLabel(chunk_)); |
| 2324 __ bind(¬_heap_number); | 2323 __ bind(¬_heap_number); |
| 2325 } | 2324 } |
| 2326 | 2325 |
| 2327 if (!expected.IsGeneric()) { | 2326 if (!expected.IsGeneric()) { |
| 2328 // We've seen something for the first time -> deopt. | 2327 // We've seen something for the first time -> deopt. |
| 2329 // This can only happen if we are not generic already. | 2328 // This can only happen if we are not generic already. |
| 2330 DeoptimizeIf(no_condition, instr->environment()); | 2329 DeoptimizeIf(no_condition, instr); |
| 2331 } | 2330 } |
| 2332 } | 2331 } |
| 2333 } | 2332 } |
| 2334 } | 2333 } |
| 2335 | 2334 |
| 2336 | 2335 |
| 2337 void LCodeGen::EmitGoto(int block) { | 2336 void LCodeGen::EmitGoto(int block) { |
| 2338 if (!IsNextEmittedBlock(block)) { | 2337 if (!IsNextEmittedBlock(block)) { |
| 2339 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); | 2338 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); |
| 2340 } | 2339 } |
| (...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2956 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset()); | 2955 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset()); |
| 2957 } | 2956 } |
| 2958 } | 2957 } |
| 2959 | 2958 |
| 2960 | 2959 |
| 2961 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { | 2960 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { |
| 2962 Register result = ToRegister(instr->result()); | 2961 Register result = ToRegister(instr->result()); |
| 2963 __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle())); | 2962 __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle())); |
| 2964 if (instr->hydrogen()->RequiresHoleCheck()) { | 2963 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2965 __ cmp(result, factory()->the_hole_value()); | 2964 __ cmp(result, factory()->the_hole_value()); |
| 2966 DeoptimizeIf(equal, instr->environment()); | 2965 DeoptimizeIf(equal, instr); |
| 2967 } | 2966 } |
| 2968 } | 2967 } |
| 2969 | 2968 |
| 2970 | 2969 |
| 2971 template <class T> | 2970 template <class T> |
| 2972 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { | 2971 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { |
| 2973 DCHECK(FLAG_vector_ics); | 2972 DCHECK(FLAG_vector_ics); |
| 2974 Register vector = ToRegister(instr->temp_vector()); | 2973 Register vector = ToRegister(instr->temp_vector()); |
| 2975 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); | 2974 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); |
| 2976 __ mov(vector, instr->hydrogen()->feedback_vector()); | 2975 __ mov(vector, instr->hydrogen()->feedback_vector()); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3000 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 2999 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
| 3001 Register value = ToRegister(instr->value()); | 3000 Register value = ToRegister(instr->value()); |
| 3002 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle(); | 3001 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle(); |
| 3003 | 3002 |
| 3004 // If the cell we are storing to contains the hole it could have | 3003 // If the cell we are storing to contains the hole it could have |
| 3005 // been deleted from the property dictionary. In that case, we need | 3004 // been deleted from the property dictionary. In that case, we need |
| 3006 // to update the property details in the property dictionary to mark | 3005 // to update the property details in the property dictionary to mark |
| 3007 // it as no longer deleted. We deoptimize in that case. | 3006 // it as no longer deleted. We deoptimize in that case. |
| 3008 if (instr->hydrogen()->RequiresHoleCheck()) { | 3007 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3009 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value()); | 3008 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value()); |
| 3010 DeoptimizeIf(equal, instr->environment()); | 3009 DeoptimizeIf(equal, instr); |
| 3011 } | 3010 } |
| 3012 | 3011 |
| 3013 // Store the value. | 3012 // Store the value. |
| 3014 __ mov(Operand::ForCell(cell_handle), value); | 3013 __ mov(Operand::ForCell(cell_handle), value); |
| 3015 // Cells are always rescanned, so no write barrier here. | 3014 // Cells are always rescanned, so no write barrier here. |
| 3016 } | 3015 } |
| 3017 | 3016 |
| 3018 | 3017 |
| 3019 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 3018 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
| 3020 Register context = ToRegister(instr->context()); | 3019 Register context = ToRegister(instr->context()); |
| 3021 Register result = ToRegister(instr->result()); | 3020 Register result = ToRegister(instr->result()); |
| 3022 __ mov(result, ContextOperand(context, instr->slot_index())); | 3021 __ mov(result, ContextOperand(context, instr->slot_index())); |
| 3023 | 3022 |
| 3024 if (instr->hydrogen()->RequiresHoleCheck()) { | 3023 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3025 __ cmp(result, factory()->the_hole_value()); | 3024 __ cmp(result, factory()->the_hole_value()); |
| 3026 if (instr->hydrogen()->DeoptimizesOnHole()) { | 3025 if (instr->hydrogen()->DeoptimizesOnHole()) { |
| 3027 DeoptimizeIf(equal, instr->environment()); | 3026 DeoptimizeIf(equal, instr); |
| 3028 } else { | 3027 } else { |
| 3029 Label is_not_hole; | 3028 Label is_not_hole; |
| 3030 __ j(not_equal, &is_not_hole, Label::kNear); | 3029 __ j(not_equal, &is_not_hole, Label::kNear); |
| 3031 __ mov(result, factory()->undefined_value()); | 3030 __ mov(result, factory()->undefined_value()); |
| 3032 __ bind(&is_not_hole); | 3031 __ bind(&is_not_hole); |
| 3033 } | 3032 } |
| 3034 } | 3033 } |
| 3035 } | 3034 } |
| 3036 | 3035 |
| 3037 | 3036 |
| 3038 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 3037 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
| 3039 Register context = ToRegister(instr->context()); | 3038 Register context = ToRegister(instr->context()); |
| 3040 Register value = ToRegister(instr->value()); | 3039 Register value = ToRegister(instr->value()); |
| 3041 | 3040 |
| 3042 Label skip_assignment; | 3041 Label skip_assignment; |
| 3043 | 3042 |
| 3044 Operand target = ContextOperand(context, instr->slot_index()); | 3043 Operand target = ContextOperand(context, instr->slot_index()); |
| 3045 if (instr->hydrogen()->RequiresHoleCheck()) { | 3044 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3046 __ cmp(target, factory()->the_hole_value()); | 3045 __ cmp(target, factory()->the_hole_value()); |
| 3047 if (instr->hydrogen()->DeoptimizesOnHole()) { | 3046 if (instr->hydrogen()->DeoptimizesOnHole()) { |
| 3048 DeoptimizeIf(equal, instr->environment()); | 3047 DeoptimizeIf(equal, instr); |
| 3049 } else { | 3048 } else { |
| 3050 __ j(not_equal, &skip_assignment, Label::kNear); | 3049 __ j(not_equal, &skip_assignment, Label::kNear); |
| 3051 } | 3050 } |
| 3052 } | 3051 } |
| 3053 | 3052 |
| 3054 __ mov(target, value); | 3053 __ mov(target, value); |
| 3055 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3054 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 3056 SmiCheck check_needed = | 3055 SmiCheck check_needed = |
| 3057 instr->hydrogen()->value()->type().IsHeapObject() | 3056 instr->hydrogen()->value()->type().IsHeapObject() |
| 3058 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 3057 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3135 Register function = ToRegister(instr->function()); | 3134 Register function = ToRegister(instr->function()); |
| 3136 Register temp = ToRegister(instr->temp()); | 3135 Register temp = ToRegister(instr->temp()); |
| 3137 Register result = ToRegister(instr->result()); | 3136 Register result = ToRegister(instr->result()); |
| 3138 | 3137 |
| 3139 // Get the prototype or initial map from the function. | 3138 // Get the prototype or initial map from the function. |
| 3140 __ mov(result, | 3139 __ mov(result, |
| 3141 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 3140 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 3142 | 3141 |
| 3143 // Check that the function has a prototype or an initial map. | 3142 // Check that the function has a prototype or an initial map. |
| 3144 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); | 3143 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); |
| 3145 DeoptimizeIf(equal, instr->environment()); | 3144 DeoptimizeIf(equal, instr); |
| 3146 | 3145 |
| 3147 // If the function does not have an initial map, we're done. | 3146 // If the function does not have an initial map, we're done. |
| 3148 Label done; | 3147 Label done; |
| 3149 __ CmpObjectType(result, MAP_TYPE, temp); | 3148 __ CmpObjectType(result, MAP_TYPE, temp); |
| 3150 __ j(not_equal, &done, Label::kNear); | 3149 __ j(not_equal, &done, Label::kNear); |
| 3151 | 3150 |
| 3152 // Get the prototype from the initial map. | 3151 // Get the prototype from the initial map. |
| 3153 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); | 3152 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); |
| 3154 | 3153 |
| 3155 // All done. | 3154 // All done. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3226 break; | 3225 break; |
| 3227 case EXTERNAL_INT32_ELEMENTS: | 3226 case EXTERNAL_INT32_ELEMENTS: |
| 3228 case INT32_ELEMENTS: | 3227 case INT32_ELEMENTS: |
| 3229 __ mov(result, operand); | 3228 __ mov(result, operand); |
| 3230 break; | 3229 break; |
| 3231 case EXTERNAL_UINT32_ELEMENTS: | 3230 case EXTERNAL_UINT32_ELEMENTS: |
| 3232 case UINT32_ELEMENTS: | 3231 case UINT32_ELEMENTS: |
| 3233 __ mov(result, operand); | 3232 __ mov(result, operand); |
| 3234 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 3233 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
| 3235 __ test(result, Operand(result)); | 3234 __ test(result, Operand(result)); |
| 3236 DeoptimizeIf(negative, instr->environment()); | 3235 DeoptimizeIf(negative, instr); |
| 3237 } | 3236 } |
| 3238 break; | 3237 break; |
| 3239 case EXTERNAL_FLOAT32_ELEMENTS: | 3238 case EXTERNAL_FLOAT32_ELEMENTS: |
| 3240 case EXTERNAL_FLOAT64_ELEMENTS: | 3239 case EXTERNAL_FLOAT64_ELEMENTS: |
| 3241 case FLOAT32_ELEMENTS: | 3240 case FLOAT32_ELEMENTS: |
| 3242 case FLOAT64_ELEMENTS: | 3241 case FLOAT64_ELEMENTS: |
| 3243 case FAST_SMI_ELEMENTS: | 3242 case FAST_SMI_ELEMENTS: |
| 3244 case FAST_ELEMENTS: | 3243 case FAST_ELEMENTS: |
| 3245 case FAST_DOUBLE_ELEMENTS: | 3244 case FAST_DOUBLE_ELEMENTS: |
| 3246 case FAST_HOLEY_SMI_ELEMENTS: | 3245 case FAST_HOLEY_SMI_ELEMENTS: |
| 3247 case FAST_HOLEY_ELEMENTS: | 3246 case FAST_HOLEY_ELEMENTS: |
| 3248 case FAST_HOLEY_DOUBLE_ELEMENTS: | 3247 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 3249 case DICTIONARY_ELEMENTS: | 3248 case DICTIONARY_ELEMENTS: |
| 3250 case SLOPPY_ARGUMENTS_ELEMENTS: | 3249 case SLOPPY_ARGUMENTS_ELEMENTS: |
| 3251 UNREACHABLE(); | 3250 UNREACHABLE(); |
| 3252 break; | 3251 break; |
| 3253 } | 3252 } |
| 3254 } | 3253 } |
| 3255 } | 3254 } |
| 3256 | 3255 |
| 3257 | 3256 |
| 3258 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { | 3257 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { |
| 3259 if (instr->hydrogen()->RequiresHoleCheck()) { | 3258 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3260 Operand hole_check_operand = BuildFastArrayOperand( | 3259 Operand hole_check_operand = BuildFastArrayOperand( |
| 3261 instr->elements(), instr->key(), | 3260 instr->elements(), instr->key(), |
| 3262 instr->hydrogen()->key()->representation(), | 3261 instr->hydrogen()->key()->representation(), |
| 3263 FAST_DOUBLE_ELEMENTS, | 3262 FAST_DOUBLE_ELEMENTS, |
| 3264 instr->base_offset() + sizeof(kHoleNanLower32)); | 3263 instr->base_offset() + sizeof(kHoleNanLower32)); |
| 3265 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); | 3264 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); |
| 3266 DeoptimizeIf(equal, instr->environment()); | 3265 DeoptimizeIf(equal, instr); |
| 3267 } | 3266 } |
| 3268 | 3267 |
| 3269 Operand double_load_operand = BuildFastArrayOperand( | 3268 Operand double_load_operand = BuildFastArrayOperand( |
| 3270 instr->elements(), | 3269 instr->elements(), |
| 3271 instr->key(), | 3270 instr->key(), |
| 3272 instr->hydrogen()->key()->representation(), | 3271 instr->hydrogen()->key()->representation(), |
| 3273 FAST_DOUBLE_ELEMENTS, | 3272 FAST_DOUBLE_ELEMENTS, |
| 3274 instr->base_offset()); | 3273 instr->base_offset()); |
| 3275 X87Mov(ToX87Register(instr->result()), double_load_operand); | 3274 X87Mov(ToX87Register(instr->result()), double_load_operand); |
| 3276 } | 3275 } |
| 3277 | 3276 |
| 3278 | 3277 |
| 3279 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3278 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
| 3280 Register result = ToRegister(instr->result()); | 3279 Register result = ToRegister(instr->result()); |
| 3281 | 3280 |
| 3282 // Load the result. | 3281 // Load the result. |
| 3283 __ mov(result, | 3282 __ mov(result, |
| 3284 BuildFastArrayOperand(instr->elements(), instr->key(), | 3283 BuildFastArrayOperand(instr->elements(), instr->key(), |
| 3285 instr->hydrogen()->key()->representation(), | 3284 instr->hydrogen()->key()->representation(), |
| 3286 FAST_ELEMENTS, instr->base_offset())); | 3285 FAST_ELEMENTS, instr->base_offset())); |
| 3287 | 3286 |
| 3288 // Check for the hole value. | 3287 // Check for the hole value. |
| 3289 if (instr->hydrogen()->RequiresHoleCheck()) { | 3288 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3290 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { | 3289 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { |
| 3291 __ test(result, Immediate(kSmiTagMask)); | 3290 __ test(result, Immediate(kSmiTagMask)); |
| 3292 DeoptimizeIf(not_equal, instr->environment()); | 3291 DeoptimizeIf(not_equal, instr); |
| 3293 } else { | 3292 } else { |
| 3294 __ cmp(result, factory()->the_hole_value()); | 3293 __ cmp(result, factory()->the_hole_value()); |
| 3295 DeoptimizeIf(equal, instr->environment()); | 3294 DeoptimizeIf(equal, instr); |
| 3296 } | 3295 } |
| 3297 } | 3296 } |
| 3298 } | 3297 } |
| 3299 | 3298 |
| 3300 | 3299 |
| 3301 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { | 3300 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { |
| 3302 if (instr->is_typed_elements()) { | 3301 if (instr->is_typed_elements()) { |
| 3303 DoLoadKeyedExternalArray(instr); | 3302 DoLoadKeyedExternalArray(instr); |
| 3304 } else if (instr->hydrogen()->representation().IsDouble()) { | 3303 } else if (instr->hydrogen()->representation().IsDouble()) { |
| 3305 DoLoadKeyedFixedDoubleArray(instr); | 3304 DoLoadKeyedFixedDoubleArray(instr); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3432 } | 3431 } |
| 3433 | 3432 |
| 3434 // Normal function. Replace undefined or null with global receiver. | 3433 // Normal function. Replace undefined or null with global receiver. |
| 3435 __ cmp(receiver, factory()->null_value()); | 3434 __ cmp(receiver, factory()->null_value()); |
| 3436 __ j(equal, &global_object, Label::kNear); | 3435 __ j(equal, &global_object, Label::kNear); |
| 3437 __ cmp(receiver, factory()->undefined_value()); | 3436 __ cmp(receiver, factory()->undefined_value()); |
| 3438 __ j(equal, &global_object, Label::kNear); | 3437 __ j(equal, &global_object, Label::kNear); |
| 3439 | 3438 |
| 3440 // The receiver should be a JS object. | 3439 // The receiver should be a JS object. |
| 3441 __ test(receiver, Immediate(kSmiTagMask)); | 3440 __ test(receiver, Immediate(kSmiTagMask)); |
| 3442 DeoptimizeIf(equal, instr->environment()); | 3441 DeoptimizeIf(equal, instr); |
| 3443 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); | 3442 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); |
| 3444 DeoptimizeIf(below, instr->environment()); | 3443 DeoptimizeIf(below, instr); |
| 3445 | 3444 |
| 3446 __ jmp(&receiver_ok, Label::kNear); | 3445 __ jmp(&receiver_ok, Label::kNear); |
| 3447 __ bind(&global_object); | 3446 __ bind(&global_object); |
| 3448 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); | 3447 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); |
| 3449 const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); | 3448 const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); |
| 3450 __ mov(receiver, Operand(receiver, global_offset)); | 3449 __ mov(receiver, Operand(receiver, global_offset)); |
| 3451 const int proxy_offset = GlobalObject::kGlobalProxyOffset; | 3450 const int proxy_offset = GlobalObject::kGlobalProxyOffset; |
| 3452 __ mov(receiver, FieldOperand(receiver, proxy_offset)); | 3451 __ mov(receiver, FieldOperand(receiver, proxy_offset)); |
| 3453 __ bind(&receiver_ok); | 3452 __ bind(&receiver_ok); |
| 3454 } | 3453 } |
| 3455 | 3454 |
| 3456 | 3455 |
| 3457 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 3456 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
| 3458 Register receiver = ToRegister(instr->receiver()); | 3457 Register receiver = ToRegister(instr->receiver()); |
| 3459 Register function = ToRegister(instr->function()); | 3458 Register function = ToRegister(instr->function()); |
| 3460 Register length = ToRegister(instr->length()); | 3459 Register length = ToRegister(instr->length()); |
| 3461 Register elements = ToRegister(instr->elements()); | 3460 Register elements = ToRegister(instr->elements()); |
| 3462 DCHECK(receiver.is(eax)); // Used for parameter count. | 3461 DCHECK(receiver.is(eax)); // Used for parameter count. |
| 3463 DCHECK(function.is(edi)); // Required by InvokeFunction. | 3462 DCHECK(function.is(edi)); // Required by InvokeFunction. |
| 3464 DCHECK(ToRegister(instr->result()).is(eax)); | 3463 DCHECK(ToRegister(instr->result()).is(eax)); |
| 3465 | 3464 |
| 3466 // Copy the arguments to this function possibly from the | 3465 // Copy the arguments to this function possibly from the |
| 3467 // adaptor frame below it. | 3466 // adaptor frame below it. |
| 3468 const uint32_t kArgumentsLimit = 1 * KB; | 3467 const uint32_t kArgumentsLimit = 1 * KB; |
| 3469 __ cmp(length, kArgumentsLimit); | 3468 __ cmp(length, kArgumentsLimit); |
| 3470 DeoptimizeIf(above, instr->environment()); | 3469 DeoptimizeIf(above, instr); |
| 3471 | 3470 |
| 3472 __ push(receiver); | 3471 __ push(receiver); |
| 3473 __ mov(receiver, length); | 3472 __ mov(receiver, length); |
| 3474 | 3473 |
| 3475 // Loop through the arguments pushing them onto the execution | 3474 // Loop through the arguments pushing them onto the execution |
| 3476 // stack. | 3475 // stack. |
| 3477 Label invoke, loop; | 3476 Label invoke, loop; |
| 3478 // length is a small non-negative integer, due to the test above. | 3477 // length is a small non-negative integer, due to the test above. |
| 3479 __ test(length, Operand(length)); | 3478 __ test(length, Operand(length)); |
| 3480 __ j(zero, &invoke, Label::kNear); | 3479 __ j(zero, &invoke, Label::kNear); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3653 } | 3652 } |
| 3654 | 3653 |
| 3655 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3654 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 3656 } | 3655 } |
| 3657 | 3656 |
| 3658 | 3657 |
| 3659 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3658 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3660 Register input_reg = ToRegister(instr->value()); | 3659 Register input_reg = ToRegister(instr->value()); |
| 3661 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 3660 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3662 factory()->heap_number_map()); | 3661 factory()->heap_number_map()); |
| 3663 DeoptimizeIf(not_equal, instr->environment()); | 3662 DeoptimizeIf(not_equal, instr); |
| 3664 | 3663 |
| 3665 Label slow, allocated, done; | 3664 Label slow, allocated, done; |
| 3666 Register tmp = input_reg.is(eax) ? ecx : eax; | 3665 Register tmp = input_reg.is(eax) ? ecx : eax; |
| 3667 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; | 3666 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; |
| 3668 | 3667 |
| 3669 // Preserve the value of all registers. | 3668 // Preserve the value of all registers. |
| 3670 PushSafepointRegistersScope scope(this); | 3669 PushSafepointRegistersScope scope(this); |
| 3671 | 3670 |
| 3672 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 3671 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
| 3673 // Check the sign of the argument. If the argument is positive, just | 3672 // Check the sign of the argument. If the argument is positive, just |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3700 __ bind(&done); | 3699 __ bind(&done); |
| 3701 } | 3700 } |
| 3702 | 3701 |
| 3703 | 3702 |
| 3704 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { | 3703 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { |
| 3705 Register input_reg = ToRegister(instr->value()); | 3704 Register input_reg = ToRegister(instr->value()); |
| 3706 __ test(input_reg, Operand(input_reg)); | 3705 __ test(input_reg, Operand(input_reg)); |
| 3707 Label is_positive; | 3706 Label is_positive; |
| 3708 __ j(not_sign, &is_positive, Label::kNear); | 3707 __ j(not_sign, &is_positive, Label::kNear); |
| 3709 __ neg(input_reg); // Sets flags. | 3708 __ neg(input_reg); // Sets flags. |
| 3710 DeoptimizeIf(negative, instr->environment()); | 3709 DeoptimizeIf(negative, instr); |
| 3711 __ bind(&is_positive); | 3710 __ bind(&is_positive); |
| 3712 } | 3711 } |
| 3713 | 3712 |
| 3714 | 3713 |
| 3715 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3714 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
| 3716 // Class for deferred case. | 3715 // Class for deferred case. |
| 3717 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { | 3716 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { |
| 3718 public: | 3717 public: |
| 3719 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 3718 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
| 3720 LMathAbs* instr, | 3719 LMathAbs* instr, |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4026 instr->hydrogen()->index()->representation())); | 4025 instr->hydrogen()->index()->representation())); |
| 4027 } else { | 4026 } else { |
| 4028 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); | 4027 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); |
| 4029 } | 4028 } |
| 4030 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { | 4029 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { |
| 4031 Label done; | 4030 Label done; |
| 4032 __ j(NegateCondition(cc), &done, Label::kNear); | 4031 __ j(NegateCondition(cc), &done, Label::kNear); |
| 4033 __ int3(); | 4032 __ int3(); |
| 4034 __ bind(&done); | 4033 __ bind(&done); |
| 4035 } else { | 4034 } else { |
| 4036 DeoptimizeIf(cc, instr->environment()); | 4035 DeoptimizeIf(cc, instr); |
| 4037 } | 4036 } |
| 4038 } | 4037 } |
| 4039 | 4038 |
| 4040 | 4039 |
| 4041 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4040 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
| 4042 ElementsKind elements_kind = instr->elements_kind(); | 4041 ElementsKind elements_kind = instr->elements_kind(); |
| 4043 LOperand* key = instr->key(); | 4042 LOperand* key = instr->key(); |
| 4044 if (!key->IsConstantOperand() && | 4043 if (!key->IsConstantOperand() && |
| 4045 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), | 4044 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), |
| 4046 elements_kind)) { | 4045 elements_kind)) { |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4223 CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code(); | 4222 CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code(); |
| 4224 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4223 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4225 } | 4224 } |
| 4226 | 4225 |
| 4227 | 4226 |
| 4228 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4227 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
| 4229 Register object = ToRegister(instr->object()); | 4228 Register object = ToRegister(instr->object()); |
| 4230 Register temp = ToRegister(instr->temp()); | 4229 Register temp = ToRegister(instr->temp()); |
| 4231 Label no_memento_found; | 4230 Label no_memento_found; |
| 4232 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); | 4231 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); |
| 4233 DeoptimizeIf(equal, instr->environment()); | 4232 DeoptimizeIf(equal, instr); |
| 4234 __ bind(&no_memento_found); | 4233 __ bind(&no_memento_found); |
| 4235 } | 4234 } |
| 4236 | 4235 |
| 4237 | 4236 |
| 4238 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 4237 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
| 4239 Register object_reg = ToRegister(instr->object()); | 4238 Register object_reg = ToRegister(instr->object()); |
| 4240 | 4239 |
| 4241 Handle<Map> from_map = instr->original_map(); | 4240 Handle<Map> from_map = instr->original_map(); |
| 4242 Handle<Map> to_map = instr->transitioned_map(); | 4241 Handle<Map> to_map = instr->transitioned_map(); |
| 4243 ElementsKind from_kind = instr->from_kind(); | 4242 ElementsKind from_kind = instr->from_kind(); |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4592 __ StoreToSafepointRegisterSlot(reg, eax); | 4591 __ StoreToSafepointRegisterSlot(reg, eax); |
| 4593 } | 4592 } |
| 4594 | 4593 |
| 4595 | 4594 |
| 4596 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4595 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 4597 HChange* hchange = instr->hydrogen(); | 4596 HChange* hchange = instr->hydrogen(); |
| 4598 Register input = ToRegister(instr->value()); | 4597 Register input = ToRegister(instr->value()); |
| 4599 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4598 if (hchange->CheckFlag(HValue::kCanOverflow) && |
| 4600 hchange->value()->CheckFlag(HValue::kUint32)) { | 4599 hchange->value()->CheckFlag(HValue::kUint32)) { |
| 4601 __ test(input, Immediate(0xc0000000)); | 4600 __ test(input, Immediate(0xc0000000)); |
| 4602 DeoptimizeIf(not_zero, instr->environment()); | 4601 DeoptimizeIf(not_zero, instr); |
| 4603 } | 4602 } |
| 4604 __ SmiTag(input); | 4603 __ SmiTag(input); |
| 4605 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4604 if (hchange->CheckFlag(HValue::kCanOverflow) && |
| 4606 !hchange->value()->CheckFlag(HValue::kUint32)) { | 4605 !hchange->value()->CheckFlag(HValue::kUint32)) { |
| 4607 DeoptimizeIf(overflow, instr->environment()); | 4606 DeoptimizeIf(overflow, instr); |
| 4608 } | 4607 } |
| 4609 } | 4608 } |
| 4610 | 4609 |
| 4611 | 4610 |
| 4612 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4611 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
| 4613 LOperand* input = instr->value(); | 4612 LOperand* input = instr->value(); |
| 4614 Register result = ToRegister(input); | 4613 Register result = ToRegister(input); |
| 4615 DCHECK(input->IsRegister() && input->Equals(instr->result())); | 4614 DCHECK(input->IsRegister() && input->Equals(instr->result())); |
| 4616 if (instr->needs_check()) { | 4615 if (instr->needs_check()) { |
| 4617 __ test(result, Immediate(kSmiTagMask)); | 4616 __ test(result, Immediate(kSmiTagMask)); |
| 4618 DeoptimizeIf(not_zero, instr->environment()); | 4617 DeoptimizeIf(not_zero, instr); |
| 4619 } else { | 4618 } else { |
| 4620 __ AssertSmi(result); | 4619 __ AssertSmi(result); |
| 4621 } | 4620 } |
| 4622 __ SmiUntag(result); | 4621 __ SmiUntag(result); |
| 4623 } | 4622 } |
| 4624 | 4623 |
| 4625 | 4624 |
| 4626 void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg, | 4625 void LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg, |
| 4627 Register temp_reg, | 4626 Register temp_reg, X87Register res_reg, |
| 4628 X87Register res_reg, | |
| 4629 bool can_convert_undefined_to_nan, | |
| 4630 bool deoptimize_on_minus_zero, | |
| 4631 LEnvironment* env, | |
| 4632 NumberUntagDMode mode) { | 4627 NumberUntagDMode mode) { |
| 4628 bool can_convert_undefined_to_nan = |
| 4629 instr->hydrogen()->can_convert_undefined_to_nan(); |
| 4630 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); |
| 4631 |
| 4633 Label load_smi, done; | 4632 Label load_smi, done; |
| 4634 | 4633 |
| 4635 X87PrepareToWrite(res_reg); | 4634 X87PrepareToWrite(res_reg); |
| 4636 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { | 4635 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
| 4637 // Smi check. | 4636 // Smi check. |
| 4638 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); | 4637 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); |
| 4639 | 4638 |
| 4640 // Heap number map check. | 4639 // Heap number map check. |
| 4641 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 4640 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 4642 factory()->heap_number_map()); | 4641 factory()->heap_number_map()); |
| 4643 if (!can_convert_undefined_to_nan) { | 4642 if (!can_convert_undefined_to_nan) { |
| 4644 DeoptimizeIf(not_equal, env); | 4643 DeoptimizeIf(not_equal, instr); |
| 4645 } else { | 4644 } else { |
| 4646 Label heap_number, convert; | 4645 Label heap_number, convert; |
| 4647 __ j(equal, &heap_number, Label::kNear); | 4646 __ j(equal, &heap_number, Label::kNear); |
| 4648 | 4647 |
| 4649 // Convert undefined (or hole) to NaN. | 4648 // Convert undefined (or hole) to NaN. |
| 4650 __ cmp(input_reg, factory()->undefined_value()); | 4649 __ cmp(input_reg, factory()->undefined_value()); |
| 4651 DeoptimizeIf(not_equal, env); | 4650 DeoptimizeIf(not_equal, instr); |
| 4652 | 4651 |
| 4653 __ bind(&convert); | 4652 __ bind(&convert); |
| 4654 ExternalReference nan = | 4653 ExternalReference nan = |
| 4655 ExternalReference::address_of_canonical_non_hole_nan(); | 4654 ExternalReference::address_of_canonical_non_hole_nan(); |
| 4656 __ fld_d(Operand::StaticVariable(nan)); | 4655 __ fld_d(Operand::StaticVariable(nan)); |
| 4657 __ jmp(&done, Label::kNear); | 4656 __ jmp(&done, Label::kNear); |
| 4658 | 4657 |
| 4659 __ bind(&heap_number); | 4658 __ bind(&heap_number); |
| 4660 } | 4659 } |
| 4661 // Heap number to x87 conversion. | 4660 // Heap number to x87 conversion. |
| 4662 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4661 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 4663 if (deoptimize_on_minus_zero) { | 4662 if (deoptimize_on_minus_zero) { |
| 4664 __ fldz(); | 4663 __ fldz(); |
| 4665 __ FCmp(); | 4664 __ FCmp(); |
| 4666 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4665 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 4667 __ j(not_zero, &done, Label::kNear); | 4666 __ j(not_zero, &done, Label::kNear); |
| 4668 | 4667 |
| 4669 // Use general purpose registers to check if we have -0.0 | 4668 // Use general purpose registers to check if we have -0.0 |
| 4670 __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 4669 __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
| 4671 __ test(temp_reg, Immediate(HeapNumber::kSignMask)); | 4670 __ test(temp_reg, Immediate(HeapNumber::kSignMask)); |
| 4672 __ j(zero, &done, Label::kNear); | 4671 __ j(zero, &done, Label::kNear); |
| 4673 | 4672 |
| 4674 // Pop FPU stack before deoptimizing. | 4673 // Pop FPU stack before deoptimizing. |
| 4675 __ fstp(0); | 4674 __ fstp(0); |
| 4676 DeoptimizeIf(not_zero, env); | 4675 DeoptimizeIf(not_zero, instr); |
| 4677 } | 4676 } |
| 4678 __ jmp(&done, Label::kNear); | 4677 __ jmp(&done, Label::kNear); |
| 4679 } else { | 4678 } else { |
| 4680 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); | 4679 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); |
| 4681 } | 4680 } |
| 4682 | 4681 |
| 4683 __ bind(&load_smi); | 4682 __ bind(&load_smi); |
| 4684 // Clobbering a temp is faster than re-tagging the | 4683 // Clobbering a temp is faster than re-tagging the |
| 4685 // input register since we avoid dependencies. | 4684 // input register since we avoid dependencies. |
| 4686 __ mov(temp_reg, input_reg); | 4685 __ mov(temp_reg, input_reg); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4720 | 4719 |
| 4721 __ bind(&check_bools); | 4720 __ bind(&check_bools); |
| 4722 __ cmp(input_reg, factory()->true_value()); | 4721 __ cmp(input_reg, factory()->true_value()); |
| 4723 __ j(not_equal, &check_false, Label::kNear); | 4722 __ j(not_equal, &check_false, Label::kNear); |
| 4724 __ Move(input_reg, Immediate(1)); | 4723 __ Move(input_reg, Immediate(1)); |
| 4725 __ jmp(done); | 4724 __ jmp(done); |
| 4726 | 4725 |
| 4727 __ bind(&check_false); | 4726 __ bind(&check_false); |
| 4728 __ cmp(input_reg, factory()->false_value()); | 4727 __ cmp(input_reg, factory()->false_value()); |
| 4729 __ RecordComment("Deferred TaggedToI: cannot truncate"); | 4728 __ RecordComment("Deferred TaggedToI: cannot truncate"); |
| 4730 DeoptimizeIf(not_equal, instr->environment()); | 4729 DeoptimizeIf(not_equal, instr); |
| 4731 __ Move(input_reg, Immediate(0)); | 4730 __ Move(input_reg, Immediate(0)); |
| 4732 } else { | 4731 } else { |
| 4733 // TODO(olivf) Converting a number on the fpu is actually quite slow. We | 4732 // TODO(olivf) Converting a number on the fpu is actually quite slow. We |
| 4734 // should first try a fast conversion and then bailout to this slow case. | 4733 // should first try a fast conversion and then bailout to this slow case. |
| 4735 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 4734 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 4736 isolate()->factory()->heap_number_map()); | 4735 isolate()->factory()->heap_number_map()); |
| 4737 __ RecordComment("Deferred TaggedToI: not a heap number"); | 4736 __ RecordComment("Deferred TaggedToI: not a heap number"); |
| 4738 DeoptimizeIf(not_equal, instr->environment()); | 4737 DeoptimizeIf(not_equal, instr); |
| 4739 | 4738 |
| 4740 __ sub(esp, Immediate(kPointerSize)); | 4739 __ sub(esp, Immediate(kPointerSize)); |
| 4741 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4740 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 4742 | 4741 |
| 4743 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { | 4742 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { |
| 4744 Label no_precision_lost, not_nan, zero_check; | 4743 Label no_precision_lost, not_nan, zero_check; |
| 4745 __ fld(0); | 4744 __ fld(0); |
| 4746 | 4745 |
| 4747 __ fist_s(MemOperand(esp, 0)); | 4746 __ fist_s(MemOperand(esp, 0)); |
| 4748 __ fild_s(MemOperand(esp, 0)); | 4747 __ fild_s(MemOperand(esp, 0)); |
| 4749 __ FCmp(); | 4748 __ FCmp(); |
| 4750 __ pop(input_reg); | 4749 __ pop(input_reg); |
| 4751 | 4750 |
| 4752 __ j(equal, &no_precision_lost, Label::kNear); | 4751 __ j(equal, &no_precision_lost, Label::kNear); |
| 4753 __ fstp(0); | 4752 __ fstp(0); |
| 4754 __ RecordComment("Deferred TaggedToI: lost precision"); | 4753 __ RecordComment("Deferred TaggedToI: lost precision"); |
| 4755 DeoptimizeIf(no_condition, instr->environment()); | 4754 DeoptimizeIf(no_condition, instr); |
| 4756 __ bind(&no_precision_lost); | 4755 __ bind(&no_precision_lost); |
| 4757 | 4756 |
| 4758 __ j(parity_odd, ¬_nan); | 4757 __ j(parity_odd, ¬_nan); |
| 4759 __ fstp(0); | 4758 __ fstp(0); |
| 4760 __ RecordComment("Deferred TaggedToI: NaN"); | 4759 __ RecordComment("Deferred TaggedToI: NaN"); |
| 4761 DeoptimizeIf(no_condition, instr->environment()); | 4760 DeoptimizeIf(no_condition, instr); |
| 4762 __ bind(¬_nan); | 4761 __ bind(¬_nan); |
| 4763 | 4762 |
| 4764 __ test(input_reg, Operand(input_reg)); | 4763 __ test(input_reg, Operand(input_reg)); |
| 4765 __ j(zero, &zero_check, Label::kNear); | 4764 __ j(zero, &zero_check, Label::kNear); |
| 4766 __ fstp(0); | 4765 __ fstp(0); |
| 4767 __ jmp(done); | 4766 __ jmp(done); |
| 4768 | 4767 |
| 4769 __ bind(&zero_check); | 4768 __ bind(&zero_check); |
| 4770 // To check for minus zero, we load the value again as float, and check | 4769 // To check for minus zero, we load the value again as float, and check |
| 4771 // if that is still 0. | 4770 // if that is still 0. |
| 4772 __ sub(esp, Immediate(kPointerSize)); | 4771 __ sub(esp, Immediate(kPointerSize)); |
| 4773 __ fstp_s(Operand(esp, 0)); | 4772 __ fstp_s(Operand(esp, 0)); |
| 4774 __ pop(input_reg); | 4773 __ pop(input_reg); |
| 4775 __ test(input_reg, Operand(input_reg)); | 4774 __ test(input_reg, Operand(input_reg)); |
| 4776 __ RecordComment("Deferred TaggedToI: minus zero"); | 4775 __ RecordComment("Deferred TaggedToI: minus zero"); |
| 4777 DeoptimizeIf(not_zero, instr->environment()); | 4776 DeoptimizeIf(not_zero, instr); |
| 4778 } else { | 4777 } else { |
| 4779 __ fist_s(MemOperand(esp, 0)); | 4778 __ fist_s(MemOperand(esp, 0)); |
| 4780 __ fild_s(MemOperand(esp, 0)); | 4779 __ fild_s(MemOperand(esp, 0)); |
| 4781 __ FCmp(); | 4780 __ FCmp(); |
| 4782 __ pop(input_reg); | 4781 __ pop(input_reg); |
| 4783 __ RecordComment("Deferred TaggedToI: lost precision"); | 4782 __ RecordComment("Deferred TaggedToI: lost precision"); |
| 4784 DeoptimizeIf(not_equal, instr->environment()); | 4783 DeoptimizeIf(not_equal, instr); |
| 4785 __ RecordComment("Deferred TaggedToI: NaN"); | 4784 __ RecordComment("Deferred TaggedToI: NaN"); |
| 4786 DeoptimizeIf(parity_even, instr->environment()); | 4785 DeoptimizeIf(parity_even, instr); |
| 4787 } | 4786 } |
| 4788 } | 4787 } |
| 4789 } | 4788 } |
| 4790 | 4789 |
| 4791 | 4790 |
| 4792 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 4791 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 4793 class DeferredTaggedToI FINAL : public LDeferredCode { | 4792 class DeferredTaggedToI FINAL : public LDeferredCode { |
| 4794 public: | 4793 public: |
| 4795 DeferredTaggedToI(LCodeGen* codegen, | 4794 DeferredTaggedToI(LCodeGen* codegen, |
| 4796 LTaggedToI* instr, | 4795 LTaggedToI* instr, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4828 | 4827 |
| 4829 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 4828 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 4830 LOperand* input = instr->value(); | 4829 LOperand* input = instr->value(); |
| 4831 DCHECK(input->IsRegister()); | 4830 DCHECK(input->IsRegister()); |
| 4832 LOperand* temp = instr->temp(); | 4831 LOperand* temp = instr->temp(); |
| 4833 DCHECK(temp->IsRegister()); | 4832 DCHECK(temp->IsRegister()); |
| 4834 LOperand* result = instr->result(); | 4833 LOperand* result = instr->result(); |
| 4835 DCHECK(result->IsDoubleRegister()); | 4834 DCHECK(result->IsDoubleRegister()); |
| 4836 | 4835 |
| 4837 Register input_reg = ToRegister(input); | 4836 Register input_reg = ToRegister(input); |
| 4838 bool deoptimize_on_minus_zero = | |
| 4839 instr->hydrogen()->deoptimize_on_minus_zero(); | |
| 4840 Register temp_reg = ToRegister(temp); | 4837 Register temp_reg = ToRegister(temp); |
| 4841 | 4838 |
| 4842 HValue* value = instr->hydrogen()->value(); | 4839 HValue* value = instr->hydrogen()->value(); |
| 4843 NumberUntagDMode mode = value->representation().IsSmi() | 4840 NumberUntagDMode mode = value->representation().IsSmi() |
| 4844 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; | 4841 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; |
| 4845 | 4842 |
| 4846 EmitNumberUntagDNoSSE2(input_reg, | 4843 EmitNumberUntagDNoSSE2(instr, input_reg, temp_reg, ToX87Register(result), |
| 4847 temp_reg, | |
| 4848 ToX87Register(result), | |
| 4849 instr->hydrogen()->can_convert_undefined_to_nan(), | |
| 4850 deoptimize_on_minus_zero, | |
| 4851 instr->environment(), | |
| 4852 mode); | 4844 mode); |
| 4853 } | 4845 } |
| 4854 | 4846 |
| 4855 | 4847 |
| 4856 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 4848 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 4857 LOperand* input = instr->value(); | 4849 LOperand* input = instr->value(); |
| 4858 DCHECK(input->IsDoubleRegister()); | 4850 DCHECK(input->IsDoubleRegister()); |
| 4859 LOperand* result = instr->result(); | 4851 LOperand* result = instr->result(); |
| 4860 DCHECK(result->IsRegister()); | 4852 DCHECK(result->IsRegister()); |
| 4861 Register result_reg = ToRegister(result); | 4853 Register result_reg = ToRegister(result); |
| 4862 | 4854 |
| 4863 if (instr->truncating()) { | 4855 if (instr->truncating()) { |
| 4864 X87Register input_reg = ToX87Register(input); | 4856 X87Register input_reg = ToX87Register(input); |
| 4865 X87Fxch(input_reg); | 4857 X87Fxch(input_reg); |
| 4866 __ TruncateX87TOSToI(result_reg); | 4858 __ TruncateX87TOSToI(result_reg); |
| 4867 } else { | 4859 } else { |
| 4868 Label bailout, done; | 4860 Label bailout, done; |
| 4869 X87Register input_reg = ToX87Register(input); | 4861 X87Register input_reg = ToX87Register(input); |
| 4870 X87Fxch(input_reg); | 4862 X87Fxch(input_reg); |
| 4871 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), | 4863 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), |
| 4872 &bailout, Label::kNear); | 4864 &bailout, Label::kNear); |
| 4873 __ jmp(&done, Label::kNear); | 4865 __ jmp(&done, Label::kNear); |
| 4874 __ bind(&bailout); | 4866 __ bind(&bailout); |
| 4875 DeoptimizeIf(no_condition, instr->environment()); | 4867 DeoptimizeIf(no_condition, instr); |
| 4876 __ bind(&done); | 4868 __ bind(&done); |
| 4877 } | 4869 } |
| 4878 } | 4870 } |
| 4879 | 4871 |
| 4880 | 4872 |
| 4881 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { | 4873 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
| 4882 LOperand* input = instr->value(); | 4874 LOperand* input = instr->value(); |
| 4883 DCHECK(input->IsDoubleRegister()); | 4875 DCHECK(input->IsDoubleRegister()); |
| 4884 LOperand* result = instr->result(); | 4876 LOperand* result = instr->result(); |
| 4885 DCHECK(result->IsRegister()); | 4877 DCHECK(result->IsRegister()); |
| 4886 Register result_reg = ToRegister(result); | 4878 Register result_reg = ToRegister(result); |
| 4887 | 4879 |
| 4888 Label bailout, done; | 4880 Label bailout, done; |
| 4889 X87Register input_reg = ToX87Register(input); | 4881 X87Register input_reg = ToX87Register(input); |
| 4890 X87Fxch(input_reg); | 4882 X87Fxch(input_reg); |
| 4891 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), | 4883 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), |
| 4892 &bailout, Label::kNear); | 4884 &bailout, Label::kNear); |
| 4893 __ jmp(&done, Label::kNear); | 4885 __ jmp(&done, Label::kNear); |
| 4894 __ bind(&bailout); | 4886 __ bind(&bailout); |
| 4895 DeoptimizeIf(no_condition, instr->environment()); | 4887 DeoptimizeIf(no_condition, instr); |
| 4896 __ bind(&done); | 4888 __ bind(&done); |
| 4897 | 4889 |
| 4898 __ SmiTag(result_reg); | 4890 __ SmiTag(result_reg); |
| 4899 DeoptimizeIf(overflow, instr->environment()); | 4891 DeoptimizeIf(overflow, instr); |
| 4900 } | 4892 } |
| 4901 | 4893 |
| 4902 | 4894 |
| 4903 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 4895 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
| 4904 LOperand* input = instr->value(); | 4896 LOperand* input = instr->value(); |
| 4905 __ test(ToOperand(input), Immediate(kSmiTagMask)); | 4897 __ test(ToOperand(input), Immediate(kSmiTagMask)); |
| 4906 DeoptimizeIf(not_zero, instr->environment()); | 4898 DeoptimizeIf(not_zero, instr); |
| 4907 } | 4899 } |
| 4908 | 4900 |
| 4909 | 4901 |
| 4910 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 4902 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
| 4911 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 4903 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
| 4912 LOperand* input = instr->value(); | 4904 LOperand* input = instr->value(); |
| 4913 __ test(ToOperand(input), Immediate(kSmiTagMask)); | 4905 __ test(ToOperand(input), Immediate(kSmiTagMask)); |
| 4914 DeoptimizeIf(zero, instr->environment()); | 4906 DeoptimizeIf(zero, instr); |
| 4915 } | 4907 } |
| 4916 } | 4908 } |
| 4917 | 4909 |
| 4918 | 4910 |
| 4919 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 4911 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
| 4920 Register input = ToRegister(instr->value()); | 4912 Register input = ToRegister(instr->value()); |
| 4921 Register temp = ToRegister(instr->temp()); | 4913 Register temp = ToRegister(instr->temp()); |
| 4922 | 4914 |
| 4923 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); | 4915 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); |
| 4924 | 4916 |
| 4925 if (instr->hydrogen()->is_interval_check()) { | 4917 if (instr->hydrogen()->is_interval_check()) { |
| 4926 InstanceType first; | 4918 InstanceType first; |
| 4927 InstanceType last; | 4919 InstanceType last; |
| 4928 instr->hydrogen()->GetCheckInterval(&first, &last); | 4920 instr->hydrogen()->GetCheckInterval(&first, &last); |
| 4929 | 4921 |
| 4930 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), | 4922 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), |
| 4931 static_cast<int8_t>(first)); | 4923 static_cast<int8_t>(first)); |
| 4932 | 4924 |
| 4933 // If there is only one type in the interval check for equality. | 4925 // If there is only one type in the interval check for equality. |
| 4934 if (first == last) { | 4926 if (first == last) { |
| 4935 DeoptimizeIf(not_equal, instr->environment()); | 4927 DeoptimizeIf(not_equal, instr); |
| 4936 } else { | 4928 } else { |
| 4937 DeoptimizeIf(below, instr->environment()); | 4929 DeoptimizeIf(below, instr); |
| 4938 // Omit check for the last type. | 4930 // Omit check for the last type. |
| 4939 if (last != LAST_TYPE) { | 4931 if (last != LAST_TYPE) { |
| 4940 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), | 4932 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), |
| 4941 static_cast<int8_t>(last)); | 4933 static_cast<int8_t>(last)); |
| 4942 DeoptimizeIf(above, instr->environment()); | 4934 DeoptimizeIf(above, instr); |
| 4943 } | 4935 } |
| 4944 } | 4936 } |
| 4945 } else { | 4937 } else { |
| 4946 uint8_t mask; | 4938 uint8_t mask; |
| 4947 uint8_t tag; | 4939 uint8_t tag; |
| 4948 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); | 4940 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); |
| 4949 | 4941 |
| 4950 if (base::bits::IsPowerOfTwo32(mask)) { | 4942 if (base::bits::IsPowerOfTwo32(mask)) { |
| 4951 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); | 4943 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); |
| 4952 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask); | 4944 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask); |
| 4953 DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment()); | 4945 DeoptimizeIf(tag == 0 ? not_zero : zero, instr); |
| 4954 } else { | 4946 } else { |
| 4955 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); | 4947 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); |
| 4956 __ and_(temp, mask); | 4948 __ and_(temp, mask); |
| 4957 __ cmp(temp, tag); | 4949 __ cmp(temp, tag); |
| 4958 DeoptimizeIf(not_equal, instr->environment()); | 4950 DeoptimizeIf(not_equal, instr); |
| 4959 } | 4951 } |
| 4960 } | 4952 } |
| 4961 } | 4953 } |
| 4962 | 4954 |
| 4963 | 4955 |
| 4964 void LCodeGen::DoCheckValue(LCheckValue* instr) { | 4956 void LCodeGen::DoCheckValue(LCheckValue* instr) { |
| 4965 Handle<HeapObject> object = instr->hydrogen()->object().handle(); | 4957 Handle<HeapObject> object = instr->hydrogen()->object().handle(); |
| 4966 if (instr->hydrogen()->object_in_new_space()) { | 4958 if (instr->hydrogen()->object_in_new_space()) { |
| 4967 Register reg = ToRegister(instr->value()); | 4959 Register reg = ToRegister(instr->value()); |
| 4968 Handle<Cell> cell = isolate()->factory()->NewCell(object); | 4960 Handle<Cell> cell = isolate()->factory()->NewCell(object); |
| 4969 __ cmp(reg, Operand::ForCell(cell)); | 4961 __ cmp(reg, Operand::ForCell(cell)); |
| 4970 } else { | 4962 } else { |
| 4971 Operand operand = ToOperand(instr->value()); | 4963 Operand operand = ToOperand(instr->value()); |
| 4972 __ cmp(operand, object); | 4964 __ cmp(operand, object); |
| 4973 } | 4965 } |
| 4974 DeoptimizeIf(not_equal, instr->environment()); | 4966 DeoptimizeIf(not_equal, instr); |
| 4975 } | 4967 } |
| 4976 | 4968 |
| 4977 | 4969 |
| 4978 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 4970 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
| 4979 { | 4971 { |
| 4980 PushSafepointRegistersScope scope(this); | 4972 PushSafepointRegistersScope scope(this); |
| 4981 __ push(object); | 4973 __ push(object); |
| 4982 __ xor_(esi, esi); | 4974 __ xor_(esi, esi); |
| 4983 __ CallRuntime(Runtime::kTryMigrateInstance); | 4975 __ CallRuntime(Runtime::kTryMigrateInstance); |
| 4984 RecordSafepointWithRegisters( | 4976 RecordSafepointWithRegisters( |
| 4985 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); | 4977 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); |
| 4986 | 4978 |
| 4987 __ test(eax, Immediate(kSmiTagMask)); | 4979 __ test(eax, Immediate(kSmiTagMask)); |
| 4988 } | 4980 } |
| 4989 DeoptimizeIf(zero, instr->environment()); | 4981 DeoptimizeIf(zero, instr); |
| 4990 } | 4982 } |
| 4991 | 4983 |
| 4992 | 4984 |
| 4993 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 4985 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 4994 class DeferredCheckMaps FINAL : public LDeferredCode { | 4986 class DeferredCheckMaps FINAL : public LDeferredCode { |
| 4995 public: | 4987 public: |
| 4996 DeferredCheckMaps(LCodeGen* codegen, | 4988 DeferredCheckMaps(LCodeGen* codegen, |
| 4997 LCheckMaps* instr, | 4989 LCheckMaps* instr, |
| 4998 Register object, | 4990 Register object, |
| 4999 const X87Stack& x87_stack) | 4991 const X87Stack& x87_stack) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5035 Handle<Map> map = maps->at(i).handle(); | 5027 Handle<Map> map = maps->at(i).handle(); |
| 5036 __ CompareMap(reg, map); | 5028 __ CompareMap(reg, map); |
| 5037 __ j(equal, &success, Label::kNear); | 5029 __ j(equal, &success, Label::kNear); |
| 5038 } | 5030 } |
| 5039 | 5031 |
| 5040 Handle<Map> map = maps->at(maps->size() - 1).handle(); | 5032 Handle<Map> map = maps->at(maps->size() - 1).handle(); |
| 5041 __ CompareMap(reg, map); | 5033 __ CompareMap(reg, map); |
| 5042 if (instr->hydrogen()->HasMigrationTarget()) { | 5034 if (instr->hydrogen()->HasMigrationTarget()) { |
| 5043 __ j(not_equal, deferred->entry()); | 5035 __ j(not_equal, deferred->entry()); |
| 5044 } else { | 5036 } else { |
| 5045 DeoptimizeIf(not_equal, instr->environment()); | 5037 DeoptimizeIf(not_equal, instr); |
| 5046 } | 5038 } |
| 5047 | 5039 |
| 5048 __ bind(&success); | 5040 __ bind(&success); |
| 5049 } | 5041 } |
| 5050 | 5042 |
| 5051 | 5043 |
| 5052 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 5044 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
| 5053 UNREACHABLE(); | 5045 UNREACHABLE(); |
| 5054 } | 5046 } |
| 5055 | 5047 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 5073 __ JumpIfSmi(input_reg, &is_smi); | 5065 __ JumpIfSmi(input_reg, &is_smi); |
| 5074 | 5066 |
| 5075 // Check for heap number | 5067 // Check for heap number |
| 5076 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 5068 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 5077 factory()->heap_number_map()); | 5069 factory()->heap_number_map()); |
| 5078 __ j(equal, &heap_number, Label::kNear); | 5070 __ j(equal, &heap_number, Label::kNear); |
| 5079 | 5071 |
| 5080 // Check for undefined. Undefined is converted to zero for clamping | 5072 // Check for undefined. Undefined is converted to zero for clamping |
| 5081 // conversions. | 5073 // conversions. |
| 5082 __ cmp(input_reg, factory()->undefined_value()); | 5074 __ cmp(input_reg, factory()->undefined_value()); |
| 5083 DeoptimizeIf(not_equal, instr->environment()); | 5075 DeoptimizeIf(not_equal, instr); |
| 5084 __ jmp(&zero_result, Label::kNear); | 5076 __ jmp(&zero_result, Label::kNear); |
| 5085 | 5077 |
| 5086 // Heap number | 5078 // Heap number |
| 5087 __ bind(&heap_number); | 5079 __ bind(&heap_number); |
| 5088 | 5080 |
| 5089 // Surprisingly, all of the hand-crafted bit-manipulations below are much | 5081 // Surprisingly, all of the hand-crafted bit-manipulations below are much |
| 5090 // faster than the x86 FPU built-in instruction, especially since "banker's | 5082 // faster than the x86 FPU built-in instruction, especially since "banker's |
| 5091 // rounding" would be additionally very expensive | 5083 // rounding" would be additionally very expensive |
| 5092 | 5084 |
| 5093 // Get exponent word. | 5085 // Get exponent word. |
| (...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5530 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 5522 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
| 5531 Deoptimizer::BailoutType type = instr->hydrogen()->type(); | 5523 Deoptimizer::BailoutType type = instr->hydrogen()->type(); |
| 5532 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the | 5524 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the |
| 5533 // needed return address), even though the implementation of LAZY and EAGER is | 5525 // needed return address), even though the implementation of LAZY and EAGER is |
| 5534 // now identical. When LAZY is eventually completely folded into EAGER, remove | 5526 // now identical. When LAZY is eventually completely folded into EAGER, remove |
| 5535 // the special case below. | 5527 // the special case below. |
| 5536 if (info()->IsStub() && type == Deoptimizer::EAGER) { | 5528 if (info()->IsStub() && type == Deoptimizer::EAGER) { |
| 5537 type = Deoptimizer::LAZY; | 5529 type = Deoptimizer::LAZY; |
| 5538 } | 5530 } |
| 5539 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); | 5531 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); |
| 5540 DeoptimizeIf(no_condition, instr->environment(), type); | 5532 DeoptimizeIf(no_condition, instr, type); |
| 5541 } | 5533 } |
| 5542 | 5534 |
| 5543 | 5535 |
| 5544 void LCodeGen::DoDummy(LDummy* instr) { | 5536 void LCodeGen::DoDummy(LDummy* instr) { |
| 5545 // Nothing to see here, move on! | 5537 // Nothing to see here, move on! |
| 5546 } | 5538 } |
| 5547 | 5539 |
| 5548 | 5540 |
| 5549 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5541 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
| 5550 // Nothing to see here, move on! | 5542 // Nothing to see here, move on! |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5627 DCHECK(!environment->HasBeenRegistered()); | 5619 DCHECK(!environment->HasBeenRegistered()); |
| 5628 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 5620 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 5629 | 5621 |
| 5630 GenerateOsrPrologue(); | 5622 GenerateOsrPrologue(); |
| 5631 } | 5623 } |
| 5632 | 5624 |
| 5633 | 5625 |
| 5634 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { | 5626 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
| 5635 DCHECK(ToRegister(instr->context()).is(esi)); | 5627 DCHECK(ToRegister(instr->context()).is(esi)); |
| 5636 __ cmp(eax, isolate()->factory()->undefined_value()); | 5628 __ cmp(eax, isolate()->factory()->undefined_value()); |
| 5637 DeoptimizeIf(equal, instr->environment()); | 5629 DeoptimizeIf(equal, instr); |
| 5638 | 5630 |
| 5639 __ cmp(eax, isolate()->factory()->null_value()); | 5631 __ cmp(eax, isolate()->factory()->null_value()); |
| 5640 DeoptimizeIf(equal, instr->environment()); | 5632 DeoptimizeIf(equal, instr); |
| 5641 | 5633 |
| 5642 __ test(eax, Immediate(kSmiTagMask)); | 5634 __ test(eax, Immediate(kSmiTagMask)); |
| 5643 DeoptimizeIf(zero, instr->environment()); | 5635 DeoptimizeIf(zero, instr); |
| 5644 | 5636 |
| 5645 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 5637 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); |
| 5646 __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx); | 5638 __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx); |
| 5647 DeoptimizeIf(below_equal, instr->environment()); | 5639 DeoptimizeIf(below_equal, instr); |
| 5648 | 5640 |
| 5649 Label use_cache, call_runtime; | 5641 Label use_cache, call_runtime; |
| 5650 __ CheckEnumCache(&call_runtime); | 5642 __ CheckEnumCache(&call_runtime); |
| 5651 | 5643 |
| 5652 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); | 5644 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); |
| 5653 __ jmp(&use_cache, Label::kNear); | 5645 __ jmp(&use_cache, Label::kNear); |
| 5654 | 5646 |
| 5655 // Get the set of properties to enumerate. | 5647 // Get the set of properties to enumerate. |
| 5656 __ bind(&call_runtime); | 5648 __ bind(&call_runtime); |
| 5657 __ push(eax); | 5649 __ push(eax); |
| 5658 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); | 5650 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); |
| 5659 | 5651 |
| 5660 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 5652 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
| 5661 isolate()->factory()->meta_map()); | 5653 isolate()->factory()->meta_map()); |
| 5662 DeoptimizeIf(not_equal, instr->environment()); | 5654 DeoptimizeIf(not_equal, instr); |
| 5663 __ bind(&use_cache); | 5655 __ bind(&use_cache); |
| 5664 } | 5656 } |
| 5665 | 5657 |
| 5666 | 5658 |
| 5667 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { | 5659 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { |
| 5668 Register map = ToRegister(instr->map()); | 5660 Register map = ToRegister(instr->map()); |
| 5669 Register result = ToRegister(instr->result()); | 5661 Register result = ToRegister(instr->result()); |
| 5670 Label load_cache, done; | 5662 Label load_cache, done; |
| 5671 __ EnumLength(result, map); | 5663 __ EnumLength(result, map); |
| 5672 __ cmp(result, Immediate(Smi::FromInt(0))); | 5664 __ cmp(result, Immediate(Smi::FromInt(0))); |
| 5673 __ j(not_equal, &load_cache, Label::kNear); | 5665 __ j(not_equal, &load_cache, Label::kNear); |
| 5674 __ mov(result, isolate()->factory()->empty_fixed_array()); | 5666 __ mov(result, isolate()->factory()->empty_fixed_array()); |
| 5675 __ jmp(&done, Label::kNear); | 5667 __ jmp(&done, Label::kNear); |
| 5676 | 5668 |
| 5677 __ bind(&load_cache); | 5669 __ bind(&load_cache); |
| 5678 __ LoadInstanceDescriptors(map, result); | 5670 __ LoadInstanceDescriptors(map, result); |
| 5679 __ mov(result, | 5671 __ mov(result, |
| 5680 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); | 5672 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); |
| 5681 __ mov(result, | 5673 __ mov(result, |
| 5682 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); | 5674 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); |
| 5683 __ bind(&done); | 5675 __ bind(&done); |
| 5684 __ test(result, result); | 5676 __ test(result, result); |
| 5685 DeoptimizeIf(equal, instr->environment()); | 5677 DeoptimizeIf(equal, instr); |
| 5686 } | 5678 } |
| 5687 | 5679 |
| 5688 | 5680 |
| 5689 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { | 5681 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { |
| 5690 Register object = ToRegister(instr->value()); | 5682 Register object = ToRegister(instr->value()); |
| 5691 __ cmp(ToRegister(instr->map()), | 5683 __ cmp(ToRegister(instr->map()), |
| 5692 FieldOperand(object, HeapObject::kMapOffset)); | 5684 FieldOperand(object, HeapObject::kMapOffset)); |
| 5693 DeoptimizeIf(not_equal, instr->environment()); | 5685 DeoptimizeIf(not_equal, instr); |
| 5694 } | 5686 } |
| 5695 | 5687 |
| 5696 | 5688 |
| 5697 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, | 5689 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, |
| 5698 Register object, | 5690 Register object, |
| 5699 Register index) { | 5691 Register index) { |
| 5700 PushSafepointRegistersScope scope(this); | 5692 PushSafepointRegistersScope scope(this); |
| 5701 __ push(object); | 5693 __ push(object); |
| 5702 __ push(index); | 5694 __ push(index); |
| 5703 __ xor_(esi, esi); | 5695 __ xor_(esi, esi); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5778 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 5770 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
| 5779 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5771 RecordSafepoint(Safepoint::kNoLazyDeopt); |
| 5780 } | 5772 } |
| 5781 | 5773 |
| 5782 | 5774 |
| 5783 #undef __ | 5775 #undef __ |
| 5784 | 5776 |
| 5785 } } // namespace v8::internal | 5777 } } // namespace v8::internal |
| 5786 | 5778 |
| 5787 #endif // V8_TARGET_ARCH_X87 | 5779 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |