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

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 507040: -Inlined double variant of compare iff one of the sides is a constant smi and... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years 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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 1773 matching lines...) Expand 10 before | Expand all | Expand 10 after
1784 LikelySmiBinaryOperation(op, operand, &constant_operand, 1784 LikelySmiBinaryOperation(op, operand, &constant_operand,
1785 overwrite_mode); 1785 overwrite_mode);
1786 } 1786 }
1787 break; 1787 break;
1788 } 1788 }
1789 } 1789 }
1790 ASSERT(!operand->is_valid()); 1790 ASSERT(!operand->is_valid());
1791 } 1791 }
1792 1792
1793 1793
1794 void CodeGenerator::Comparison(Condition cc, 1794 void CodeGenerator::Comparison(AstNode* node,
1795 Condition cc,
1795 bool strict, 1796 bool strict,
1796 ControlDestination* dest) { 1797 ControlDestination* dest) {
1797 // Strict only makes sense for equality comparisons. 1798 // Strict only makes sense for equality comparisons.
1798 ASSERT(!strict || cc == equal); 1799 ASSERT(!strict || cc == equal);
1799 1800
1800 Result left_side; 1801 Result left_side;
1801 Result right_side; 1802 Result right_side;
1802 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. 1803 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
1803 if (cc == greater || cc == less_equal) { 1804 if (cc == greater || cc == less_equal) {
1804 cc = ReverseCondition(cc); 1805 cc = ReverseCondition(cc);
(...skipping 26 matching lines...) Expand all
1831 break; 1832 break;
1832 case equal: 1833 case equal:
1833 dest->Goto(left_value == right_value); 1834 dest->Goto(left_value == right_value);
1834 break; 1835 break;
1835 case greater_equal: 1836 case greater_equal:
1836 dest->Goto(left_value >= right_value); 1837 dest->Goto(left_value >= right_value);
1837 break; 1838 break;
1838 default: 1839 default:
1839 UNREACHABLE(); 1840 UNREACHABLE();
1840 } 1841 }
1841 } else { // Only one side is a constant Smi. 1842 } else {
1843 // Only one side is a constant Smi.
1842 // If left side is a constant Smi, reverse the operands. 1844 // If left side is a constant Smi, reverse the operands.
1843 // Since one side is a constant Smi, conversion order does not matter. 1845 // Since one side is a constant Smi, conversion order does not matter.
1844 if (left_side_constant_smi) { 1846 if (left_side_constant_smi) {
1845 Result temp = left_side; 1847 Result temp = left_side;
1846 left_side = right_side; 1848 left_side = right_side;
1847 right_side = temp; 1849 right_side = temp;
1848 cc = ReverseCondition(cc); 1850 cc = ReverseCondition(cc);
1849 // This may reintroduce greater or less_equal as the value of cc. 1851 // This may reintroduce greater or less_equal as the value of cc.
1850 // CompareStub and the inline code both support all values of cc. 1852 // CompareStub and the inline code both support all values of cc.
1851 } 1853 }
1852 // Implement comparison against a constant Smi, inlining the case 1854 // Implement comparison against a constant Smi, inlining the case
1853 // where both sides are Smis. 1855 // where both sides are Smis.
1854 left_side.ToRegister(); 1856 left_side.ToRegister();
1857 Register left_reg = left_side.reg();
1858 Handle<Object> right_val = right_side.handle();
1855 1859
1856 // Here we split control flow to the stub call and inlined cases 1860 // Here we split control flow to the stub call and inlined cases
1857 // before finally splitting it to the control destination. We use 1861 // before finally splitting it to the control destination. We use
1858 // a jump target and branching to duplicate the virtual frame at 1862 // a jump target and branching to duplicate the virtual frame at
1859 // the first split. We manually handle the off-frame references 1863 // the first split. We manually handle the off-frame references
1860 // by reconstituting them on the non-fall-through path. 1864 // by reconstituting them on the non-fall-through path.
1861 JumpTarget is_smi; 1865 JumpTarget is_smi;
1862 Register left_reg = left_side.reg();
1863 Handle<Object> right_val = right_side.handle();
1864 __ test(left_side.reg(), Immediate(kSmiTagMask)); 1866 __ test(left_side.reg(), Immediate(kSmiTagMask));
1865 is_smi.Branch(zero, taken); 1867 is_smi.Branch(zero, taken);
1866 1868
1869 bool is_for_loop_compare = node->AsCompareOperation()
iposva 2009/12/17 21:03:50 Shouldn't you do a " != NULL" here?
bakster 2009/12/18 06:38:47 Done.
1870 && node->AsCompareOperation()->is_for_loop_condition();
1871 if (!is_for_loop_compare
1872 && CpuFeatures::IsSupported(SSE2)
1873 && right_val->IsSmi()) {
1874 // The right side value is either a smi or heap number.
iposva 2009/12/17 21:03:50 Comment does not match the check. Right side is a
bakster 2009/12/18 06:38:47 Done.
1875 CpuFeatures::Scope use_sse2(SSE2);
1876 JumpTarget not_number;
1877 __ cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
1878 Immediate(Factory::heap_number_map()));
1879 not_number.Branch(not_equal, &left_side);
1880 __ movdbl(xmm1,
1881 FieldOperand(left_reg, HeapNumber::kValueOffset));
1882 int value = Smi::cast(*right_val)->value();
1883 if (value == 0) {
1884 __ xorpd(xmm0, xmm0);
1885 } else {
1886 Result temp = allocator()->Allocate();
1887 __ mov (temp.reg(), Immediate(value));
1888 __ cvtsi2sd(xmm0, Operand(temp.reg()));
iposva 2009/12/17 21:03:50 Why do you keep converting the value to double fro
bakster 2009/12/18 06:38:47 I'm not sure it makes a difference. I'll try the o
1889 temp.Unuse();
1890 }
1891 __ comisd(xmm1, xmm0);
1892 // Jump to builtin for NaN.
1893 not_number.Branch(parity_even, &left_side);
1894 left_side.Unuse();
1895 Condition double_cc = cc;
1896 switch (cc) {
1897 case less: double_cc = below; break;
1898 case equal: double_cc = equal; break;
1899 case less_equal: double_cc = below_equal; break;
1900 case greater: double_cc = above; break;
1901 case greater_equal: double_cc = above_equal; break;
1902 default: UNREACHABLE();
1903 }
1904 dest->true_target()->Branch(double_cc);
1905 dest->false_target()->Jump();
1906 not_number.Bind(&left_side);
1907 }
1908
1867 // Setup and call the compare stub. 1909 // Setup and call the compare stub.
1868 CompareStub stub(cc, strict); 1910 CompareStub stub(cc, strict);
1869 Result result = frame_->CallStub(&stub, &left_side, &right_side); 1911 Result result = frame_->CallStub(&stub, &left_side, &right_side);
1870 result.ToRegister(); 1912 result.ToRegister();
1871 __ cmp(result.reg(), 0); 1913 __ cmp(result.reg(), 0);
1872 result.Unuse(); 1914 result.Unuse();
1873 dest->true_target()->Branch(cc); 1915 dest->true_target()->Branch(cc);
1874 dest->false_target()->Jump(); 1916 dest->false_target()->Jump();
1875 1917
1876 is_smi.Bind(); 1918 is_smi.Bind();
1877 left_side = Result(left_reg); 1919 left_side = Result(left_reg);
1878 right_side = Result(right_val); 1920 right_side = Result(right_val);
1879 // Test smi equality and comparison by signed int comparison. 1921 // Test smi equality and comparison by signed int comparison.
1880 if (IsUnsafeSmi(right_side.handle())) { 1922 if (IsUnsafeSmi(right_side.handle())) {
1881 right_side.ToRegister(); 1923 right_side.ToRegister();
1882 __ cmp(left_side.reg(), Operand(right_side.reg())); 1924 __ cmp(left_side.reg(), Operand(right_side.reg()));
1883 } else { 1925 } else {
1884 __ cmp(Operand(left_side.reg()), Immediate(right_side.handle())); 1926 __ cmp(Operand(left_side.reg()), Immediate(right_side.handle()));
1885 } 1927 }
1886 left_side.Unuse(); 1928 left_side.Unuse();
1887 right_side.Unuse(); 1929 right_side.Unuse();
1888 dest->Split(cc); 1930 dest->Split(cc);
1889 } 1931 }
1932
1890 } else if (cc == equal && 1933 } else if (cc == equal &&
1891 (left_side_constant_null || right_side_constant_null)) { 1934 (left_side_constant_null || right_side_constant_null)) {
1892 // To make null checks efficient, we check if either the left side or 1935 // To make null checks efficient, we check if either the left side or
1893 // the right side is the constant 'null'. 1936 // the right side is the constant 'null'.
1894 // If so, we optimize the code by inlining a null check instead of 1937 // If so, we optimize the code by inlining a null check instead of
1895 // calling the (very) general runtime routine for checking equality. 1938 // calling the (very) general runtime routine for checking equality.
1896 Result operand = left_side_constant_null ? right_side : left_side; 1939 Result operand = left_side_constant_null ? right_side : left_side;
1897 right_side.Unuse(); 1940 right_side.Unuse();
1898 left_side.Unuse(); 1941 left_side.Unuse();
1899 operand.ToRegister(); 1942 operand.ToRegister();
(...skipping 16 matching lines...) Expand all
1916 ASSERT(temp.is_valid()); 1959 ASSERT(temp.is_valid());
1917 __ mov(temp.reg(), 1960 __ mov(temp.reg(),
1918 FieldOperand(operand.reg(), HeapObject::kMapOffset)); 1961 FieldOperand(operand.reg(), HeapObject::kMapOffset));
1919 __ movzx_b(temp.reg(), 1962 __ movzx_b(temp.reg(),
1920 FieldOperand(temp.reg(), Map::kBitFieldOffset)); 1963 FieldOperand(temp.reg(), Map::kBitFieldOffset));
1921 __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable)); 1964 __ test(temp.reg(), Immediate(1 << Map::kIsUndetectable));
1922 temp.Unuse(); 1965 temp.Unuse();
1923 operand.Unuse(); 1966 operand.Unuse();
1924 dest->Split(not_zero); 1967 dest->Split(not_zero);
1925 } 1968 }
1926 } else { // Neither side is a constant Smi or null. 1969 } else {
1970 // Neither side is a constant Smi or null.
1927 // If either side is a non-smi constant, skip the smi check. 1971 // If either side is a non-smi constant, skip the smi check.
1928 bool known_non_smi = 1972 bool known_non_smi =
1929 (left_side.is_constant() && !left_side.handle()->IsSmi()) || 1973 (left_side.is_constant() && !left_side.handle()->IsSmi()) ||
1930 (right_side.is_constant() && !right_side.handle()->IsSmi()); 1974 (right_side.is_constant() && !right_side.handle()->IsSmi());
1931 left_side.ToRegister(); 1975 left_side.ToRegister();
1932 right_side.ToRegister(); 1976 right_side.ToRegister();
1933 1977
1934 if (known_non_smi) { 1978 if (known_non_smi) {
1935 // When non-smi, call out to the compare stub. 1979 // When non-smi, call out to the compare stub.
1936 CompareStub stub(cc, strict); 1980 CompareStub stub(cc, strict);
(...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after
2583 2627
2584 // Duplicate the switch value. 2628 // Duplicate the switch value.
2585 frame_->Dup(); 2629 frame_->Dup();
2586 2630
2587 // Compile the label expression. 2631 // Compile the label expression.
2588 Load(clause->label()); 2632 Load(clause->label());
2589 2633
2590 // Compare and branch to the body if true or the next test if 2634 // Compare and branch to the body if true or the next test if
2591 // false. Prefer the next test as a fall through. 2635 // false. Prefer the next test as a fall through.
2592 ControlDestination dest(clause->body_target(), &next_test, false); 2636 ControlDestination dest(clause->body_target(), &next_test, false);
2593 Comparison(equal, true, &dest); 2637 Comparison(node, equal, true, &dest);
2594 2638
2595 // If the comparison fell through to the true target, jump to the 2639 // If the comparison fell through to the true target, jump to the
2596 // actual body. 2640 // actual body.
2597 if (dest.true_was_fall_through()) { 2641 if (dest.true_was_fall_through()) {
2598 clause->body_target()->Unuse(); 2642 clause->body_target()->Unuse();
2599 clause->body_target()->Jump(); 2643 clause->body_target()->Jump();
2600 } 2644 }
2601 } 2645 }
2602 2646
2603 // If there was control flow to a next test from the last one 2647 // If there was control flow to a next test from the last one
(...skipping 3392 matching lines...) Expand 10 before | Expand all | Expand 10 after
5996 __ test(answer.reg(), Operand(answer.reg())); 6040 __ test(answer.reg(), Operand(answer.reg()));
5997 answer.Unuse(); 6041 answer.Unuse();
5998 destination()->Split(zero); 6042 destination()->Split(zero);
5999 return; 6043 return;
6000 } 6044 }
6001 default: 6045 default:
6002 UNREACHABLE(); 6046 UNREACHABLE();
6003 } 6047 }
6004 Load(left); 6048 Load(left);
6005 Load(right); 6049 Load(right);
6006 Comparison(cc, strict, destination()); 6050 Comparison(node, cc, strict, destination());
6007 } 6051 }
6008 6052
6009 6053
6010 #ifdef DEBUG 6054 #ifdef DEBUG
6011 bool CodeGenerator::HasValidEntryRegisters() { 6055 bool CodeGenerator::HasValidEntryRegisters() {
6012 return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0)) 6056 return (allocator()->count(eax) == (frame()->is_used(eax) ? 1 : 0))
6013 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0)) 6057 && (allocator()->count(ebx) == (frame()->is_used(ebx) ? 1 : 0))
6014 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0)) 6058 && (allocator()->count(ecx) == (frame()->is_used(ecx) ? 1 : 0))
6015 && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0)) 6059 && (allocator()->count(edx) == (frame()->is_used(edx) ? 1 : 0))
6016 && (allocator()->count(edi) == (frame()->is_used(edi) ? 1 : 0)); 6060 && (allocator()->count(edi) == (frame()->is_used(edi) ? 1 : 0));
(...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after
6795 6839
6796 void GenericBinaryOpStub::GenerateCall( 6840 void GenericBinaryOpStub::GenerateCall(
6797 MacroAssembler* masm, 6841 MacroAssembler* masm,
6798 Register left, 6842 Register left,
6799 Smi* right) { 6843 Smi* right) {
6800 if (!ArgsInRegistersSupported()) { 6844 if (!ArgsInRegistersSupported()) {
6801 // Pass arguments on the stack. 6845 // Pass arguments on the stack.
6802 __ push(left); 6846 __ push(left);
6803 __ push(Immediate(right)); 6847 __ push(Immediate(right));
6804 } else { 6848 } else {
6805 // The calling convention with registers is left in edx and right in eax. 6849 // The calling convention with registers is left in edx and right in eax.
iposva 2009/12/17 21:03:50 Unmotivated space?
bakster 2009/12/18 06:38:47 Done.
6806 Register left_arg = edx; 6850 Register left_arg = edx;
6807 Register right_arg = eax; 6851 Register right_arg = eax;
6808 if (left.is(left_arg)) { 6852 if (left.is(left_arg)) {
6809 __ mov(right_arg, Immediate(right)); 6853 __ mov(right_arg, Immediate(right));
6810 } else if (left.is(right_arg) && IsOperationCommutative()) { 6854 } else if (left.is(right_arg) && IsOperationCommutative()) {
6811 __ mov(left_arg, Immediate(right)); 6855 __ mov(left_arg, Immediate(right));
6812 SetArgsReversed(); 6856 SetArgsReversed();
6813 } else { 6857 } else {
6814 __ mov(left_arg, left); 6858 __ mov(left_arg, left);
6815 __ mov(right_arg, Immediate(right)); 6859 __ mov(right_arg, Immediate(right));
(...skipping 1862 matching lines...) Expand 10 before | Expand all | Expand 10 after
8678 __ add(Operand(dest), Immediate(2)); 8722 __ add(Operand(dest), Immediate(2));
8679 } 8723 }
8680 __ sub(Operand(count), Immediate(1)); 8724 __ sub(Operand(count), Immediate(1));
8681 __ j(not_zero, &loop); 8725 __ j(not_zero, &loop);
8682 } 8726 }
8683 8727
8684 8728
8685 #undef __ 8729 #undef __
8686 8730
8687 } } // namespace v8::internal 8731 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/disasm-ia32.cc » ('j') | src/ia32/disasm-ia32.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698