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

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
« no previous file with comments | « runtime/vm/flow_graph_optimizer.cc ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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)) {
1829 // This condition may not be known earlier in some cases because
1830 // of constant propagation, inlining, etc.
1831 __ jmp(deopt);
1832 break;
1833 }
1834 Register temp = locs()->temp(0).reg();
1835 __ movl(temp, left);
1836 __ shll(left, Immediate(value));
1837 __ sarl(left, Immediate(value));
1838 __ cmpl(left, temp);
1839 __ j(NOT_EQUAL, deopt); // Overflow.
1840 // Shift for result now we know there is no overflow.
1841 __ shll(left, Immediate(value));
1842 break;
1843 }
1825 1844
1826 default: 1845 default:
1827 UNREACHABLE(); 1846 UNREACHABLE();
1828 break; 1847 break;
1829 } 1848 }
1830 return; 1849 return;
1831 } 1850 }
1832 1851
1833 Register right = locs()->in(1).reg(); 1852 Register right = locs()->in(1).reg();
1834 switch (op_kind()) { 1853 switch (op_kind()) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1899 __ movl(right, kCountLimit); 1918 __ movl(right, kCountLimit);
1900 __ Bind(&count_ok); 1919 __ Bind(&count_ok);
1901 ASSERT(right == ECX); // Count must be in ECX 1920 ASSERT(right == ECX); // Count must be in ECX
1902 __ SmiUntag(left); 1921 __ SmiUntag(left);
1903 __ sarl(left, right); 1922 __ sarl(left, right);
1904 __ SmiTag(left); 1923 __ SmiTag(left);
1905 break; 1924 break;
1906 } 1925 }
1907 case Token::kSHL: { 1926 case Token::kSHL: {
1908 Register temp = locs()->temp(0).reg(); 1927 Register temp = locs()->temp(0).reg();
1909 Label call_method, done;
1910 // Check if count too large for handling it inlined. 1928 // Check if count too large for handling it inlined.
1911 __ movl(temp, left); 1929 __ movl(temp, left);
1912 Range* right_range = this->right()->definition()->range(); 1930 Range* right_range = this->right()->definition()->range();
1913 const bool right_needs_check = 1931 const bool right_needs_check =
1914 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); 1932 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1));
1915 if (right_needs_check) { 1933 if (right_needs_check) {
1916 __ cmpl(right, 1934 __ cmpl(right,
1917 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); 1935 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
1918 __ j(ABOVE_EQUAL, &call_method, Assembler::kNearJump); 1936 __ j(ABOVE_EQUAL, deopt);
1919 } 1937 }
1920 Register right_temp = locs()->temp(1).reg(); 1938 ASSERT(right == ECX); // Count must be in ECX
1921 ASSERT(right_temp == ECX); // Count must be in ECX 1939 __ SmiUntag(right);
1922 __ movl(right_temp, right);
1923 __ SmiUntag(right_temp);
1924 // Overflow test (preserve temp and right); 1940 // Overflow test (preserve temp and right);
1925 __ shll(left, right_temp); 1941 __ shll(left, right);
1926 __ sarl(left, right_temp); 1942 __ sarl(left, right);
1927 __ cmpl(left, temp); 1943 __ cmpl(left, temp);
1928 __ j(NOT_EQUAL, &call_method, Assembler::kNearJump); // Overflow. 1944 __ j(NOT_EQUAL, deopt); // Overflow.
1929 // Shift for result now we know there is no overflow. 1945 // Shift for result now we know there is no overflow.
1930 __ shll(left, right_temp); 1946 __ 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; 1947 break;
1951 } 1948 }
1952 case Token::kDIV: { 1949 case Token::kDIV: {
1953 // Dispatches to 'Double./'. 1950 // Dispatches to 'Double./'.
1954 // TODO(srdjan): Implement as conversion to double and double division. 1951 // TODO(srdjan): Implement as conversion to double and double division.
1955 UNREACHABLE(); 1952 UNREACHABLE();
1956 break; 1953 break;
1957 } 1954 }
1958 case Token::kMOD: { 1955 case Token::kMOD: {
1959 // TODO(srdjan): Implement. 1956 // TODO(srdjan): Implement.
(...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after
2723 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. 2720 __ pcmpeqq(XMM0, XMM0); // Generate all 1's.
2724 __ pxor(value, XMM0); 2721 __ pxor(value, XMM0);
2725 } 2722 }
2726 2723
2727 2724
2728 } // namespace dart 2725 } // namespace dart
2729 2726
2730 #undef __ 2727 #undef __
2731 2728
2732 #endif // defined TARGET_ARCH_X64 2729 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.cc ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698