Chromium Code Reviews| 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 |