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

Side by Side Diff: src/arm/code-stubs-arm.cc

Issue 7063017: Rename TypeRecording...Stub into ...Stub. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 7 months 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 | « src/arm/code-stubs-arm.h ('k') | src/arm/full-codegen-arm.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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 1689 matching lines...) Expand 10 before | Expand all | Expand 10 after
1700 // If length is not zero, "tos_" contains a non-zero value ==> true. 1700 // If length is not zero, "tos_" contains a non-zero value ==> true.
1701 __ Ret(); 1701 __ Ret();
1702 1702
1703 // Return 0 in "tos_" for false . 1703 // Return 0 in "tos_" for false .
1704 __ bind(&false_result); 1704 __ bind(&false_result);
1705 __ mov(tos_, Operand(0, RelocInfo::NONE)); 1705 __ mov(tos_, Operand(0, RelocInfo::NONE));
1706 __ Ret(); 1706 __ Ret();
1707 } 1707 }
1708 1708
1709 1709
1710 Handle<Code> GetTypeRecordingUnaryOpStub(int key, 1710 Handle<Code> GetUnaryOpStub(int key, UnaryOpIC::TypeInfo type_info) {
1711 TRUnaryOpIC::TypeInfo type_info) { 1711 UnaryOpStub stub(key, type_info);
1712 TypeRecordingUnaryOpStub stub(key, type_info);
1713 return stub.GetCode(); 1712 return stub.GetCode();
1714 } 1713 }
1715 1714
1716 1715
1717 const char* TypeRecordingUnaryOpStub::GetName() { 1716 const char* UnaryOpStub::GetName() {
1718 if (name_ != NULL) return name_; 1717 if (name_ != NULL) return name_;
1719 const int kMaxNameLength = 100; 1718 const int kMaxNameLength = 100;
1720 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( 1719 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
1721 kMaxNameLength); 1720 kMaxNameLength);
1722 if (name_ == NULL) return "OOM"; 1721 if (name_ == NULL) return "OOM";
1723 const char* op_name = Token::Name(op_); 1722 const char* op_name = Token::Name(op_);
1724 const char* overwrite_name = NULL; // Make g++ happy. 1723 const char* overwrite_name = NULL; // Make g++ happy.
1725 switch (mode_) { 1724 switch (mode_) {
1726 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; 1725 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break;
1727 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break; 1726 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break;
1728 } 1727 }
1729 1728
1730 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 1729 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
1731 "TypeRecordingUnaryOpStub_%s_%s_%s", 1730 "UnaryOpStub_%s_%s_%s",
1732 op_name, 1731 op_name,
1733 overwrite_name, 1732 overwrite_name,
1734 TRUnaryOpIC::GetName(operand_type_)); 1733 UnaryOpIC::GetName(operand_type_));
1735 return name_; 1734 return name_;
1736 } 1735 }
1737 1736
1738 1737
1739 // TODO(svenpanne): Use virtual functions instead of switch. 1738 // TODO(svenpanne): Use virtual functions instead of switch.
1740 void TypeRecordingUnaryOpStub::Generate(MacroAssembler* masm) { 1739 void UnaryOpStub::Generate(MacroAssembler* masm) {
1741 switch (operand_type_) { 1740 switch (operand_type_) {
1742 case TRUnaryOpIC::UNINITIALIZED: 1741 case UnaryOpIC::UNINITIALIZED:
1743 GenerateTypeTransition(masm); 1742 GenerateTypeTransition(masm);
1744 break; 1743 break;
1745 case TRUnaryOpIC::SMI: 1744 case UnaryOpIC::SMI:
1746 GenerateSmiStub(masm); 1745 GenerateSmiStub(masm);
1747 break; 1746 break;
1748 case TRUnaryOpIC::HEAP_NUMBER: 1747 case UnaryOpIC::HEAP_NUMBER:
1749 GenerateHeapNumberStub(masm); 1748 GenerateHeapNumberStub(masm);
1750 break; 1749 break;
1751 case TRUnaryOpIC::GENERIC: 1750 case UnaryOpIC::GENERIC:
1752 GenerateGenericStub(masm); 1751 GenerateGenericStub(masm);
1753 break; 1752 break;
1754 } 1753 }
1755 } 1754 }
1756 1755
1757 1756
1758 void TypeRecordingUnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 1757 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
1759 // Prepare to push argument. 1758 // Prepare to push argument.
1760 __ mov(r3, Operand(r0)); 1759 __ mov(r3, Operand(r0));
1761 1760
1762 // Push this stub's key. Although the operation and the type info are 1761 // Push this stub's key. Although the operation and the type info are
1763 // encoded into the key, the encoding is opaque, so push them too. 1762 // encoded into the key, the encoding is opaque, so push them too.
1764 __ mov(r2, Operand(Smi::FromInt(MinorKey()))); 1763 __ mov(r2, Operand(Smi::FromInt(MinorKey())));
1765 __ mov(r1, Operand(Smi::FromInt(op_))); 1764 __ mov(r1, Operand(Smi::FromInt(op_)));
1766 __ mov(r0, Operand(Smi::FromInt(operand_type_))); 1765 __ mov(r0, Operand(Smi::FromInt(operand_type_)));
1767 1766
1768 __ Push(r3, r2, r1, r0); 1767 __ Push(r3, r2, r1, r0);
1769 1768
1770 __ TailCallExternalReference( 1769 __ TailCallExternalReference(
1771 ExternalReference(IC_Utility(IC::kTypeRecordingUnaryOp_Patch), 1770 ExternalReference(IC_Utility(IC::kUnaryOp_Patch),
1772 masm->isolate()), 1771 masm->isolate()),
1773 4, 1772 4,
1774 1); 1773 1);
1775 } 1774 }
1776 1775
1777 1776
1778 // TODO(svenpanne): Use virtual functions instead of switch. 1777 // TODO(svenpanne): Use virtual functions instead of switch.
1779 void TypeRecordingUnaryOpStub::GenerateSmiStub(MacroAssembler* masm) { 1778 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
1780 switch (op_) { 1779 switch (op_) {
1781 case Token::SUB: 1780 case Token::SUB:
1782 GenerateSmiStubSub(masm); 1781 GenerateSmiStubSub(masm);
1783 break; 1782 break;
1784 case Token::BIT_NOT: 1783 case Token::BIT_NOT:
1785 GenerateSmiStubBitNot(masm); 1784 GenerateSmiStubBitNot(masm);
1786 break; 1785 break;
1787 default: 1786 default:
1788 UNREACHABLE(); 1787 UNREACHABLE();
1789 } 1788 }
1790 } 1789 }
1791 1790
1792 1791
1793 void TypeRecordingUnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) { 1792 void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
1794 Label non_smi, slow; 1793 Label non_smi, slow;
1795 GenerateSmiCodeSub(masm, &non_smi, &slow); 1794 GenerateSmiCodeSub(masm, &non_smi, &slow);
1796 __ bind(&non_smi); 1795 __ bind(&non_smi);
1797 __ bind(&slow); 1796 __ bind(&slow);
1798 GenerateTypeTransition(masm); 1797 GenerateTypeTransition(masm);
1799 } 1798 }
1800 1799
1801 1800
1802 void TypeRecordingUnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) { 1801 void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
1803 Label non_smi; 1802 Label non_smi;
1804 GenerateSmiCodeBitNot(masm, &non_smi); 1803 GenerateSmiCodeBitNot(masm, &non_smi);
1805 __ bind(&non_smi); 1804 __ bind(&non_smi);
1806 GenerateTypeTransition(masm); 1805 GenerateTypeTransition(masm);
1807 } 1806 }
1808 1807
1809 1808
1810 void TypeRecordingUnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, 1809 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
1811 Label* non_smi, 1810 Label* non_smi,
1812 Label* slow) { 1811 Label* slow) {
1813 __ JumpIfNotSmi(r0, non_smi); 1812 __ JumpIfNotSmi(r0, non_smi);
1814 1813
1815 // The result of negating zero or the smallest negative smi is not a smi. 1814 // The result of negating zero or the smallest negative smi is not a smi.
1816 __ bic(ip, r0, Operand(0x80000000), SetCC); 1815 __ bic(ip, r0, Operand(0x80000000), SetCC);
1817 __ b(eq, slow); 1816 __ b(eq, slow);
1818 1817
1819 // Return '0 - value'. 1818 // Return '0 - value'.
1820 __ rsb(r0, r0, Operand(0, RelocInfo::NONE)); 1819 __ rsb(r0, r0, Operand(0, RelocInfo::NONE));
1821 __ Ret(); 1820 __ Ret();
1822 } 1821 }
1823 1822
1824 1823
1825 void TypeRecordingUnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm, 1824 void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm,
1826 Label* non_smi) { 1825 Label* non_smi) {
1827 __ JumpIfNotSmi(r0, non_smi); 1826 __ JumpIfNotSmi(r0, non_smi);
1828 1827
1829 // Flip bits and revert inverted smi-tag. 1828 // Flip bits and revert inverted smi-tag.
1830 __ mvn(r0, Operand(r0)); 1829 __ mvn(r0, Operand(r0));
1831 __ bic(r0, r0, Operand(kSmiTagMask)); 1830 __ bic(r0, r0, Operand(kSmiTagMask));
1832 __ Ret(); 1831 __ Ret();
1833 } 1832 }
1834 1833
1835 1834
1836 // TODO(svenpanne): Use virtual functions instead of switch. 1835 // TODO(svenpanne): Use virtual functions instead of switch.
1837 void TypeRecordingUnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { 1836 void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
1838 switch (op_) { 1837 switch (op_) {
1839 case Token::SUB: 1838 case Token::SUB:
1840 GenerateHeapNumberStubSub(masm); 1839 GenerateHeapNumberStubSub(masm);
1841 break; 1840 break;
1842 case Token::BIT_NOT: 1841 case Token::BIT_NOT:
1843 GenerateHeapNumberStubBitNot(masm); 1842 GenerateHeapNumberStubBitNot(masm);
1844 break; 1843 break;
1845 default: 1844 default:
1846 UNREACHABLE(); 1845 UNREACHABLE();
1847 } 1846 }
1848 } 1847 }
1849 1848
1850 1849
1851 void TypeRecordingUnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) { 1850 void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
1852 Label non_smi, slow, call_builtin; 1851 Label non_smi, slow, call_builtin;
1853 GenerateSmiCodeSub(masm, &non_smi, &call_builtin); 1852 GenerateSmiCodeSub(masm, &non_smi, &call_builtin);
1854 __ bind(&non_smi); 1853 __ bind(&non_smi);
1855 GenerateHeapNumberCodeSub(masm, &slow); 1854 GenerateHeapNumberCodeSub(masm, &slow);
1856 __ bind(&slow); 1855 __ bind(&slow);
1857 GenerateTypeTransition(masm); 1856 GenerateTypeTransition(masm);
1858 __ bind(&call_builtin); 1857 __ bind(&call_builtin);
1859 GenerateGenericCodeFallback(masm); 1858 GenerateGenericCodeFallback(masm);
1860 } 1859 }
1861 1860
1862 1861
1863 void TypeRecordingUnaryOpStub::GenerateHeapNumberStubBitNot( 1862 void UnaryOpStub::GenerateHeapNumberStubBitNot(MacroAssembler* masm) {
1864 MacroAssembler* masm) {
1865 Label non_smi, slow; 1863 Label non_smi, slow;
1866 GenerateSmiCodeBitNot(masm, &non_smi); 1864 GenerateSmiCodeBitNot(masm, &non_smi);
1867 __ bind(&non_smi); 1865 __ bind(&non_smi);
1868 GenerateHeapNumberCodeBitNot(masm, &slow); 1866 GenerateHeapNumberCodeBitNot(masm, &slow);
1869 __ bind(&slow); 1867 __ bind(&slow);
1870 GenerateTypeTransition(masm); 1868 GenerateTypeTransition(masm);
1871 } 1869 }
1872 1870
1873 void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm, 1871 void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
1874 Label* slow) { 1872 Label* slow) {
1875 EmitCheckForHeapNumber(masm, r0, r1, r6, slow); 1873 EmitCheckForHeapNumber(masm, r0, r1, r6, slow);
1876 // r0 is a heap number. Get a new heap number in r1. 1874 // r0 is a heap number. Get a new heap number in r1.
1877 if (mode_ == UNARY_OVERWRITE) { 1875 if (mode_ == UNARY_OVERWRITE) {
1878 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 1876 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
1879 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. 1877 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign.
1880 __ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 1878 __ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
1881 } else { 1879 } else {
1882 Label slow_allocate_heapnumber, heapnumber_allocated; 1880 Label slow_allocate_heapnumber, heapnumber_allocated;
1883 __ AllocateHeapNumber(r1, r2, r3, r6, &slow_allocate_heapnumber); 1881 __ AllocateHeapNumber(r1, r2, r3, r6, &slow_allocate_heapnumber);
1884 __ jmp(&heapnumber_allocated); 1882 __ jmp(&heapnumber_allocated);
(...skipping 11 matching lines...) Expand all
1896 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 1894 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
1897 __ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset)); 1895 __ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset));
1898 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. 1896 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign.
1899 __ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset)); 1897 __ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset));
1900 __ mov(r0, Operand(r1)); 1898 __ mov(r0, Operand(r1));
1901 } 1899 }
1902 __ Ret(); 1900 __ Ret();
1903 } 1901 }
1904 1902
1905 1903
1906 void TypeRecordingUnaryOpStub::GenerateHeapNumberCodeBitNot( 1904 void UnaryOpStub::GenerateHeapNumberCodeBitNot(
1907 MacroAssembler* masm, Label* slow) { 1905 MacroAssembler* masm, Label* slow) {
1908 EmitCheckForHeapNumber(masm, r0, r1, r6, slow); 1906 EmitCheckForHeapNumber(masm, r0, r1, r6, slow);
1909 // Convert the heap number is r0 to an untagged integer in r1. 1907 // Convert the heap number is r0 to an untagged integer in r1.
1910 __ ConvertToInt32(r0, r1, r2, r3, d0, slow); 1908 __ ConvertToInt32(r0, r1, r2, r3, d0, slow);
1911 1909
1912 // Do the bitwise operation and check if the result fits in a smi. 1910 // Do the bitwise operation and check if the result fits in a smi.
1913 Label try_float; 1911 Label try_float;
1914 __ mvn(r1, Operand(r1)); 1912 __ mvn(r1, Operand(r1));
1915 __ add(r2, r1, Operand(0x40000000), SetCC); 1913 __ add(r2, r1, Operand(0x40000000), SetCC);
1916 __ b(mi, &try_float); 1914 __ b(mi, &try_float);
(...skipping 30 matching lines...) Expand all
1947 } else { 1945 } else {
1948 // WriteInt32ToHeapNumberStub does not trigger GC, so we do not 1946 // WriteInt32ToHeapNumberStub does not trigger GC, so we do not
1949 // have to set up a frame. 1947 // have to set up a frame.
1950 WriteInt32ToHeapNumberStub stub(r1, r0, r2); 1948 WriteInt32ToHeapNumberStub stub(r1, r0, r2);
1951 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET); 1949 __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
1952 } 1950 }
1953 } 1951 }
1954 1952
1955 1953
1956 // TODO(svenpanne): Use virtual functions instead of switch. 1954 // TODO(svenpanne): Use virtual functions instead of switch.
1957 void TypeRecordingUnaryOpStub::GenerateGenericStub(MacroAssembler* masm) { 1955 void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
1958 switch (op_) { 1956 switch (op_) {
1959 case Token::SUB: 1957 case Token::SUB:
1960 GenerateGenericStubSub(masm); 1958 GenerateGenericStubSub(masm);
1961 break; 1959 break;
1962 case Token::BIT_NOT: 1960 case Token::BIT_NOT:
1963 GenerateGenericStubBitNot(masm); 1961 GenerateGenericStubBitNot(masm);
1964 break; 1962 break;
1965 default: 1963 default:
1966 UNREACHABLE(); 1964 UNREACHABLE();
1967 } 1965 }
1968 } 1966 }
1969 1967
1970 1968
1971 void TypeRecordingUnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) { 1969 void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
1972 Label non_smi, slow; 1970 Label non_smi, slow;
1973 GenerateSmiCodeSub(masm, &non_smi, &slow); 1971 GenerateSmiCodeSub(masm, &non_smi, &slow);
1974 __ bind(&non_smi); 1972 __ bind(&non_smi);
1975 GenerateHeapNumberCodeSub(masm, &slow); 1973 GenerateHeapNumberCodeSub(masm, &slow);
1976 __ bind(&slow); 1974 __ bind(&slow);
1977 GenerateGenericCodeFallback(masm); 1975 GenerateGenericCodeFallback(masm);
1978 } 1976 }
1979 1977
1980 1978
1981 void TypeRecordingUnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) { 1979 void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
1982 Label non_smi, slow; 1980 Label non_smi, slow;
1983 GenerateSmiCodeBitNot(masm, &non_smi); 1981 GenerateSmiCodeBitNot(masm, &non_smi);
1984 __ bind(&non_smi); 1982 __ bind(&non_smi);
1985 GenerateHeapNumberCodeBitNot(masm, &slow); 1983 GenerateHeapNumberCodeBitNot(masm, &slow);
1986 __ bind(&slow); 1984 __ bind(&slow);
1987 GenerateGenericCodeFallback(masm); 1985 GenerateGenericCodeFallback(masm);
1988 } 1986 }
1989 1987
1990 1988
1991 void TypeRecordingUnaryOpStub::GenerateGenericCodeFallback( 1989 void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) {
1992 MacroAssembler* masm) {
1993 // Handle the slow case by jumping to the JavaScript builtin. 1990 // Handle the slow case by jumping to the JavaScript builtin.
1994 __ push(r0); 1991 __ push(r0);
1995 switch (op_) { 1992 switch (op_) {
1996 case Token::SUB: 1993 case Token::SUB:
1997 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); 1994 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
1998 break; 1995 break;
1999 case Token::BIT_NOT: 1996 case Token::BIT_NOT:
2000 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); 1997 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION);
2001 break; 1998 break;
2002 default: 1999 default:
2003 UNREACHABLE(); 2000 UNREACHABLE();
2004 } 2001 }
2005 } 2002 }
2006 2003
2007 2004
2008 Handle<Code> GetTypeRecordingBinaryOpStub(int key, 2005 Handle<Code> GetBinaryOpStub(int key,
2009 TRBinaryOpIC::TypeInfo type_info, 2006 BinaryOpIC::TypeInfo type_info,
2010 TRBinaryOpIC::TypeInfo result_type_info) { 2007 BinaryOpIC::TypeInfo result_type_info) {
2011 TypeRecordingBinaryOpStub stub(key, type_info, result_type_info); 2008 BinaryOpStub stub(key, type_info, result_type_info);
2012 return stub.GetCode(); 2009 return stub.GetCode();
2013 } 2010 }
2014 2011
2015 2012
2016 void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 2013 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
2017 Label get_result; 2014 Label get_result;
2018 2015
2019 __ Push(r1, r0); 2016 __ Push(r1, r0);
2020 2017
2021 __ mov(r2, Operand(Smi::FromInt(MinorKey()))); 2018 __ mov(r2, Operand(Smi::FromInt(MinorKey())));
2022 __ mov(r1, Operand(Smi::FromInt(op_))); 2019 __ mov(r1, Operand(Smi::FromInt(op_)));
2023 __ mov(r0, Operand(Smi::FromInt(operands_type_))); 2020 __ mov(r0, Operand(Smi::FromInt(operands_type_)));
2024 __ Push(r2, r1, r0); 2021 __ Push(r2, r1, r0);
2025 2022
2026 __ TailCallExternalReference( 2023 __ TailCallExternalReference(
2027 ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch), 2024 ExternalReference(IC_Utility(IC::kBinaryOp_Patch),
2028 masm->isolate()), 2025 masm->isolate()),
2029 5, 2026 5,
2030 1); 2027 1);
2031 } 2028 }
2032 2029
2033 2030
2034 void TypeRecordingBinaryOpStub::GenerateTypeTransitionWithSavedArgs( 2031 void BinaryOpStub::GenerateTypeTransitionWithSavedArgs(
2035 MacroAssembler* masm) { 2032 MacroAssembler* masm) {
2036 UNIMPLEMENTED(); 2033 UNIMPLEMENTED();
2037 } 2034 }
2038 2035
2039 2036
2040 void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) { 2037 void BinaryOpStub::Generate(MacroAssembler* masm) {
2041 switch (operands_type_) { 2038 switch (operands_type_) {
2042 case TRBinaryOpIC::UNINITIALIZED: 2039 case BinaryOpIC::UNINITIALIZED:
2043 GenerateTypeTransition(masm); 2040 GenerateTypeTransition(masm);
2044 break; 2041 break;
2045 case TRBinaryOpIC::SMI: 2042 case BinaryOpIC::SMI:
2046 GenerateSmiStub(masm); 2043 GenerateSmiStub(masm);
2047 break; 2044 break;
2048 case TRBinaryOpIC::INT32: 2045 case BinaryOpIC::INT32:
2049 GenerateInt32Stub(masm); 2046 GenerateInt32Stub(masm);
2050 break; 2047 break;
2051 case TRBinaryOpIC::HEAP_NUMBER: 2048 case BinaryOpIC::HEAP_NUMBER:
2052 GenerateHeapNumberStub(masm); 2049 GenerateHeapNumberStub(masm);
2053 break; 2050 break;
2054 case TRBinaryOpIC::ODDBALL: 2051 case BinaryOpIC::ODDBALL:
2055 GenerateOddballStub(masm); 2052 GenerateOddballStub(masm);
2056 break; 2053 break;
2057 case TRBinaryOpIC::BOTH_STRING: 2054 case BinaryOpIC::BOTH_STRING:
2058 GenerateBothStringStub(masm); 2055 GenerateBothStringStub(masm);
2059 break; 2056 break;
2060 case TRBinaryOpIC::STRING: 2057 case BinaryOpIC::STRING:
2061 GenerateStringStub(masm); 2058 GenerateStringStub(masm);
2062 break; 2059 break;
2063 case TRBinaryOpIC::GENERIC: 2060 case BinaryOpIC::GENERIC:
2064 GenerateGeneric(masm); 2061 GenerateGeneric(masm);
2065 break; 2062 break;
2066 default: 2063 default:
2067 UNREACHABLE(); 2064 UNREACHABLE();
2068 } 2065 }
2069 } 2066 }
2070 2067
2071 2068
2072 const char* TypeRecordingBinaryOpStub::GetName() { 2069 const char* BinaryOpStub::GetName() {
2073 if (name_ != NULL) return name_; 2070 if (name_ != NULL) return name_;
2074 const int kMaxNameLength = 100; 2071 const int kMaxNameLength = 100;
2075 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( 2072 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
2076 kMaxNameLength); 2073 kMaxNameLength);
2077 if (name_ == NULL) return "OOM"; 2074 if (name_ == NULL) return "OOM";
2078 const char* op_name = Token::Name(op_); 2075 const char* op_name = Token::Name(op_);
2079 const char* overwrite_name; 2076 const char* overwrite_name;
2080 switch (mode_) { 2077 switch (mode_) {
2081 case NO_OVERWRITE: overwrite_name = "Alloc"; break; 2078 case NO_OVERWRITE: overwrite_name = "Alloc"; break;
2082 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; 2079 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
2083 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; 2080 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
2084 default: overwrite_name = "UnknownOverwrite"; break; 2081 default: overwrite_name = "UnknownOverwrite"; break;
2085 } 2082 }
2086 2083
2087 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 2084 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
2088 "TypeRecordingBinaryOpStub_%s_%s_%s", 2085 "BinaryOpStub_%s_%s_%s",
2089 op_name, 2086 op_name,
2090 overwrite_name, 2087 overwrite_name,
2091 TRBinaryOpIC::GetName(operands_type_)); 2088 BinaryOpIC::GetName(operands_type_));
2092 return name_; 2089 return name_;
2093 } 2090 }
2094 2091
2095 2092
2096 void TypeRecordingBinaryOpStub::GenerateSmiSmiOperation( 2093 void BinaryOpStub::GenerateSmiSmiOperation(MacroAssembler* masm) {
2097 MacroAssembler* masm) {
2098 Register left = r1; 2094 Register left = r1;
2099 Register right = r0; 2095 Register right = r0;
2100 Register scratch1 = r7; 2096 Register scratch1 = r7;
2101 Register scratch2 = r9; 2097 Register scratch2 = r9;
2102 2098
2103 ASSERT(right.is(r0)); 2099 ASSERT(right.is(r0));
2104 STATIC_ASSERT(kSmiTag == 0); 2100 STATIC_ASSERT(kSmiTag == 0);
2105 2101
2106 Label not_smi_result; 2102 Label not_smi_result;
2107 switch (op_) { 2103 switch (op_) {
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
2212 __ SmiTag(right, scratch1); 2208 __ SmiTag(right, scratch1);
2213 __ Ret(); 2209 __ Ret();
2214 break; 2210 break;
2215 default: 2211 default:
2216 UNREACHABLE(); 2212 UNREACHABLE();
2217 } 2213 }
2218 __ bind(&not_smi_result); 2214 __ bind(&not_smi_result);
2219 } 2215 }
2220 2216
2221 2217
2222 void TypeRecordingBinaryOpStub::GenerateFPOperation(MacroAssembler* masm, 2218 void BinaryOpStub::GenerateFPOperation(MacroAssembler* masm,
2223 bool smi_operands, 2219 bool smi_operands,
2224 Label* not_numbers, 2220 Label* not_numbers,
2225 Label* gc_required) { 2221 Label* gc_required) {
2226 Register left = r1; 2222 Register left = r1;
2227 Register right = r0; 2223 Register right = r0;
2228 Register scratch1 = r7; 2224 Register scratch1 = r7;
2229 Register scratch2 = r9; 2225 Register scratch2 = r9;
2230 Register scratch3 = r4; 2226 Register scratch3 = r4;
2231 2227
2232 ASSERT(smi_operands || (not_numbers != NULL)); 2228 ASSERT(smi_operands || (not_numbers != NULL));
2233 if (smi_operands && FLAG_debug_code) { 2229 if (smi_operands && FLAG_debug_code) {
2234 __ AbortIfNotSmi(left); 2230 __ AbortIfNotSmi(left);
2235 __ AbortIfNotSmi(right); 2231 __ AbortIfNotSmi(right);
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
2426 default: 2422 default:
2427 UNREACHABLE(); 2423 UNREACHABLE();
2428 } 2424 }
2429 } 2425 }
2430 2426
2431 2427
2432 // Generate the smi code. If the operation on smis are successful this return is 2428 // Generate the smi code. If the operation on smis are successful this return is
2433 // generated. If the result is not a smi and heap number allocation is not 2429 // generated. If the result is not a smi and heap number allocation is not
2434 // requested the code falls through. If number allocation is requested but a 2430 // requested the code falls through. If number allocation is requested but a
2435 // heap number cannot be allocated the code jumps to the lable gc_required. 2431 // heap number cannot be allocated the code jumps to the lable gc_required.
2436 void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, 2432 void BinaryOpStub::GenerateSmiCode(
2433 MacroAssembler* masm,
2437 Label* use_runtime, 2434 Label* use_runtime,
2438 Label* gc_required, 2435 Label* gc_required,
2439 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { 2436 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
2440 Label not_smis; 2437 Label not_smis;
2441 2438
2442 Register left = r1; 2439 Register left = r1;
2443 Register right = r0; 2440 Register right = r0;
2444 Register scratch1 = r7; 2441 Register scratch1 = r7;
2445 Register scratch2 = r9; 2442 Register scratch2 = r9;
2446 2443
2447 // Perform combined smi check on both operands. 2444 // Perform combined smi check on both operands.
2448 __ orr(scratch1, left, Operand(right)); 2445 __ orr(scratch1, left, Operand(right));
2449 STATIC_ASSERT(kSmiTag == 0); 2446 STATIC_ASSERT(kSmiTag == 0);
2450 __ tst(scratch1, Operand(kSmiTagMask)); 2447 __ tst(scratch1, Operand(kSmiTagMask));
2451 __ b(ne, &not_smis); 2448 __ b(ne, &not_smis);
2452 2449
2453 // If the smi-smi operation results in a smi return is generated. 2450 // If the smi-smi operation results in a smi return is generated.
2454 GenerateSmiSmiOperation(masm); 2451 GenerateSmiSmiOperation(masm);
2455 2452
2456 // If heap number results are possible generate the result in an allocated 2453 // If heap number results are possible generate the result in an allocated
2457 // heap number. 2454 // heap number.
2458 if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) { 2455 if (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) {
2459 GenerateFPOperation(masm, true, use_runtime, gc_required); 2456 GenerateFPOperation(masm, true, use_runtime, gc_required);
2460 } 2457 }
2461 __ bind(&not_smis); 2458 __ bind(&not_smis);
2462 } 2459 }
2463 2460
2464 2461
2465 void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { 2462 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
2466 Label not_smis, call_runtime; 2463 Label not_smis, call_runtime;
2467 2464
2468 if (result_type_ == TRBinaryOpIC::UNINITIALIZED || 2465 if (result_type_ == BinaryOpIC::UNINITIALIZED ||
2469 result_type_ == TRBinaryOpIC::SMI) { 2466 result_type_ == BinaryOpIC::SMI) {
2470 // Only allow smi results. 2467 // Only allow smi results.
2471 GenerateSmiCode(masm, &call_runtime, NULL, NO_HEAPNUMBER_RESULTS); 2468 GenerateSmiCode(masm, &call_runtime, NULL, NO_HEAPNUMBER_RESULTS);
2472 } else { 2469 } else {
2473 // Allow heap number result and don't make a transition if a heap number 2470 // Allow heap number result and don't make a transition if a heap number
2474 // cannot be allocated. 2471 // cannot be allocated.
2475 GenerateSmiCode(masm, 2472 GenerateSmiCode(masm,
2476 &call_runtime, 2473 &call_runtime,
2477 &call_runtime, 2474 &call_runtime,
2478 ALLOW_HEAPNUMBER_RESULTS); 2475 ALLOW_HEAPNUMBER_RESULTS);
2479 } 2476 }
2480 2477
2481 // Code falls through if the result is not returned as either a smi or heap 2478 // Code falls through if the result is not returned as either a smi or heap
2482 // number. 2479 // number.
2483 GenerateTypeTransition(masm); 2480 GenerateTypeTransition(masm);
2484 2481
2485 __ bind(&call_runtime); 2482 __ bind(&call_runtime);
2486 GenerateCallRuntime(masm); 2483 GenerateCallRuntime(masm);
2487 } 2484 }
2488 2485
2489 2486
2490 void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) { 2487 void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
2491 ASSERT(operands_type_ == TRBinaryOpIC::STRING); 2488 ASSERT(operands_type_ == BinaryOpIC::STRING);
2492 ASSERT(op_ == Token::ADD); 2489 ASSERT(op_ == Token::ADD);
2493 // Try to add arguments as strings, otherwise, transition to the generic 2490 // Try to add arguments as strings, otherwise, transition to the generic
2494 // TRBinaryOpIC type. 2491 // BinaryOpIC type.
2495 GenerateAddStrings(masm); 2492 GenerateAddStrings(masm);
2496 GenerateTypeTransition(masm); 2493 GenerateTypeTransition(masm);
2497 } 2494 }
2498 2495
2499 2496
2500 void TypeRecordingBinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) { 2497 void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
2501 Label call_runtime; 2498 Label call_runtime;
2502 ASSERT(operands_type_ == TRBinaryOpIC::BOTH_STRING); 2499 ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING);
2503 ASSERT(op_ == Token::ADD); 2500 ASSERT(op_ == Token::ADD);
2504 // If both arguments are strings, call the string add stub. 2501 // If both arguments are strings, call the string add stub.
2505 // Otherwise, do a transition. 2502 // Otherwise, do a transition.
2506 2503
2507 // Registers containing left and right operands respectively. 2504 // Registers containing left and right operands respectively.
2508 Register left = r1; 2505 Register left = r1;
2509 Register right = r0; 2506 Register right = r0;
2510 2507
2511 // Test if left operand is a string. 2508 // Test if left operand is a string.
2512 __ JumpIfSmi(left, &call_runtime); 2509 __ JumpIfSmi(left, &call_runtime);
2513 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE); 2510 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE);
2514 __ b(ge, &call_runtime); 2511 __ b(ge, &call_runtime);
2515 2512
2516 // Test if right operand is a string. 2513 // Test if right operand is a string.
2517 __ JumpIfSmi(right, &call_runtime); 2514 __ JumpIfSmi(right, &call_runtime);
2518 __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE); 2515 __ CompareObjectType(right, r2, r2, FIRST_NONSTRING_TYPE);
2519 __ b(ge, &call_runtime); 2516 __ b(ge, &call_runtime);
2520 2517
2521 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); 2518 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB);
2522 GenerateRegisterArgsPush(masm); 2519 GenerateRegisterArgsPush(masm);
2523 __ TailCallStub(&string_add_stub); 2520 __ TailCallStub(&string_add_stub);
2524 2521
2525 __ bind(&call_runtime); 2522 __ bind(&call_runtime);
2526 GenerateTypeTransition(masm); 2523 GenerateTypeTransition(masm);
2527 } 2524 }
2528 2525
2529 2526
2530 void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { 2527 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
2531 ASSERT(operands_type_ == TRBinaryOpIC::INT32); 2528 ASSERT(operands_type_ == BinaryOpIC::INT32);
2532 2529
2533 Register left = r1; 2530 Register left = r1;
2534 Register right = r0; 2531 Register right = r0;
2535 Register scratch1 = r7; 2532 Register scratch1 = r7;
2536 Register scratch2 = r9; 2533 Register scratch2 = r9;
2537 DwVfpRegister double_scratch = d0; 2534 DwVfpRegister double_scratch = d0;
2538 SwVfpRegister single_scratch = s3; 2535 SwVfpRegister single_scratch = s3;
2539 2536
2540 Register heap_number_result = no_reg; 2537 Register heap_number_result = no_reg;
2541 Register heap_number_map = r6; 2538 Register heap_number_map = r6;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2618 // Try to return a smi if we can. 2615 // Try to return a smi if we can.
2619 // Otherwise return a heap number if allowed, or jump to type 2616 // Otherwise return a heap number if allowed, or jump to type
2620 // transition. 2617 // transition.
2621 2618
2622 __ EmitVFPTruncate(kRoundToZero, 2619 __ EmitVFPTruncate(kRoundToZero,
2623 single_scratch, 2620 single_scratch,
2624 d5, 2621 d5,
2625 scratch1, 2622 scratch1,
2626 scratch2); 2623 scratch2);
2627 2624
2628 if (result_type_ <= TRBinaryOpIC::INT32) { 2625 if (result_type_ <= BinaryOpIC::INT32) {
2629 // If the ne condition is set, result does 2626 // If the ne condition is set, result does
2630 // not fit in a 32-bit integer. 2627 // not fit in a 32-bit integer.
2631 __ b(ne, &transition); 2628 __ b(ne, &transition);
2632 } 2629 }
2633 2630
2634 // Check if the result fits in a smi. 2631 // Check if the result fits in a smi.
2635 __ vmov(scratch1, single_scratch); 2632 __ vmov(scratch1, single_scratch);
2636 __ add(scratch2, scratch1, Operand(0x40000000), SetCC); 2633 __ add(scratch2, scratch1, Operand(0x40000000), SetCC);
2637 // If not try to return a heap number. 2634 // If not try to return a heap number.
2638 __ b(mi, &return_heap_number); 2635 __ b(mi, &return_heap_number);
2639 // Check for minus zero. Return heap number for minus zero. 2636 // Check for minus zero. Return heap number for minus zero.
2640 Label not_zero; 2637 Label not_zero;
2641 __ cmp(scratch1, Operand(0)); 2638 __ cmp(scratch1, Operand(0));
2642 __ b(ne, &not_zero); 2639 __ b(ne, &not_zero);
2643 __ vmov(scratch2, d5.high()); 2640 __ vmov(scratch2, d5.high());
2644 __ tst(scratch2, Operand(HeapNumber::kSignMask)); 2641 __ tst(scratch2, Operand(HeapNumber::kSignMask));
2645 __ b(ne, &return_heap_number); 2642 __ b(ne, &return_heap_number);
2646 __ bind(&not_zero); 2643 __ bind(&not_zero);
2647 2644
2648 // Tag the result and return. 2645 // Tag the result and return.
2649 __ SmiTag(r0, scratch1); 2646 __ SmiTag(r0, scratch1);
2650 __ Ret(); 2647 __ Ret();
2651 } else { 2648 } else {
2652 // DIV just falls through to allocating a heap number. 2649 // DIV just falls through to allocating a heap number.
2653 } 2650 }
2654 2651
2655 if (result_type_ >= (op_ == Token::DIV) ? TRBinaryOpIC::HEAP_NUMBER 2652 if (result_type_ >= (op_ == Token::DIV) ? BinaryOpIC::HEAP_NUMBER
2656 : TRBinaryOpIC::INT32) { 2653 : BinaryOpIC::INT32) {
2657 __ bind(&return_heap_number); 2654 __ bind(&return_heap_number);
2658 // We are using vfp registers so r5 is available. 2655 // We are using vfp registers so r5 is available.
2659 heap_number_result = r5; 2656 heap_number_result = r5;
2660 GenerateHeapResultAllocation(masm, 2657 GenerateHeapResultAllocation(masm,
2661 heap_number_result, 2658 heap_number_result,
2662 heap_number_map, 2659 heap_number_map,
2663 scratch1, 2660 scratch1,
2664 scratch2, 2661 scratch2,
2665 &call_runtime); 2662 &call_runtime);
2666 __ sub(r0, heap_number_result, Operand(kHeapObjectTag)); 2663 __ sub(r0, heap_number_result, Operand(kHeapObjectTag));
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
2755 case Token::SHR: 2752 case Token::SHR:
2756 __ and_(r2, r2, Operand(0x1f)); 2753 __ and_(r2, r2, Operand(0x1f));
2757 __ mov(r2, Operand(r3, LSR, r2), SetCC); 2754 __ mov(r2, Operand(r3, LSR, r2), SetCC);
2758 // SHR is special because it is required to produce a positive answer. 2755 // SHR is special because it is required to produce a positive answer.
2759 // We only get a negative result if the shift value (r2) is 0. 2756 // We only get a negative result if the shift value (r2) is 0.
2760 // This result cannot be respresented as a signed 32-bit integer, try 2757 // This result cannot be respresented as a signed 32-bit integer, try
2761 // to return a heap number if we can. 2758 // to return a heap number if we can.
2762 // The non vfp3 code does not support this special case, so jump to 2759 // The non vfp3 code does not support this special case, so jump to
2763 // runtime if we don't support it. 2760 // runtime if we don't support it.
2764 if (CpuFeatures::IsSupported(VFP3)) { 2761 if (CpuFeatures::IsSupported(VFP3)) {
2765 __ b(mi, 2762 __ b(mi, (result_type_ <= BinaryOpIC::INT32)
2766 (result_type_ <= TRBinaryOpIC::INT32) ? &transition 2763 ? &transition
2767 : &return_heap_number); 2764 : &return_heap_number);
2768 } else { 2765 } else {
2769 __ b(mi, (result_type_ <= TRBinaryOpIC::INT32) ? &transition 2766 __ b(mi, (result_type_ <= BinaryOpIC::INT32)
2770 : &call_runtime); 2767 ? &transition
2768 : &call_runtime);
2771 } 2769 }
2772 break; 2770 break;
2773 case Token::SHL: 2771 case Token::SHL:
2774 __ and_(r2, r2, Operand(0x1f)); 2772 __ and_(r2, r2, Operand(0x1f));
2775 __ mov(r2, Operand(r3, LSL, r2)); 2773 __ mov(r2, Operand(r3, LSL, r2));
2776 break; 2774 break;
2777 default: 2775 default:
2778 UNREACHABLE(); 2776 UNREACHABLE();
2779 } 2777 }
2780 2778
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2830 if (transition.is_linked()) { 2828 if (transition.is_linked()) {
2831 __ bind(&transition); 2829 __ bind(&transition);
2832 GenerateTypeTransition(masm); 2830 GenerateTypeTransition(masm);
2833 } 2831 }
2834 2832
2835 __ bind(&call_runtime); 2833 __ bind(&call_runtime);
2836 GenerateCallRuntime(masm); 2834 GenerateCallRuntime(masm);
2837 } 2835 }
2838 2836
2839 2837
2840 void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) { 2838 void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
2841 Label call_runtime; 2839 Label call_runtime;
2842 2840
2843 if (op_ == Token::ADD) { 2841 if (op_ == Token::ADD) {
2844 // Handle string addition here, because it is the only operation 2842 // Handle string addition here, because it is the only operation
2845 // that does not do a ToNumber conversion on the operands. 2843 // that does not do a ToNumber conversion on the operands.
2846 GenerateAddStrings(masm); 2844 GenerateAddStrings(masm);
2847 } 2845 }
2848 2846
2849 // Convert oddball arguments to numbers. 2847 // Convert oddball arguments to numbers.
2850 Label check, done; 2848 Label check, done;
(...skipping 12 matching lines...) Expand all
2863 __ mov(r0, Operand(Smi::FromInt(0))); 2861 __ mov(r0, Operand(Smi::FromInt(0)));
2864 } else { 2862 } else {
2865 __ LoadRoot(r0, Heap::kNanValueRootIndex); 2863 __ LoadRoot(r0, Heap::kNanValueRootIndex);
2866 } 2864 }
2867 __ bind(&done); 2865 __ bind(&done);
2868 2866
2869 GenerateHeapNumberStub(masm); 2867 GenerateHeapNumberStub(masm);
2870 } 2868 }
2871 2869
2872 2870
2873 void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) { 2871 void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
2874 Label call_runtime; 2872 Label call_runtime;
2875 GenerateFPOperation(masm, false, &call_runtime, &call_runtime); 2873 GenerateFPOperation(masm, false, &call_runtime, &call_runtime);
2876 2874
2877 __ bind(&call_runtime); 2875 __ bind(&call_runtime);
2878 GenerateCallRuntime(masm); 2876 GenerateCallRuntime(masm);
2879 } 2877 }
2880 2878
2881 2879
2882 void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) { 2880 void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
2883 Label call_runtime, call_string_add_or_runtime; 2881 Label call_runtime, call_string_add_or_runtime;
2884 2882
2885 GenerateSmiCode(masm, &call_runtime, &call_runtime, ALLOW_HEAPNUMBER_RESULTS); 2883 GenerateSmiCode(masm, &call_runtime, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
2886 2884
2887 GenerateFPOperation(masm, false, &call_string_add_or_runtime, &call_runtime); 2885 GenerateFPOperation(masm, false, &call_string_add_or_runtime, &call_runtime);
2888 2886
2889 __ bind(&call_string_add_or_runtime); 2887 __ bind(&call_string_add_or_runtime);
2890 if (op_ == Token::ADD) { 2888 if (op_ == Token::ADD) {
2891 GenerateAddStrings(masm); 2889 GenerateAddStrings(masm);
2892 } 2890 }
2893 2891
2894 __ bind(&call_runtime); 2892 __ bind(&call_runtime);
2895 GenerateCallRuntime(masm); 2893 GenerateCallRuntime(masm);
2896 } 2894 }
2897 2895
2898 2896
2899 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { 2897 void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
2900 ASSERT(op_ == Token::ADD); 2898 ASSERT(op_ == Token::ADD);
2901 Label left_not_string, call_runtime; 2899 Label left_not_string, call_runtime;
2902 2900
2903 Register left = r1; 2901 Register left = r1;
2904 Register right = r0; 2902 Register right = r0;
2905 2903
2906 // Check if left argument is a string. 2904 // Check if left argument is a string.
2907 __ JumpIfSmi(left, &left_not_string); 2905 __ JumpIfSmi(left, &left_not_string);
2908 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE); 2906 __ CompareObjectType(left, r2, r2, FIRST_NONSTRING_TYPE);
2909 __ b(ge, &left_not_string); 2907 __ b(ge, &left_not_string);
(...skipping 10 matching lines...) Expand all
2920 2918
2921 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); 2919 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB);
2922 GenerateRegisterArgsPush(masm); 2920 GenerateRegisterArgsPush(masm);
2923 __ TailCallStub(&string_add_right_stub); 2921 __ TailCallStub(&string_add_right_stub);
2924 2922
2925 // At least one argument is not a string. 2923 // At least one argument is not a string.
2926 __ bind(&call_runtime); 2924 __ bind(&call_runtime);
2927 } 2925 }
2928 2926
2929 2927
2930 void TypeRecordingBinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) { 2928 void BinaryOpStub::GenerateCallRuntime(MacroAssembler* masm) {
2931 GenerateRegisterArgsPush(masm); 2929 GenerateRegisterArgsPush(masm);
2932 switch (op_) { 2930 switch (op_) {
2933 case Token::ADD: 2931 case Token::ADD:
2934 __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION); 2932 __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION);
2935 break; 2933 break;
2936 case Token::SUB: 2934 case Token::SUB:
2937 __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION); 2935 __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION);
2938 break; 2936 break;
2939 case Token::MUL: 2937 case Token::MUL:
2940 __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION); 2938 __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION);
(...skipping 21 matching lines...) Expand all
2962 break; 2960 break;
2963 case Token::SHL: 2961 case Token::SHL:
2964 __ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION); 2962 __ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION);
2965 break; 2963 break;
2966 default: 2964 default:
2967 UNREACHABLE(); 2965 UNREACHABLE();
2968 } 2966 }
2969 } 2967 }
2970 2968
2971 2969
2972 void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation( 2970 void BinaryOpStub::GenerateHeapResultAllocation(MacroAssembler* masm,
2973 MacroAssembler* masm, 2971 Register result,
2974 Register result, 2972 Register heap_number_map,
2975 Register heap_number_map, 2973 Register scratch1,
2976 Register scratch1, 2974 Register scratch2,
2977 Register scratch2, 2975 Label* gc_required) {
2978 Label* gc_required) {
2979
2980 // Code below will scratch result if allocation fails. To keep both arguments 2976 // Code below will scratch result if allocation fails. To keep both arguments
2981 // intact for the runtime call result cannot be one of these. 2977 // intact for the runtime call result cannot be one of these.
2982 ASSERT(!result.is(r0) && !result.is(r1)); 2978 ASSERT(!result.is(r0) && !result.is(r1));
2983 2979
2984 if (mode_ == OVERWRITE_LEFT || mode_ == OVERWRITE_RIGHT) { 2980 if (mode_ == OVERWRITE_LEFT || mode_ == OVERWRITE_RIGHT) {
2985 Label skip_allocation, allocated; 2981 Label skip_allocation, allocated;
2986 Register overwritable_operand = mode_ == OVERWRITE_LEFT ? r1 : r0; 2982 Register overwritable_operand = mode_ == OVERWRITE_LEFT ? r1 : r0;
2987 // If the overwritable operand is already an object, we skip the 2983 // If the overwritable operand is already an object, we skip the
2988 // allocation of a heap number. 2984 // allocation of a heap number.
2989 __ JumpIfNotSmi(overwritable_operand, &skip_allocation); 2985 __ JumpIfNotSmi(overwritable_operand, &skip_allocation);
2990 // Allocate a heap number for the result. 2986 // Allocate a heap number for the result.
2991 __ AllocateHeapNumber( 2987 __ AllocateHeapNumber(
2992 result, scratch1, scratch2, heap_number_map, gc_required); 2988 result, scratch1, scratch2, heap_number_map, gc_required);
2993 __ b(&allocated); 2989 __ b(&allocated);
2994 __ bind(&skip_allocation); 2990 __ bind(&skip_allocation);
2995 // Use object holding the overwritable operand for result. 2991 // Use object holding the overwritable operand for result.
2996 __ mov(result, Operand(overwritable_operand)); 2992 __ mov(result, Operand(overwritable_operand));
2997 __ bind(&allocated); 2993 __ bind(&allocated);
2998 } else { 2994 } else {
2999 ASSERT(mode_ == NO_OVERWRITE); 2995 ASSERT(mode_ == NO_OVERWRITE);
3000 __ AllocateHeapNumber( 2996 __ AllocateHeapNumber(
3001 result, scratch1, scratch2, heap_number_map, gc_required); 2997 result, scratch1, scratch2, heap_number_map, gc_required);
3002 } 2998 }
3003 } 2999 }
3004 3000
3005 3001
3006 void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { 3002 void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
3007 __ Push(r1, r0); 3003 __ Push(r1, r0);
3008 } 3004 }
3009 3005
3010 3006
3011 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { 3007 void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
3012 // Untagged case: double input in d2, double result goes 3008 // Untagged case: double input in d2, double result goes
3013 // into d2. 3009 // into d2.
3014 // Tagged case: tagged input on top of stack and in r0, 3010 // Tagged case: tagged input on top of stack and in r0,
3015 // tagged result (heap number) goes into r0. 3011 // tagged result (heap number) goes into r0.
3016 3012
(...skipping 3372 matching lines...) Expand 10 before | Expand all | Expand 10 after
6389 __ mov(result, Operand(0)); 6385 __ mov(result, Operand(0));
6390 __ Ret(); 6386 __ Ret();
6391 } 6387 }
6392 6388
6393 6389
6394 #undef __ 6390 #undef __
6395 6391
6396 } } // namespace v8::internal 6392 } } // namespace v8::internal
6397 6393
6398 #endif // V8_TARGET_ARCH_ARM 6394 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/code-stubs-arm.h ('k') | src/arm/full-codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698