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 1795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1806 __ bind(&miss); | 1806 __ bind(&miss); |
1807 // ecx: function name. | 1807 // ecx: function name. |
1808 Object* obj = GenerateMissBranch(); | 1808 Object* obj = GenerateMissBranch(); |
1809 if (obj->IsFailure()) return obj; | 1809 if (obj->IsFailure()) return obj; |
1810 | 1810 |
1811 // Return the generated code. | 1811 // Return the generated code. |
1812 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 1812 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); |
1813 } | 1813 } |
1814 | 1814 |
1815 | 1815 |
1816 Object* CallStubCompiler::CompileMathFloorCall(Object* object, | |
1817 JSObject* holder, | |
1818 JSGlobalPropertyCell* cell, | |
1819 JSFunction* function, | |
1820 String* name) { | |
1821 // ----------- S t a t e ------------- | |
1822 // -- ecx : name | |
1823 // -- esp[0] : return address | |
1824 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | |
1825 // -- ... | |
1826 // -- esp[(argc + 1) * 4] : receiver | |
1827 // ----------------------------------- | |
1828 | |
1829 if (!CpuFeatures::IsSupported(SSE2)) return Heap::undefined_value(); | |
1830 CpuFeatures::Scope use_sse2(SSE2); | |
1831 | |
1832 const int argc = arguments().immediate(); | |
1833 | |
1834 // If the object is not a JSObject or we got an unexpected number of | |
1835 // arguments, bail out to the regular call. | |
1836 if (!object->IsJSObject() || argc != 1) return Heap::undefined_value(); | |
1837 | |
1838 Label miss; | |
1839 GenerateNameCheck(name, &miss); | |
1840 | |
1841 if (cell == NULL) { | |
1842 __ mov(edx, Operand(esp, 2 * kPointerSize)); | |
1843 | |
1844 STATIC_ASSERT(kSmiTag == 0); | |
1845 __ test(edx, Immediate(kSmiTagMask)); | |
1846 __ j(zero, &miss); | |
1847 | |
1848 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | |
1849 &miss); | |
1850 } else { | |
1851 ASSERT(cell->value() == function); | |
1852 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | |
1853 GenerateLoadFunctionFromCell(cell, function, &miss); | |
1854 } | |
1855 | |
1856 // Load the (only) argument into eax. | |
1857 __ mov(eax, Operand(esp, 1 * kPointerSize)); | |
1858 | |
1859 // Check if the argument is a smi. | |
1860 Label smi; | |
1861 STATIC_ASSERT(kSmiTag == 0); | |
1862 __ test(eax, Immediate(kSmiTagMask)); | |
1863 __ j(zero, &smi); | |
1864 | |
1865 // Check if the argument is a heap number and load its value into xmm0. | |
1866 Label slow; | |
1867 __ CheckMap(eax, Factory::heap_number_map(), &slow, true); | |
1868 __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); | |
1869 | |
1870 // Check if the argument is strictly positive. Note this also | |
1871 // discards NaN. | |
Erik Corry
2010/09/20 11:56:50
It might be nice to detect +- zero and pass it thr
Vitaly Repeshko
2010/09/21 12:54:49
I filed a bug to consider extending it.
| |
1872 __ xorpd(xmm1, xmm1); | |
1873 __ ucomisd(xmm0, xmm1); | |
1874 __ j(below_equal, &slow); | |
1875 | |
1876 // Do a truncating conversion. | |
1877 __ cvttsd2si(eax, Operand(xmm0)); | |
1878 | |
1879 // Check if the result fits into a smi. Note this also checks for | |
1880 // 0x80000000 which signals a failed conversion. | |
1881 Label wont_fit_into_smi; | |
1882 __ test(eax, Immediate(0xc0000000)); | |
1883 __ j(not_zero, &wont_fit_into_smi); | |
1884 | |
1885 // Smi tag and return. | |
1886 __ SmiTag(eax); | |
1887 __ bind(&smi); | |
1888 __ ret(2 * kPointerSize); | |
1889 | |
1890 // Check if the argument is < 2^kMantissaBits. | |
1891 Label already_round; | |
1892 __ bind(&wont_fit_into_smi); | |
1893 __ LoadPowerOf2(xmm1, ebx, HeapNumber::kMantissaBits); | |
1894 __ ucomisd(xmm0, xmm1); | |
1895 __ j(above_equal, &already_round); | |
1896 | |
1897 // Save a copy of the argument. | |
1898 __ movaps(xmm2, Operand(xmm0)); | |
1899 | |
1900 // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits. | |
1901 __ addsd(xmm0, xmm1); | |
1902 __ subsd(xmm0, xmm1); | |
1903 | |
1904 // Compare the argument and the tentative result to get the right mask: | |
1905 // if xmm2 < xmm0: | |
1906 // xmm2 = 1...1 | |
1907 // else: | |
1908 // xmm2 = 0...0 | |
1909 __ cmpltsd(xmm2, xmm0); | |
1910 | |
1911 // Subtract 1 if the argument was less than the tentative result. | |
1912 __ LoadPowerOf2(xmm1, ebx, 0); | |
1913 __ andpd(xmm1, Operand(xmm2)); | |
1914 __ subsd(xmm0, xmm1); | |
1915 | |
1916 // Return a new heap number. | |
1917 __ AllocateHeapNumber(eax, ebx, edx, &slow); | |
1918 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | |
1919 __ ret(2 * kPointerSize); | |
1920 | |
1921 // Return the argument (when it's an already round heap number). | |
1922 __ bind(&already_round); | |
1923 __ mov(eax, Operand(esp, 1 * kPointerSize)); | |
1924 __ ret(2 * kPointerSize); | |
1925 | |
1926 // Tail call the full function. We do not have to patch the receiver | |
1927 // because the function makes no use of it. | |
1928 __ bind(&slow); | |
1929 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | |
1930 | |
1931 __ bind(&miss); | |
1932 // ecx: function name. | |
1933 Object* obj = GenerateMissBranch(); | |
1934 if (obj->IsFailure()) return obj; | |
1935 | |
1936 // Return the generated code. | |
1937 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | |
1938 } | |
1939 | |
1940 | |
1816 Object* CallStubCompiler::CompileCallConstant(Object* object, | 1941 Object* CallStubCompiler::CompileCallConstant(Object* object, |
1817 JSObject* holder, | 1942 JSObject* holder, |
1818 JSFunction* function, | 1943 JSFunction* function, |
1819 String* name, | 1944 String* name, |
1820 CheckType check) { | 1945 CheckType check) { |
1821 // ----------- S t a t e ------------- | 1946 // ----------- S t a t e ------------- |
1822 // -- ecx : name | 1947 // -- ecx : name |
1823 // -- esp[0] : return address | 1948 // -- esp[0] : return address |
1824 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1949 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1825 // -- ... | 1950 // -- ... |
(...skipping 994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2820 // Return the generated code. | 2945 // Return the generated code. |
2821 return GetCode(); | 2946 return GetCode(); |
2822 } | 2947 } |
2823 | 2948 |
2824 | 2949 |
2825 #undef __ | 2950 #undef __ |
2826 | 2951 |
2827 } } // namespace v8::internal | 2952 } } // namespace v8::internal |
2828 | 2953 |
2829 #endif // V8_TARGET_ARCH_IA32 | 2954 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |