Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 703 } | 703 } |
| 704 | 704 |
| 705 | 705 |
| 706 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { | 706 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { |
| 707 return AssignEnvironment(new(zone()) LDeoptimize); | 707 return AssignEnvironment(new(zone()) LDeoptimize); |
| 708 } | 708 } |
| 709 | 709 |
| 710 | 710 |
| 711 LInstruction* LChunkBuilder::DoShift(Token::Value op, | 711 LInstruction* LChunkBuilder::DoShift(Token::Value op, |
| 712 HBitwiseBinaryOperation* instr) { | 712 HBitwiseBinaryOperation* instr) { |
| 713 if (instr->representation().IsTagged()) { | 713 if (instr->representation().IsSmiOrInteger32()) { |
| 714 ASSERT(instr->left()->representation().IsTagged()); | 714 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 715 ASSERT(instr->right()->representation().IsTagged()); | 715 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 716 LOperand* left = UseRegisterAtStart(instr->left()); | |
| 716 | 717 |
| 717 LOperand* left = UseFixed(instr->left(), r1); | 718 HValue* right_value = instr->right(); |
| 718 LOperand* right = UseFixed(instr->right(), r0); | 719 LOperand* right = NULL; |
| 719 LArithmeticT* result = new(zone()) LArithmeticT(op, left, right); | 720 int constant_value = 0; |
| 720 return MarkAsCall(DefineFixed(result, r0), instr); | 721 bool does_deopt = false; |
| 722 if (right_value->IsConstant()) { | |
| 723 HConstant* constant = HConstant::cast(right_value); | |
| 724 right = chunk_->DefineConstantOperand(constant); | |
| 725 constant_value = constant->Integer32Value() & 0x1f; | |
| 726 // Left shifts can deoptimize if we shift by > 0 and the result cannot be | |
| 727 // truncated to smi. | |
| 728 if (instr->representation().IsSmi() && constant_value > 0) { | |
| 729 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi); | |
| 730 } | |
| 731 } else { | |
| 732 right = UseRegisterAtStart(right_value); | |
| 733 } | |
| 734 | |
| 735 // Shift operations can only deoptimize if we do a logical shift | |
| 736 // by 0 and the result cannot be truncated to int32. | |
| 737 if (op == Token::SHR && constant_value == 0) { | |
| 738 if (FLAG_opt_safe_uint32_operations) { | |
| 739 does_deopt = !instr->CheckFlag(HInstruction::kUint32); | |
| 740 } else { | |
| 741 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); | |
| 742 } | |
| 743 } | |
| 744 | |
| 745 LInstruction* result = | |
| 746 DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt)); | |
| 747 return does_deopt ? AssignEnvironment(result) : result; | |
| 748 } else { | |
| 749 return DoArithmeticT(op, instr); | |
| 721 } | 750 } |
| 722 | |
| 723 ASSERT(instr->representation().IsSmiOrInteger32()); | |
| 724 ASSERT(instr->left()->representation().Equals(instr->representation())); | |
| 725 ASSERT(instr->right()->representation().Equals(instr->representation())); | |
| 726 LOperand* left = UseRegisterAtStart(instr->left()); | |
| 727 | |
| 728 HValue* right_value = instr->right(); | |
| 729 LOperand* right = NULL; | |
| 730 int constant_value = 0; | |
| 731 bool does_deopt = false; | |
| 732 if (right_value->IsConstant()) { | |
| 733 HConstant* constant = HConstant::cast(right_value); | |
| 734 right = chunk_->DefineConstantOperand(constant); | |
| 735 constant_value = constant->Integer32Value() & 0x1f; | |
| 736 // Left shifts can deoptimize if we shift by > 0 and the result cannot be | |
| 737 // truncated to smi. | |
| 738 if (instr->representation().IsSmi() && constant_value > 0) { | |
| 739 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi); | |
| 740 } | |
| 741 } else { | |
| 742 right = UseRegisterAtStart(right_value); | |
| 743 } | |
| 744 | |
| 745 // Shift operations can only deoptimize if we do a logical shift | |
| 746 // by 0 and the result cannot be truncated to int32. | |
| 747 if (op == Token::SHR && constant_value == 0) { | |
| 748 if (FLAG_opt_safe_uint32_operations) { | |
| 749 does_deopt = !instr->CheckFlag(HInstruction::kUint32); | |
| 750 } else { | |
| 751 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); | |
| 752 } | |
| 753 } | |
| 754 | |
| 755 LInstruction* result = | |
| 756 DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt)); | |
| 757 return does_deopt ? AssignEnvironment(result) : result; | |
| 758 } | 751 } |
| 759 | 752 |
| 760 | 753 |
| 761 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, | 754 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, |
| 762 HArithmeticBinaryOperation* instr) { | 755 HArithmeticBinaryOperation* instr) { |
| 763 ASSERT(instr->representation().IsDouble()); | 756 ASSERT(instr->representation().IsDouble()); |
| 764 ASSERT(instr->left()->representation().IsDouble()); | 757 ASSERT(instr->left()->representation().IsDouble()); |
| 765 ASSERT(instr->right()->representation().IsDouble()); | 758 ASSERT(instr->right()->representation().IsDouble()); |
| 766 ASSERT(op != Token::MOD); | 759 LOperand* left = (op == Token::MOD) |
|
Sven Panne
2013/09/16 13:10:32
Refactor this into
if (op == Token::MOD) {
...
}
| |
| 767 LOperand* left = UseRegisterAtStart(instr->left()); | 760 ? UseFixedDouble(instr->left(), d1) |
| 768 LOperand* right = UseRegisterAtStart(instr->right()); | 761 : UseRegisterAtStart(instr->left()); |
| 762 LOperand* right = (op == Token::MOD) | |
| 763 ? UseFixedDouble(instr->right(), d2) | |
| 764 : UseRegisterAtStart(instr->right()); | |
| 769 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); | 765 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
| 766 | |
| 767 // We call a C function for double modulo. It can't trigger a GC. We need | |
| 768 // to use fixed result register for the call. | |
| 769 // TODO(fschneider): Allow any register as input registers. | |
| 770 if (op == Token::MOD) return MarkAsCall(DefineFixedDouble(result, d1), instr); | |
| 770 return DefineAsRegister(result); | 771 return DefineAsRegister(result); |
| 771 } | 772 } |
| 772 | 773 |
| 773 | 774 |
| 774 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, | 775 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
| 775 HArithmeticBinaryOperation* instr) { | 776 HBinaryOperation* instr) { |
| 776 ASSERT(op == Token::ADD || | |
| 777 op == Token::DIV || | |
| 778 op == Token::MOD || | |
| 779 op == Token::MUL || | |
| 780 op == Token::SUB); | |
| 781 HValue* left = instr->left(); | 777 HValue* left = instr->left(); |
| 782 HValue* right = instr->right(); | 778 HValue* right = instr->right(); |
| 783 ASSERT(left->representation().IsTagged()); | 779 ASSERT(left->representation().IsTagged()); |
| 784 ASSERT(right->representation().IsTagged()); | 780 ASSERT(right->representation().IsTagged()); |
| 785 LOperand* left_operand = UseFixed(left, r1); | 781 LOperand* left_operand = UseFixed(left, r1); |
| 786 LOperand* right_operand = UseFixed(right, r0); | 782 LOperand* right_operand = UseFixed(right, r0); |
| 787 LArithmeticT* result = | 783 LArithmeticT* result = |
| 788 new(zone()) LArithmeticT(op, left_operand, right_operand); | 784 new(zone()) LArithmeticT(op, left_operand, right_operand); |
| 789 return MarkAsCall(DefineFixed(result, r0), instr); | 785 return MarkAsCall(DefineFixed(result, r0), instr); |
| 790 } | 786 } |
| (...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1340 | 1336 |
| 1341 LInstruction* LChunkBuilder::DoShl(HShl* instr) { | 1337 LInstruction* LChunkBuilder::DoShl(HShl* instr) { |
| 1342 return DoShift(Token::SHL, instr); | 1338 return DoShift(Token::SHL, instr); |
| 1343 } | 1339 } |
| 1344 | 1340 |
| 1345 | 1341 |
| 1346 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { | 1342 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { |
| 1347 if (instr->representation().IsSmiOrInteger32()) { | 1343 if (instr->representation().IsSmiOrInteger32()) { |
| 1348 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1344 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1349 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1345 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1346 ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32)); | |
| 1350 | 1347 |
| 1351 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1348 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1352 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1349 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1353 return DefineAsRegister(new(zone()) LBitI(left, right)); | 1350 return DefineAsRegister(new(zone()) LBitI(left, right)); |
| 1354 } else { | 1351 } else { |
| 1355 ASSERT(instr->representation().IsTagged()); | 1352 return DoArithmeticT(instr->op(), instr); |
| 1356 ASSERT(instr->left()->representation().IsTagged()); | |
| 1357 ASSERT(instr->right()->representation().IsTagged()); | |
| 1358 | |
| 1359 LOperand* left = UseFixed(instr->left(), r1); | |
| 1360 LOperand* right = UseFixed(instr->right(), r0); | |
| 1361 LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right); | |
| 1362 return MarkAsCall(DefineFixed(result, r0), instr); | |
| 1363 } | 1353 } |
| 1364 } | 1354 } |
| 1365 | 1355 |
| 1366 | 1356 |
| 1367 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1357 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
| 1368 if (instr->representation().IsDouble()) { | 1358 if (instr->representation().IsSmiOrInteger32()) { |
| 1369 return DoArithmeticD(Token::DIV, instr); | |
| 1370 } else if (instr->representation().IsSmiOrInteger32()) { | |
| 1371 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1359 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1372 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1360 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1373 if (instr->HasPowerOf2Divisor()) { | 1361 if (instr->HasPowerOf2Divisor()) { |
| 1374 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); | 1362 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); |
| 1375 LOperand* value = UseRegisterAtStart(instr->left()); | 1363 LOperand* value = UseRegisterAtStart(instr->left()); |
| 1376 LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL); | 1364 LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL); |
| 1377 return AssignEnvironment(DefineAsRegister(div)); | 1365 return AssignEnvironment(DefineAsRegister(div)); |
| 1378 } | 1366 } |
| 1379 LOperand* dividend = UseRegister(instr->left()); | 1367 LOperand* dividend = UseRegister(instr->left()); |
| 1380 LOperand* divisor = UseRegister(instr->right()); | 1368 LOperand* divisor = UseRegister(instr->right()); |
| 1381 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); | 1369 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); |
| 1382 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); | 1370 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); |
| 1383 return AssignEnvironment(DefineAsRegister(div)); | 1371 return AssignEnvironment(DefineAsRegister(div)); |
| 1372 } else if (instr->representation().IsDouble()) { | |
| 1373 return DoArithmeticD(Token::DIV, instr); | |
| 1384 } else { | 1374 } else { |
| 1385 return DoArithmeticT(Token::DIV, instr); | 1375 return DoArithmeticT(Token::DIV, instr); |
| 1386 } | 1376 } |
| 1387 } | 1377 } |
| 1388 | 1378 |
| 1389 | 1379 |
| 1390 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { | 1380 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { |
| 1391 uint32_t divisor_abs = abs(divisor); | 1381 uint32_t divisor_abs = abs(divisor); |
| 1392 // Dividing by 0, 1, and powers of 2 is easy. | 1382 // Dividing by 0, 1, and powers of 2 is easy. |
| 1393 // Note that IsPowerOf2(0) returns true; | 1383 // Note that IsPowerOf2(0) returns true; |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1494 FixedTemp(d10), | 1484 FixedTemp(d10), |
| 1495 FixedTemp(d11)); | 1485 FixedTemp(d11)); |
| 1496 LInstruction* result = DefineAsRegister(mod); | 1486 LInstruction* result = DefineAsRegister(mod); |
| 1497 return (right->CanBeZero() || | 1487 return (right->CanBeZero() || |
| 1498 (left->CanBeNegative() && | 1488 (left->CanBeNegative() && |
| 1499 instr->CanBeZero() && | 1489 instr->CanBeZero() && |
| 1500 instr->CheckFlag(HValue::kBailoutOnMinusZero))) | 1490 instr->CheckFlag(HValue::kBailoutOnMinusZero))) |
| 1501 ? AssignEnvironment(result) | 1491 ? AssignEnvironment(result) |
| 1502 : result; | 1492 : result; |
| 1503 } | 1493 } |
| 1504 } else if (instr->representation().IsTagged()) { | 1494 } else if (instr->representation().IsDouble()) { |
| 1495 return DoArithmeticD(Token::MOD, instr); | |
| 1496 } else { | |
| 1505 return DoArithmeticT(Token::MOD, instr); | 1497 return DoArithmeticT(Token::MOD, instr); |
| 1506 } else { | |
| 1507 ASSERT(instr->representation().IsDouble()); | |
| 1508 // We call a C function for double modulo. It can't trigger a GC. We need | |
| 1509 // to use fixed result register for the call. | |
| 1510 // TODO(fschneider): Allow any register as input registers. | |
| 1511 LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, | |
| 1512 UseFixedDouble(left, d1), | |
| 1513 UseFixedDouble(right, d2)); | |
| 1514 return MarkAsCall(DefineFixedDouble(mod, d1), instr); | |
| 1515 } | 1498 } |
| 1516 } | 1499 } |
| 1517 | 1500 |
| 1518 | 1501 |
| 1519 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1502 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
| 1520 if (instr->representation().IsSmiOrInteger32()) { | 1503 if (instr->representation().IsSmiOrInteger32()) { |
| 1521 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1504 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1522 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1505 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1523 HValue* left = instr->BetterLeftOperand(); | 1506 HValue* left = instr->BetterLeftOperand(); |
| 1524 HValue* right = instr->BetterRightOperand(); | 1507 HValue* right = instr->BetterRightOperand(); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1671 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); | 1654 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); |
| 1672 } | 1655 } |
| 1673 | 1656 |
| 1674 if (instr->right()->IsMul()) { | 1657 if (instr->right()->IsMul()) { |
| 1675 ASSERT(!instr->left()->IsMul()); | 1658 ASSERT(!instr->left()->IsMul()); |
| 1676 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); | 1659 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); |
| 1677 } | 1660 } |
| 1678 | 1661 |
| 1679 return DoArithmeticD(Token::ADD, instr); | 1662 return DoArithmeticD(Token::ADD, instr); |
| 1680 } else { | 1663 } else { |
| 1681 ASSERT(instr->representation().IsTagged()); | |
| 1682 return DoArithmeticT(Token::ADD, instr); | 1664 return DoArithmeticT(Token::ADD, instr); |
| 1683 } | 1665 } |
| 1684 } | 1666 } |
| 1685 | 1667 |
| 1686 | 1668 |
| 1687 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { | 1669 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { |
| 1688 LOperand* left = NULL; | 1670 LOperand* left = NULL; |
| 1689 LOperand* right = NULL; | 1671 LOperand* right = NULL; |
| 1690 if (instr->representation().IsSmiOrInteger32()) { | 1672 if (instr->representation().IsSmiOrInteger32()) { |
| 1691 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1673 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| (...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2621 | 2603 |
| 2622 | 2604 |
| 2623 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2605 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2624 LOperand* object = UseRegister(instr->object()); | 2606 LOperand* object = UseRegister(instr->object()); |
| 2625 LOperand* index = UseRegister(instr->index()); | 2607 LOperand* index = UseRegister(instr->index()); |
| 2626 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); | 2608 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); |
| 2627 } | 2609 } |
| 2628 | 2610 |
| 2629 | 2611 |
| 2630 } } // namespace v8::internal | 2612 } } // namespace v8::internal |
| OLD | NEW |