Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1008)

Side by Side Diff: runtime/vm/intermediate_language_ia32.cc

Issue 11363141: Improve smi shift operations and avoid repeated deoptimizations. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 1714 matching lines...) Expand 10 before | Expand all | Expand 10 after
1725 return summary; 1725 return summary;
1726 } else if (op_kind() == Token::kSHR) { 1726 } else if (op_kind() == Token::kSHR) {
1727 const intptr_t kNumTemps = 0; 1727 const intptr_t kNumTemps = 0;
1728 LocationSummary* summary = 1728 LocationSummary* summary =
1729 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1729 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1730 summary->set_in(0, Location::RequiresRegister()); 1730 summary->set_in(0, Location::RequiresRegister());
1731 summary->set_in(1, Location::FixedRegisterOrConstant(right(), ECX)); 1731 summary->set_in(1, Location::FixedRegisterOrConstant(right(), ECX));
1732 summary->set_out(Location::SameAsFirstInput()); 1732 summary->set_out(Location::SameAsFirstInput());
1733 return summary; 1733 return summary;
1734 } else if (op_kind() == Token::kSHL) { 1734 } else if (op_kind() == Token::kSHL) {
1735 // Two Smi operands can easily overflow into Mint. 1735 const intptr_t kNumTemps = 1;
1736 const intptr_t kNumTemps = 2;
1737 LocationSummary* summary = 1736 LocationSummary* summary =
1738 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 1737 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1739 summary->set_in(0, Location::RegisterLocation(EAX)); 1738 summary->set_in(0, Location::RequiresRegister());
1740 summary->set_in(1, Location::RegisterLocation(EDX)); 1739 summary->set_in(1, Location::FixedRegisterOrConstant(right(), ECX));
1741 summary->set_temp(0, Location::RegisterLocation(EBX)); 1740 summary->set_temp(0, Location::RequiresRegister());
1742 summary->set_temp(1, Location::RegisterLocation(ECX)); 1741 summary->set_out(Location::SameAsFirstInput());
1743 summary->set_out(Location::RegisterLocation(EAX));
1744 return summary; 1742 return summary;
1745 } else { 1743 } else {
1746 const intptr_t kNumTemps = 0; 1744 const intptr_t kNumTemps = 0;
1747 LocationSummary* summary = 1745 LocationSummary* summary =
1748 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 1746 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
1749 summary->set_in(0, Location::RequiresRegister()); 1747 summary->set_in(0, Location::RequiresRegister());
1750 summary->set_in(1, Location::RegisterOrConstant(right())); 1748 summary->set_in(1, Location::RegisterOrConstant(right()));
1751 summary->set_out(Location::SameAsFirstInput()); 1749 summary->set_out(Location::SameAsFirstInput());
1752 return summary; 1750 return summary;
1753 } 1751 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1815 break; 1813 break;
1816 } 1814 }
1817 1815
1818 value = value + kSmiTagSize; 1816 value = value + kSmiTagSize;
1819 if (value >= kCountLimit) value = kCountLimit; 1817 if (value >= kCountLimit) value = kCountLimit;
1820 1818
1821 __ sarl(left, Immediate(value)); 1819 __ sarl(left, Immediate(value));
1822 __ SmiTag(left); 1820 __ SmiTag(left);
1823 break; 1821 break;
1824 } 1822 }
1823 case Token::kSHL: {
1824 // shll operation masks the count to 5 bits.
1825 const intptr_t kCountLimit = 0x1F;
1826 intptr_t value = Smi::Cast(constant).Value();
1827 if (value == 0) break;
1828 if (value < 0 || value >= kCountLimit) {
srdjan 2012/11/08 21:37:27 Add parenthesis.
1829 __ jmp(deopt);
srdjan 2012/11/08 21:37:27 Make a note that this may not be known at instruct
Florian Schneider 2012/11/08 22:03:00 Done.
1830 break;
1831 }
1832 Register temp = locs()->temp(0).reg();
1833 __ movl(temp, left);
1834 __ shll(left, Immediate(value));
1835 __ sarl(left, Immediate(value));
1836 __ cmpl(left, temp);
1837 __ j(NOT_EQUAL, deopt); // Overflow.
1838 // Shift for result now we know there is no overflow.
1839 __ shll(left, Immediate(value));
1840 break;
1841 }
1825 1842
1826 default: 1843 default:
1827 UNREACHABLE(); 1844 UNREACHABLE();
1828 break; 1845 break;
1829 } 1846 }
1830 return; 1847 return;
1831 } 1848 }
1832 1849
1833 Register right = locs()->in(1).reg(); 1850 Register right = locs()->in(1).reg();
1834 switch (op_kind()) { 1851 switch (op_kind()) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1899 __ movl(right, kCountLimit); 1916 __ movl(right, kCountLimit);
1900 __ Bind(&count_ok); 1917 __ Bind(&count_ok);
1901 ASSERT(right == ECX); // Count must be in ECX 1918 ASSERT(right == ECX); // Count must be in ECX
1902 __ SmiUntag(left); 1919 __ SmiUntag(left);
1903 __ sarl(left, right); 1920 __ sarl(left, right);
1904 __ SmiTag(left); 1921 __ SmiTag(left);
1905 break; 1922 break;
1906 } 1923 }
1907 case Token::kSHL: { 1924 case Token::kSHL: {
1908 Register temp = locs()->temp(0).reg(); 1925 Register temp = locs()->temp(0).reg();
1909 Label call_method, done;
1910 // Check if count too large for handling it inlined. 1926 // Check if count too large for handling it inlined.
1911 __ movl(temp, left); 1927 __ movl(temp, left);
1912 Range* right_range = this->right()->definition()->range(); 1928 Range* right_range = this->right()->definition()->range();
1913 const bool right_needs_check = 1929 const bool right_needs_check =
1914 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); 1930 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1));
1915 if (right_needs_check) { 1931 if (right_needs_check) {
1916 __ cmpl(right, 1932 __ cmpl(right,
1917 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); 1933 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
1918 __ j(ABOVE_EQUAL, &call_method, Assembler::kNearJump); 1934 __ j(ABOVE_EQUAL, deopt);
1919 } 1935 }
1920 Register right_temp = locs()->temp(1).reg(); 1936 ASSERT(right == ECX); // Count must be in ECX
1921 ASSERT(right_temp == ECX); // Count must be in ECX 1937 __ SmiUntag(right);
1922 __ movl(right_temp, right);
1923 __ SmiUntag(right_temp);
1924 // Overflow test (preserve temp and right); 1938 // Overflow test (preserve temp and right);
1925 __ shll(left, right_temp); 1939 __ shll(left, right);
1926 __ sarl(left, right_temp); 1940 __ sarl(left, right);
1927 __ cmpl(left, temp); 1941 __ cmpl(left, temp);
1928 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow. 1942 __ j(NOT_EQUAL, deopt); // Overflow.
1929 // Shift for result now we know there is no overflow. 1943 // Shift for result now we know there is no overflow.
1930 __ shll(left, right_temp); 1944 __ shll(left, right);
1931 __ jmp(&done);
1932 {
1933 __ Bind(&call_method);
1934 Function& target = Function::ZoneHandle(
1935 ic_data()->GetTargetForReceiverClassId(kSmiCid));
1936 ASSERT(!target.IsNull());
1937 const intptr_t kArgumentCount = 2;
1938 __ pushl(temp);
1939 __ pushl(right);
1940 compiler->GenerateStaticCall(
1941 deopt_id(),
1942 instance_call()->token_pos(),
1943 target,
1944 kArgumentCount,
1945 Array::Handle(), // No argument names.
1946 locs());
1947 ASSERT(result == EAX);
1948 }
1949 __ Bind(&done);
1950 break; 1945 break;
1951 } 1946 }
1952 case Token::kDIV: { 1947 case Token::kDIV: {
1953 // Dispatches to 'Double./'. 1948 // Dispatches to 'Double./'.
1954 // TODO(srdjan): Implement as conversion to double and double division. 1949 // TODO(srdjan): Implement as conversion to double and double division.
1955 UNREACHABLE(); 1950 UNREACHABLE();
1956 break; 1951 break;
1957 } 1952 }
1958 case Token::kMOD: { 1953 case Token::kMOD: {
1959 // TODO(srdjan): Implement. 1954 // TODO(srdjan): Implement.
(...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after
2723 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. 2718 __ pcmpeqq(XMM0, XMM0); // Generate all 1's.
2724 __ pxor(value, XMM0); 2719 __ pxor(value, XMM0);
2725 } 2720 }
2726 2721
2727 2722
2728 } // namespace dart 2723 } // namespace dart
2729 2724
2730 #undef __ 2725 #undef __
2731 2726
2732 #endif // defined TARGET_ARCH_X64 2727 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698