| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 1594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1605 return summary; | 1605 return summary; |
| 1606 } else if (op_kind() == Token::kSHR) { | 1606 } else if (op_kind() == Token::kSHR) { |
| 1607 const intptr_t kNumTemps = 0; | 1607 const intptr_t kNumTemps = 0; |
| 1608 LocationSummary* summary = | 1608 LocationSummary* summary = |
| 1609 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1609 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1610 summary->set_in(0, Location::RequiresRegister()); | 1610 summary->set_in(0, Location::RequiresRegister()); |
| 1611 summary->set_in(1, Location::RegisterLocation(RCX)); | 1611 summary->set_in(1, Location::RegisterLocation(RCX)); |
| 1612 summary->set_out(Location::SameAsFirstInput()); | 1612 summary->set_out(Location::SameAsFirstInput()); |
| 1613 return summary; | 1613 return summary; |
| 1614 } else if (op_kind() == Token::kSHL) { | 1614 } else if (op_kind() == Token::kSHL) { |
| 1615 const intptr_t kNumTemps = 1; | 1615 // Two Smi operands can easily overflow into Mint. |
| 1616 const intptr_t kNumTemps = 2; |
| 1616 LocationSummary* summary = | 1617 LocationSummary* summary = |
| 1617 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1618 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1618 summary->set_in(0, Location::RequiresRegister()); | 1619 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 1619 summary->set_in(1, Location::FixedRegisterOrConstant(right(), RCX)); | 1620 summary->set_in(1, Location::RegisterLocation(RDX)); |
| 1620 summary->set_temp(0, Location::RequiresRegister()); | 1621 summary->set_out(Location::RegisterLocation(RAX)); |
| 1621 summary->set_out(Location::SameAsFirstInput()); | 1622 summary->set_temp(0, Location::RegisterLocation(RBX)); |
| 1623 summary->set_temp(1, Location::RegisterLocation(RCX)); |
| 1622 return summary; | 1624 return summary; |
| 1623 } else { | 1625 } else { |
| 1624 const intptr_t kNumTemps = 0; | 1626 const intptr_t kNumTemps = 0; |
| 1625 LocationSummary* summary = | 1627 LocationSummary* summary = |
| 1626 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1628 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1627 summary->set_in(0, Location::RequiresRegister()); | 1629 summary->set_in(0, Location::RequiresRegister()); |
| 1628 summary->set_in(1, Location::RequiresRegister()); | 1630 summary->set_in(1, Location::RequiresRegister()); |
| 1629 summary->set_out(Location::SameAsFirstInput()); | 1631 summary->set_out(Location::SameAsFirstInput()); |
| 1630 return summary; | 1632 return summary; |
| 1631 } | 1633 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1688 break; | 1690 break; |
| 1689 } | 1691 } |
| 1690 | 1692 |
| 1691 value = value + kSmiTagSize; | 1693 value = value + kSmiTagSize; |
| 1692 if (value >= kCountLimit) value = kCountLimit; | 1694 if (value >= kCountLimit) value = kCountLimit; |
| 1693 | 1695 |
| 1694 __ sarq(left, Immediate(value)); | 1696 __ sarq(left, Immediate(value)); |
| 1695 __ SmiTag(left); | 1697 __ SmiTag(left); |
| 1696 break; | 1698 break; |
| 1697 } | 1699 } |
| 1698 case Token::kSHL: { | |
| 1699 // shlq operation masks the count to 6 bits. | |
| 1700 const intptr_t kCountLimit = 0x3F; | |
| 1701 intptr_t value = Smi::Cast(constant).Value(); | |
| 1702 if (value == 0) break; | |
| 1703 if ((value < 0) || (value >= kCountLimit)) { | |
| 1704 // This condition may not be known earlier in some cases because | |
| 1705 // of constant propagation, inlining, etc. | |
| 1706 __ jmp(deopt); | |
| 1707 break; | |
| 1708 } | |
| 1709 Register temp = locs()->temp(0).reg(); | |
| 1710 __ movq(temp, left); | |
| 1711 __ shlq(left, Immediate(value)); | |
| 1712 __ sarq(left, Immediate(value)); | |
| 1713 __ cmpq(left, temp); | |
| 1714 __ j(NOT_EQUAL, deopt); // Overflow. | |
| 1715 // Shift for result now we know there is no overflow. | |
| 1716 __ shlq(left, Immediate(value)); | |
| 1717 break; | |
| 1718 } | |
| 1719 | |
| 1720 default: | 1700 default: |
| 1721 UNREACHABLE(); | 1701 UNREACHABLE(); |
| 1722 break; | 1702 break; |
| 1723 } | 1703 } |
| 1724 return; | 1704 return; |
| 1725 } | 1705 } |
| 1726 | 1706 |
| 1727 Register right = locs()->in(1).reg(); | 1707 Register right = locs()->in(1).reg(); |
| 1728 switch (op_kind()) { | 1708 switch (op_kind()) { |
| 1729 case Token::kADD: { | 1709 case Token::kADD: { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1793 __ movq(right, kCountLimit); | 1773 __ movq(right, kCountLimit); |
| 1794 __ Bind(&count_ok); | 1774 __ Bind(&count_ok); |
| 1795 ASSERT(right == RCX); // Count must be in RCX | 1775 ASSERT(right == RCX); // Count must be in RCX |
| 1796 __ SmiUntag(left); | 1776 __ SmiUntag(left); |
| 1797 __ sarq(left, right); | 1777 __ sarq(left, right); |
| 1798 __ SmiTag(left); | 1778 __ SmiTag(left); |
| 1799 break; | 1779 break; |
| 1800 } | 1780 } |
| 1801 case Token::kSHL: { | 1781 case Token::kSHL: { |
| 1802 Register temp = locs()->temp(0).reg(); | 1782 Register temp = locs()->temp(0).reg(); |
| 1783 Label call_method, done; |
| 1803 // Check if count too large for handling it inlined. | 1784 // Check if count too large for handling it inlined. |
| 1804 __ movq(temp, left); | 1785 __ movq(temp, left); |
| 1805 Range* right_range = this->right()->definition()->range(); | 1786 Range* right_range = this->right()->definition()->range(); |
| 1806 const bool right_needs_check = | 1787 const bool right_needs_check = |
| 1807 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); | 1788 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); |
| 1808 if (right_needs_check) { | 1789 if (right_needs_check) { |
| 1809 __ cmpq(right, | 1790 __ cmpq(right, |
| 1810 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); | 1791 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); |
| 1811 __ j(ABOVE_EQUAL, deopt); | 1792 __ j(ABOVE_EQUAL, &call_method, Assembler::kNearJump); |
| 1812 } | 1793 } |
| 1813 ASSERT(right == RCX); // Count must be in RCX | 1794 Register right_temp = locs()->temp(1).reg(); |
| 1814 __ SmiUntag(right); | 1795 ASSERT(right_temp == RCX); // Count must be in RCX |
| 1796 __ movq(right_temp, right); |
| 1797 __ SmiUntag(right_temp); |
| 1815 // Overflow test (preserve temp and right); | 1798 // Overflow test (preserve temp and right); |
| 1816 __ shlq(left, right); | 1799 __ shlq(left, right_temp); |
| 1817 __ sarq(left, right); | 1800 __ sarq(left, right_temp); |
| 1818 __ cmpq(left, temp); | 1801 __ cmpq(left, temp); |
| 1819 __ j(NOT_EQUAL, deopt); // Overflow. | 1802 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow. |
| 1820 // Shift for result now we know there is no overflow. | 1803 // Shift for result now we know there is no overflow. |
| 1821 __ shlq(left, right); | 1804 __ shlq(left, right_temp); |
| 1805 __ jmp(&done); |
| 1806 { |
| 1807 __ Bind(&call_method); |
| 1808 Function& target = Function::ZoneHandle( |
| 1809 ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
| 1810 ASSERT(!target.IsNull()); |
| 1811 const intptr_t kArgumentCount = 2; |
| 1812 __ pushq(temp); |
| 1813 __ pushq(right); |
| 1814 compiler->GenerateStaticCall( |
| 1815 deopt_id(), |
| 1816 instance_call()->token_pos(), |
| 1817 target, |
| 1818 kArgumentCount, |
| 1819 Array::Handle(), // No argument names. |
| 1820 locs()); |
| 1821 ASSERT(result == RAX); |
| 1822 } |
| 1823 __ Bind(&done); |
| 1822 break; | 1824 break; |
| 1823 } | 1825 } |
| 1824 case Token::kDIV: { | 1826 case Token::kDIV: { |
| 1825 // Dispatches to 'Double./'. | 1827 // Dispatches to 'Double./'. |
| 1826 // TODO(srdjan): Implement as conversion to double and double division. | 1828 // TODO(srdjan): Implement as conversion to double and double division. |
| 1827 UNREACHABLE(); | 1829 UNREACHABLE(); |
| 1828 break; | 1830 break; |
| 1829 } | 1831 } |
| 1830 case Token::kMOD: { | 1832 case Token::kMOD: { |
| 1831 // TODO(srdjan): Implement. | 1833 // TODO(srdjan): Implement. |
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2355 | 2357 |
| 2356 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2358 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2357 UNIMPLEMENTED(); | 2359 UNIMPLEMENTED(); |
| 2358 } | 2360 } |
| 2359 | 2361 |
| 2360 } // namespace dart | 2362 } // namespace dart |
| 2361 | 2363 |
| 2362 #undef __ | 2364 #undef __ |
| 2363 | 2365 |
| 2364 #endif // defined TARGET_ARCH_X64 | 2366 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |