OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |