Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 1768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1779 __ j(BELOW_EQUAL, slow_path->entry_label()); | 1779 __ j(BELOW_EQUAL, slow_path->entry_label()); |
| 1780 __ Bind(slow_path->exit_label()); | 1780 __ Bind(slow_path->exit_label()); |
| 1781 } | 1781 } |
| 1782 | 1782 |
| 1783 | 1783 |
| 1784 static bool CanBeImmediate(const Object& constant) { | 1784 static bool CanBeImmediate(const Object& constant) { |
| 1785 return constant.IsSmi() && | 1785 return constant.IsSmi() && |
| 1786 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); | 1786 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); |
| 1787 } | 1787 } |
| 1788 | 1788 |
| 1789 | |
| 1789 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { | 1790 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { |
| 1790 const intptr_t kNumInputs = 2; | 1791 const intptr_t kNumInputs = 2; |
| 1791 | 1792 |
| 1792 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 1793 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
| 1793 if ((right_constant != NULL) && | 1794 if ((right_constant != NULL) && |
| 1794 (op_kind() != Token::kTRUNCDIV) && | 1795 (op_kind() != Token::kTRUNCDIV) && |
| 1795 (op_kind() != Token::kSHL) && | 1796 (op_kind() != Token::kSHL) && |
| 1796 (op_kind() != Token::kMUL) && | 1797 (op_kind() != Token::kMUL) && |
| 1797 CanBeImmediate(right_constant->value())) { | 1798 CanBeImmediate(right_constant->value())) { |
| 1798 const intptr_t kNumTemps = 0; | 1799 const intptr_t kNumTemps = 0; |
| 1799 LocationSummary* summary = | 1800 LocationSummary* summary = |
| 1800 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1801 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1801 summary->set_in(0, Location::RequiresRegister()); | 1802 summary->set_in(0, Location::RequiresRegister()); |
| 1802 summary->set_in(1, Location::Constant(right_constant->value())); | 1803 summary->set_in(1, Location::Constant(right_constant->value())); |
| 1803 summary->set_out(Location::SameAsFirstInput()); | 1804 summary->set_out(Location::SameAsFirstInput()); |
| 1804 return summary; | 1805 return summary; |
| 1805 } | 1806 } |
| 1806 | 1807 |
| 1807 if (op_kind() == Token::kTRUNCDIV) { | 1808 if (op_kind() == Token::kTRUNCDIV) { |
| 1808 const intptr_t kNumTemps = 1; | 1809 const intptr_t kNumTemps = 1; |
| 1809 LocationSummary* summary = | 1810 LocationSummary* summary = |
| 1810 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1811 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1811 // Both inputs must be writable because they will be untagged. | 1812 if (RightIsPowerOfTwoConstant()) { |
| 1812 summary->set_in(0, Location::RegisterLocation(RAX)); | 1813 summary->set_in(0, Location::RequiresRegister()); |
| 1813 summary->set_in(1, Location::WritableRegister()); | 1814 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
| 1814 summary->set_out(Location::SameAsFirstInput()); | 1815 summary->set_in(1, Location::Constant(right_constant->value())); |
| 1815 // Will be used for sign extension and division. | 1816 summary->set_temp(0, Location::RequiresRegister()); |
| 1816 summary->set_temp(0, Location::RegisterLocation(RDX)); | 1817 summary->set_out(Location::SameAsFirstInput()); |
| 1818 } else { | |
| 1819 // Both inputs must be writable because they will be untagged. | |
| 1820 summary->set_in(0, Location::RegisterLocation(RAX)); | |
| 1821 summary->set_in(1, Location::WritableRegister()); | |
| 1822 summary->set_out(Location::SameAsFirstInput()); | |
| 1823 // Will be used for sign extension and division. | |
| 1824 summary->set_temp(0, Location::RegisterLocation(RDX)); | |
| 1825 } | |
| 1817 return summary; | 1826 return summary; |
| 1818 } else if (op_kind() == Token::kSHR) { | 1827 } else if (op_kind() == Token::kSHR) { |
| 1819 const intptr_t kNumTemps = 0; | 1828 const intptr_t kNumTemps = 0; |
| 1820 LocationSummary* summary = | 1829 LocationSummary* summary = |
| 1821 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1830 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1822 summary->set_in(0, Location::RequiresRegister()); | 1831 summary->set_in(0, Location::RequiresRegister()); |
| 1823 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 1832 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
| 1824 summary->set_out(Location::SameAsFirstInput()); | 1833 summary->set_out(Location::SameAsFirstInput()); |
| 1825 return summary; | 1834 return summary; |
| 1826 } else if (op_kind() == Token::kSHL) { | 1835 } else if (op_kind() == Token::kSHL) { |
| 1827 const intptr_t kNumTemps = 1; | 1836 const intptr_t kNumTemps = 1; |
| 1828 LocationSummary* summary = | 1837 LocationSummary* summary = |
| 1829 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1838 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1830 summary->set_in(0, Location::RequiresRegister()); | 1839 summary->set_in(0, Location::RequiresRegister()); |
| 1831 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 1840 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
| 1832 summary->set_temp(0, Location::RequiresRegister()); | 1841 summary->set_temp(0, Location::RequiresRegister()); |
| 1833 summary->set_out(Location::SameAsFirstInput()); | 1842 summary->set_out(Location::SameAsFirstInput()); |
| 1834 return summary; | 1843 return summary; |
| 1835 } else { | 1844 } else { |
| 1836 const intptr_t kNumTemps = 0; | 1845 const intptr_t kNumTemps = 0; |
| 1837 LocationSummary* summary = | 1846 LocationSummary* summary = |
| 1838 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1847 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1839 summary->set_in(0, Location::RequiresRegister()); | 1848 summary->set_in(0, Location::RequiresRegister()); |
| 1840 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 1849 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 1841 summary->set_out(Location::SameAsFirstInput()); | 1850 summary->set_out(Location::SameAsFirstInput()); |
| 1842 return summary; | 1851 return summary; |
| 1843 } | 1852 } |
| 1844 } | 1853 } |
| 1845 | 1854 |
| 1846 | |
| 1847 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1855 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1848 Register left = locs()->in(0).reg(); | 1856 Register left = locs()->in(0).reg(); |
| 1849 Register result = locs()->out().reg(); | 1857 Register result = locs()->out().reg(); |
| 1850 ASSERT(left == result); | 1858 ASSERT(left == result); |
| 1851 Label* deopt = NULL; | 1859 Label* deopt = NULL; |
| 1852 if (CanDeoptimize()) { | 1860 if (CanDeoptimize()) { |
| 1853 deopt = compiler->AddDeoptStub(deopt_id(), | 1861 deopt = compiler->AddDeoptStub(deopt_id(), |
| 1854 kDeoptBinarySmiOp); | 1862 kDeoptBinarySmiOp); |
| 1855 } | 1863 } |
| 1856 | 1864 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1870 if (deopt != NULL) __ j(OVERFLOW, deopt); | 1878 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 1871 break; | 1879 break; |
| 1872 } | 1880 } |
| 1873 case Token::kMUL: { | 1881 case Token::kMUL: { |
| 1874 // Keep left value tagged and untag right value. | 1882 // Keep left value tagged and untag right value. |
| 1875 const intptr_t value = Smi::Cast(constant).Value(); | 1883 const intptr_t value = Smi::Cast(constant).Value(); |
| 1876 __ imulq(left, Immediate(value)); | 1884 __ imulq(left, Immediate(value)); |
| 1877 if (deopt != NULL) __ j(OVERFLOW, deopt); | 1885 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 1878 break; | 1886 break; |
| 1879 } | 1887 } |
| 1888 case Token::kTRUNCDIV: { | |
| 1889 const intptr_t value = Smi::Cast(constant).Value(); | |
| 1890 if (value == 1) { | |
| 1891 // Do nothing. | |
| 1892 break; | |
| 1893 } else if (value == -1) { | |
| 1894 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | |
| 1895 // case we cannot negate the result. | |
| 1896 __ cmpl(left, Immediate(0x8000000000000000)); | |
| 1897 __ j(EQUAL, deopt); | |
| 1898 __ negl(left); | |
| 1899 break; | |
| 1900 } | |
| 1901 | |
| 1902 ASSERT((value != 0) && Utils::IsPowerOfTwo(Utils::Abs(value))); | |
| 1903 const intptr_t shift_count = | |
| 1904 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; | |
| 1905 Register temp = locs()->temp(0).reg(); | |
| 1906 __ movq(temp, left); | |
| 1907 __ sarq(temp, Immediate(63)); | |
| 1908 if (shift_count > 1) { | |
|
Florian Schneider
2013/02/04 13:04:03
Same comments as on ia32.
| |
| 1909 __ shrq(temp, Immediate(64 - shift_count)); | |
| 1910 } | |
| 1911 __ addq(left, temp); | |
| 1912 if (shift_count > 0) { | |
| 1913 __ sarq(left, Immediate(shift_count)); | |
| 1914 } | |
| 1915 if (value < 0) { | |
| 1916 __ negq(left); | |
| 1917 } | |
| 1918 __ SmiTag(left); | |
| 1919 break; | |
| 1920 } | |
| 1880 case Token::kBIT_AND: { | 1921 case Token::kBIT_AND: { |
| 1881 // No overflow check. | 1922 // No overflow check. |
| 1882 __ andq(left, Immediate(imm)); | 1923 __ andq(left, Immediate(imm)); |
| 1883 break; | 1924 break; |
| 1884 } | 1925 } |
| 1885 case Token::kBIT_OR: { | 1926 case Token::kBIT_OR: { |
| 1886 // No overflow check. | 1927 // No overflow check. |
| 1887 __ orq(left, Immediate(imm)); | 1928 __ orq(left, Immediate(imm)); |
| 1888 break; | 1929 break; |
| 1889 } | 1930 } |
| (...skipping 1096 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2986 PcDescriptors::kOther, | 3027 PcDescriptors::kOther, |
| 2987 locs()); | 3028 locs()); |
| 2988 __ Drop(2); // Discard type arguments and receiver. | 3029 __ Drop(2); // Discard type arguments and receiver. |
| 2989 } | 3030 } |
| 2990 | 3031 |
| 2991 } // namespace dart | 3032 } // namespace dart |
| 2992 | 3033 |
| 2993 #undef __ | 3034 #undef __ |
| 2994 | 3035 |
| 2995 #endif // defined TARGET_ARCH_X64 | 3036 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |