OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 1351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1362 return MarkAsCall(new(zone()) LDeclareGlobals(context), instr); | 1362 return MarkAsCall(new(zone()) LDeclareGlobals(context), instr); |
1363 } | 1363 } |
1364 | 1364 |
1365 | 1365 |
1366 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { | 1366 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { |
1367 return AssignEnvironment(new(zone()) LDeoptimize); | 1367 return AssignEnvironment(new(zone()) LDeoptimize); |
1368 } | 1368 } |
1369 | 1369 |
1370 | 1370 |
1371 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) { | 1371 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) { |
1372 ASSERT(instr->representation().IsInteger32()); | 1372 ASSERT(instr->representation().IsSmiOrInteger32()); |
1373 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1373 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1374 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1374 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1375 LOperand* dividend = UseRegister(instr->left()); | 1375 LOperand* dividend = UseRegister(instr->left()); |
1376 int32_t divisor = instr->right()->GetInteger32Constant(); | 1376 int32_t divisor = instr->right()->GetInteger32Constant(); |
1377 LInstruction* result = | 1377 LInstruction* result = |
1378 DefineAsRegister(new(zone()) LDivByPowerOf2I(dividend, divisor)); | 1378 DefineAsRegister(new(zone()) LDivByPowerOf2I(dividend, divisor)); |
1379 bool can_deopt = | 1379 bool can_deopt = |
1380 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && | 1380 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && |
1381 instr->left()->RangeCanInclude(0) && divisor < 0) || | 1381 instr->left()->RangeCanInclude(0) && divisor < 0) || |
1382 (instr->CheckFlag(HValue::kCanOverflow) && | 1382 (instr->CheckFlag(HValue::kCanOverflow) && |
1383 instr->left()->RangeCanInclude(kMinInt) && divisor == -1) || | 1383 instr->left()->RangeCanInclude(kMinInt) && divisor == -1) || |
1384 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | 1384 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
1385 divisor != 1 && divisor != -1); | 1385 divisor != 1 && divisor != -1); |
1386 return can_deopt ? AssignEnvironment(result) : result; | 1386 return can_deopt ? AssignEnvironment(result) : result; |
1387 } | 1387 } |
1388 | 1388 |
1389 | 1389 |
1390 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) { | |
1391 ASSERT(instr->representation().IsInteger32()); | |
1392 ASSERT(instr->left()->representation().Equals(instr->representation())); | |
1393 ASSERT(instr->right()->representation().Equals(instr->representation())); | |
1394 LOperand* dividend = UseRegister(instr->left()); | |
1395 int32_t divisor = instr->right()->GetInteger32Constant(); | |
1396 bool truncating = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32); | |
1397 LOperand* temp = truncating ? NULL : TempRegister(); | |
1398 LInstruction* result = | |
1399 DefineAsRegister(new(zone()) LDivByConstI(dividend, divisor, temp)); | |
1400 bool can_deopt = | |
1401 divisor == 0 || | |
1402 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && | |
1403 instr->left()->RangeCanInclude(0) && divisor < 0) || | |
1404 !truncating; | |
1405 return can_deopt ? AssignEnvironment(result) : result; | |
1406 } | |
1407 | |
1408 | |
1409 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { | 1390 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { |
1410 ASSERT(instr->representation().IsSmiOrInteger32()); | 1391 ASSERT(instr->representation().IsSmiOrInteger32()); |
1411 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1392 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1412 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1393 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1413 LOperand* dividend = UseRegister(instr->left()); | 1394 LOperand* dividend = UseRegister(instr->left()); |
1414 LOperand* divisor = UseRegister(instr->right()); | 1395 LOperand* divisor = UseRegister(instr->right()); |
1415 LOperand* temp = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) | 1396 LOperand* temp = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) |
1416 ? NULL : TempRegister(); | 1397 ? NULL : TempRegister(); |
1417 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); | 1398 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); |
1418 return AssignEnvironment(DefineAsRegister(div)); | 1399 return AssignEnvironment(DefineAsRegister(div)); |
1419 } | 1400 } |
1420 | 1401 |
1421 | 1402 |
1422 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1403 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
1423 if (instr->representation().IsSmiOrInteger32()) { | 1404 if (instr->representation().IsSmiOrInteger32()) { |
1424 if (instr->RightIsPowerOf2()) { | 1405 // TODO(all): Add Smi support to DoDivI and turn this into a ternary. |
1425 return DoDivByPowerOf2I(instr); | 1406 if (instr->RightIsPowerOf2()) return DoDivByPowerOf2I(instr); |
1426 } else if (instr->right()->IsConstant()) { | 1407 if (instr->representation().IsInteger32()) return DoDivI(instr); |
1427 return DoDivByConstI(instr); | 1408 return DoArithmeticT(Token::DIV, instr); |
1428 } else { | |
1429 return DoDivI(instr); | |
1430 } | |
1431 } else if (instr->representation().IsDouble()) { | 1409 } else if (instr->representation().IsDouble()) { |
1432 return DoArithmeticD(Token::DIV, instr); | 1410 return DoArithmeticD(Token::DIV, instr); |
1433 } else { | 1411 } else { |
1434 return DoArithmeticT(Token::DIV, instr); | 1412 return DoArithmeticT(Token::DIV, instr); |
1435 } | 1413 } |
1436 } | 1414 } |
1437 | 1415 |
1438 | 1416 |
1439 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) { | 1417 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) { |
1440 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value()))); | 1418 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value()))); |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1729 } | 1707 } |
1730 | 1708 |
1731 | 1709 |
1732 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) { | 1710 LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) { |
1733 LOperand* map = UseRegisterAtStart(instr->value()); | 1711 LOperand* map = UseRegisterAtStart(instr->value()); |
1734 return DefineAsRegister(new(zone()) LMapEnumLength(map)); | 1712 return DefineAsRegister(new(zone()) LMapEnumLength(map)); |
1735 } | 1713 } |
1736 | 1714 |
1737 | 1715 |
1738 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) { | 1716 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) { |
1739 ASSERT(instr->representation().IsInteger32()); | |
1740 ASSERT(instr->left()->representation().Equals(instr->representation())); | |
1741 ASSERT(instr->right()->representation().Equals(instr->representation())); | |
1742 LOperand* dividend = UseRegisterAtStart(instr->left()); | 1717 LOperand* dividend = UseRegisterAtStart(instr->left()); |
1743 int32_t divisor = instr->right()->GetInteger32Constant(); | 1718 int32_t divisor = instr->right()->GetInteger32Constant(); |
1744 LInstruction* result = | 1719 LInstruction* result = |
1745 DefineSameAsFirst(new(zone()) LFlooringDivByPowerOf2I(dividend, divisor)); | 1720 DefineSameAsFirst(new(zone()) LFlooringDivByPowerOf2I(dividend, divisor)); |
1746 bool can_deopt = | 1721 bool can_deopt = |
1747 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || | 1722 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
1748 (instr->left()->RangeCanInclude(kMinInt) && divisor == -1); | 1723 (instr->left()->RangeCanInclude(kMinInt) && divisor == -1); |
1749 return can_deopt ? AssignEnvironment(result) : result; | 1724 return can_deopt ? AssignEnvironment(result) : result; |
1750 } | 1725 } |
1751 | 1726 |
1752 | 1727 |
1753 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) { | |
1754 ASSERT(instr->representation().IsInteger32()); | |
1755 ASSERT(instr->left()->representation().Equals(instr->representation())); | |
1756 ASSERT(instr->right()->representation().Equals(instr->representation())); | |
1757 LOperand* dividend = UseRegister(instr->left()); | |
1758 int32_t divisor = instr->right()->GetInteger32Constant(); | |
1759 LInstruction* result = | |
1760 DefineAsRegister(new(zone()) LFlooringDivByConstI(dividend, divisor)); | |
1761 bool can_deopt = | |
1762 divisor == 0 || | |
1763 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && | |
1764 instr->left()->RangeCanInclude(0) && divisor < 0); | |
1765 return can_deopt ? AssignEnvironment(result) : result; | |
1766 } | |
1767 | |
1768 | |
1769 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) { | 1728 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) { |
1770 LOperand* dividend = UseRegister(instr->left()); | 1729 LOperand* dividend = UseRegister(instr->left()); |
1771 LOperand* divisor = UseRegister(instr->right()); | 1730 LOperand* divisor = UseRegister(instr->right()); |
1772 LOperand* remainder = TempRegister(); | 1731 LOperand* remainder = TempRegister(); |
1773 LInstruction* result = | 1732 LInstruction* result = |
1774 DefineAsRegister(new(zone()) LFlooringDivI(dividend, divisor, remainder)); | 1733 DefineAsRegister(new(zone()) LFlooringDivI(dividend, divisor, remainder)); |
1775 return AssignEnvironment(result); | 1734 return AssignEnvironment(result); |
1776 } | 1735 } |
1777 | 1736 |
1778 | 1737 |
1779 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { | 1738 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { |
1780 if (instr->RightIsPowerOf2()) { | 1739 if (instr->RightIsPowerOf2()) { |
1781 return DoFlooringDivByPowerOf2I(instr); | 1740 return DoFlooringDivByPowerOf2I(instr); |
1782 } else if (instr->right()->IsConstant()) { | 1741 } else if (instr->right()->IsConstant()) { |
1783 return DoFlooringDivByConstI(instr); | 1742 // TODO(svenpanne) Do something more efficient in this case. |
| 1743 return DoFlooringDivI(instr); |
1784 } else { | 1744 } else { |
1785 return DoFlooringDivI(instr); | 1745 return DoFlooringDivI(instr); |
1786 } | 1746 } |
1787 } | 1747 } |
1788 | 1748 |
1789 | 1749 |
1790 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { | 1750 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { |
1791 LOperand* left = NULL; | 1751 LOperand* left = NULL; |
1792 LOperand* right = NULL; | 1752 LOperand* right = NULL; |
1793 if (instr->representation().IsSmiOrInteger32()) { | 1753 if (instr->representation().IsSmiOrInteger32()) { |
1794 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1754 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1795 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1755 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1796 left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1756 left = UseRegisterAtStart(instr->BetterLeftOperand()); |
1797 right = UseRegisterOrConstantAtStart(instr->BetterRightOperand()); | 1757 right = UseRegisterOrConstantAtStart(instr->BetterRightOperand()); |
1798 } else { | 1758 } else { |
1799 ASSERT(instr->representation().IsDouble()); | 1759 ASSERT(instr->representation().IsDouble()); |
1800 ASSERT(instr->left()->representation().IsDouble()); | 1760 ASSERT(instr->left()->representation().IsDouble()); |
1801 ASSERT(instr->right()->representation().IsDouble()); | 1761 ASSERT(instr->right()->representation().IsDouble()); |
1802 left = UseRegisterAtStart(instr->left()); | 1762 left = UseRegisterAtStart(instr->left()); |
1803 right = UseRegisterAtStart(instr->right()); | 1763 right = UseRegisterAtStart(instr->right()); |
1804 } | 1764 } |
1805 return DefineAsRegister(new(zone()) LMathMinMax(left, right)); | 1765 return DefineAsRegister(new(zone()) LMathMinMax(left, right)); |
1806 } | 1766 } |
1807 | 1767 |
1808 | 1768 |
1809 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) { | 1769 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) { |
1810 ASSERT(instr->representation().IsInteger32()); | 1770 ASSERT(instr->representation().IsSmiOrInteger32()); |
1811 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1771 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1812 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1772 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1813 LOperand* dividend = UseRegisterAtStart(instr->left()); | 1773 LOperand* dividend = UseRegisterAtStart(instr->left()); |
1814 int32_t divisor = instr->right()->GetInteger32Constant(); | 1774 int32_t divisor = instr->right()->GetInteger32Constant(); |
1815 LInstruction* result = | 1775 LInstruction* result = |
1816 DefineSameAsFirst(new(zone()) LModByPowerOf2I(dividend, divisor)); | 1776 DefineSameAsFirst(new(zone()) LModByPowerOf2I(dividend, divisor)); |
1817 bool can_deopt = | 1777 bool can_deopt = |
1818 instr->CheckFlag(HValue::kBailoutOnMinusZero) && | 1778 instr->CheckFlag(HValue::kBailoutOnMinusZero) && |
1819 instr->left()->CanBeNegative(); | 1779 instr->left()->CanBeNegative(); |
1820 return can_deopt ? AssignEnvironment(result) : result; | 1780 return can_deopt ? AssignEnvironment(result) : result; |
1821 } | 1781 } |
1822 | 1782 |
1823 | 1783 |
1824 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) { | |
1825 ASSERT(instr->representation().IsInteger32()); | |
1826 ASSERT(instr->left()->representation().Equals(instr->representation())); | |
1827 ASSERT(instr->right()->representation().Equals(instr->representation())); | |
1828 LOperand* dividend = UseRegister(instr->left()); | |
1829 int32_t divisor = instr->right()->GetInteger32Constant(); | |
1830 LOperand* temp = TempRegister(); | |
1831 LInstruction* result = | |
1832 DefineAsRegister(new(zone()) LModByConstI(dividend, divisor, temp)); | |
1833 bool can_deopt = | |
1834 divisor == 0 || | |
1835 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && | |
1836 instr->left()->CanBeNegative()); | |
1837 return can_deopt ? AssignEnvironment(result) : result; | |
1838 } | |
1839 | |
1840 | |
1841 LInstruction* LChunkBuilder::DoModI(HMod* instr) { | 1784 LInstruction* LChunkBuilder::DoModI(HMod* instr) { |
1842 ASSERT(instr->representation().IsSmiOrInteger32()); | 1785 ASSERT(instr->representation().IsSmiOrInteger32()); |
1843 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1786 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1844 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1787 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1845 LOperand* dividend = UseRegister(instr->left()); | 1788 LOperand* dividend = UseRegister(instr->left()); |
1846 LOperand* divisor = UseRegister(instr->right()); | 1789 LOperand* divisor = UseRegister(instr->right()); |
1847 LInstruction* result = | 1790 LInstruction* result = |
1848 DefineAsRegister(new(zone()) LModI(dividend, divisor)); | 1791 DefineAsRegister(new(zone()) LModI(dividend, divisor)); |
1849 bool can_deopt = (instr->right()->CanBeZero() || | 1792 bool can_deopt = (instr->right()->CanBeZero() || |
1850 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && | 1793 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && |
1851 instr->left()->CanBeNegative() && instr->CanBeZero())); | 1794 instr->left()->CanBeNegative() && instr->CanBeZero())); |
1852 return can_deopt ? AssignEnvironment(result) : result; | 1795 return can_deopt ? AssignEnvironment(result) : result; |
1853 } | 1796 } |
1854 | 1797 |
1855 | 1798 |
1856 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1799 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
1857 if (instr->representation().IsSmiOrInteger32()) { | 1800 if (instr->representation().IsSmiOrInteger32()) { |
1858 if (instr->RightIsPowerOf2()) { | 1801 // TODO(all): Add Smi support to DoDivI and turn this into a ternary. |
1859 return DoModByPowerOf2I(instr); | 1802 if (instr->RightIsPowerOf2()) return DoModByPowerOf2I(instr); |
1860 } else if (instr->right()->IsConstant()) { | 1803 if (instr->representation().IsInteger32()) return DoModI(instr); |
1861 return DoModByConstI(instr); | 1804 return DoArithmeticT(Token::MOD, instr); |
1862 } else { | |
1863 return DoModI(instr); | |
1864 } | |
1865 } else if (instr->representation().IsDouble()) { | 1805 } else if (instr->representation().IsDouble()) { |
1866 return DoArithmeticD(Token::MOD, instr); | 1806 return DoArithmeticD(Token::MOD, instr); |
1867 } else { | 1807 } else { |
1868 return DoArithmeticT(Token::MOD, instr); | 1808 return DoArithmeticT(Token::MOD, instr); |
1869 } | 1809 } |
1870 } | 1810 } |
1871 | 1811 |
1872 | 1812 |
1873 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1813 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
1874 if (instr->representation().IsSmiOrInteger32()) { | 1814 if (instr->representation().IsSmiOrInteger32()) { |
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2552 | 2492 |
2553 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { | 2493 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) { |
2554 LOperand* receiver = UseRegister(instr->receiver()); | 2494 LOperand* receiver = UseRegister(instr->receiver()); |
2555 LOperand* function = UseRegister(instr->function()); | 2495 LOperand* function = UseRegister(instr->function()); |
2556 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function); | 2496 LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function); |
2557 return AssignEnvironment(DefineAsRegister(result)); | 2497 return AssignEnvironment(DefineAsRegister(result)); |
2558 } | 2498 } |
2559 | 2499 |
2560 | 2500 |
2561 } } // namespace v8::internal | 2501 } } // namespace v8::internal |
OLD | NEW |