OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
(...skipping 1755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1766 // The function is a "classConstructor", need to raise an exception. | 1766 // The function is a "classConstructor", need to raise an exception. |
1767 __ bind(&class_constructor); | 1767 __ bind(&class_constructor); |
1768 { | 1768 { |
1769 FrameScope frame(masm, StackFrame::INTERNAL); | 1769 FrameScope frame(masm, StackFrame::INTERNAL); |
1770 __ push(edi); | 1770 __ push(edi); |
1771 __ CallRuntime(Runtime::kThrowConstructorNonCallableError, 1); | 1771 __ CallRuntime(Runtime::kThrowConstructorNonCallableError, 1); |
1772 } | 1772 } |
1773 } | 1773 } |
1774 | 1774 |
1775 | 1775 |
| 1776 namespace { |
| 1777 |
| 1778 void Generate_PushBoundArguments(MacroAssembler* masm) { |
| 1779 // ----------- S t a t e ------------- |
| 1780 // -- eax : the number of arguments (not including the receiver) |
| 1781 // -- edx : new.target (only in case of [[Construct]]) |
| 1782 // -- edi : target (checked to be a JSBoundFunction) |
| 1783 // ----------------------------------- |
| 1784 |
| 1785 // Load [[BoundArguments]] into ecx and length of that into ebx. |
| 1786 Label no_bound_arguments; |
| 1787 __ mov(ecx, FieldOperand(edi, JSBoundFunction::kBoundArgumentsOffset)); |
| 1788 __ mov(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); |
| 1789 __ SmiUntag(ebx); |
| 1790 __ test(ebx, ebx); |
| 1791 __ j(zero, &no_bound_arguments); |
| 1792 { |
| 1793 // ----------- S t a t e ------------- |
| 1794 // -- eax : the number of arguments (not including the receiver) |
| 1795 // -- edx : new.target (only in case of [[Construct]]) |
| 1796 // -- edi : target (checked to be a JSBoundFunction) |
| 1797 // -- ecx : the [[BoundArguments]] (implemented as FixedArray) |
| 1798 // -- ebx : the number of [[BoundArguments]] |
| 1799 // ----------------------------------- |
| 1800 |
| 1801 // Reserve stack space for the [[BoundArguments]]. |
| 1802 { |
| 1803 Label done; |
| 1804 __ lea(ecx, Operand(ebx, times_pointer_size, 0)); |
| 1805 __ sub(esp, ecx); |
| 1806 // Check the stack for overflow. We are not trying to catch interruptions |
| 1807 // (i.e. debug break and preemption) here, so check the "real stack |
| 1808 // limit". |
| 1809 __ CompareRoot(esp, ecx, Heap::kRealStackLimitRootIndex); |
| 1810 __ j(greater, &done, Label::kNear); // Signed comparison. |
| 1811 // Restore the stack pointer. |
| 1812 __ lea(esp, Operand(esp, ebx, times_pointer_size, 0)); |
| 1813 { |
| 1814 FrameScope scope(masm, StackFrame::MANUAL); |
| 1815 __ EnterFrame(StackFrame::INTERNAL); |
| 1816 __ CallRuntime(Runtime::kThrowStackOverflow, 0); |
| 1817 } |
| 1818 __ bind(&done); |
| 1819 } |
| 1820 |
| 1821 // Adjust effective number of arguments to include return address. |
| 1822 __ inc(eax); |
| 1823 |
| 1824 // Relocate arguments and return address down the stack. |
| 1825 { |
| 1826 Label loop; |
| 1827 __ Set(ecx, 0); |
| 1828 __ lea(ebx, Operand(esp, ebx, times_pointer_size, 0)); |
| 1829 __ bind(&loop); |
| 1830 __ fld_s(Operand(ebx, ecx, times_pointer_size, 0)); |
| 1831 __ fstp_s(Operand(esp, ecx, times_pointer_size, 0)); |
| 1832 __ inc(ecx); |
| 1833 __ cmp(ecx, eax); |
| 1834 __ j(less, &loop); |
| 1835 } |
| 1836 |
| 1837 // Copy [[BoundArguments]] to the stack (below the arguments). |
| 1838 { |
| 1839 Label loop; |
| 1840 __ mov(ecx, FieldOperand(edi, JSBoundFunction::kBoundArgumentsOffset)); |
| 1841 __ mov(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); |
| 1842 __ SmiUntag(ebx); |
| 1843 __ bind(&loop); |
| 1844 __ dec(ebx); |
| 1845 __ fld_s( |
| 1846 FieldOperand(ecx, ebx, times_pointer_size, FixedArray::kHeaderSize)); |
| 1847 __ fstp_s(Operand(esp, eax, times_pointer_size, 0)); |
| 1848 __ lea(eax, Operand(eax, 1)); |
| 1849 __ j(greater, &loop); |
| 1850 } |
| 1851 |
| 1852 // Adjust effective number of arguments (eax contains the number of |
| 1853 // arguments from the call plus return address plus the number of |
| 1854 // [[BoundArguments]]), so we need to subtract one for the return address. |
| 1855 __ dec(eax); |
| 1856 } |
| 1857 __ bind(&no_bound_arguments); |
| 1858 } |
| 1859 |
| 1860 } // namespace |
| 1861 |
| 1862 |
| 1863 // static |
| 1864 void Builtins::Generate_CallBoundFunction(MacroAssembler* masm) { |
| 1865 // ----------- S t a t e ------------- |
| 1866 // -- eax : the number of arguments (not including the receiver) |
| 1867 // -- edi : the function to call (checked to be a JSBoundFunction) |
| 1868 // ----------------------------------- |
| 1869 __ AssertBoundFunction(edi); |
| 1870 |
| 1871 // Patch the receiver to [[BoundThis]]. |
| 1872 __ mov(ebx, FieldOperand(edi, JSBoundFunction::kBoundThisOffset)); |
| 1873 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), ebx); |
| 1874 |
| 1875 // Push the [[BoundArguments]] onto the stack. |
| 1876 Generate_PushBoundArguments(masm); |
| 1877 |
| 1878 // Call the [[BoundTargetFunction]] via the Call builtin. |
| 1879 __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); |
| 1880 __ mov(ecx, Operand::StaticVariable(ExternalReference( |
| 1881 Builtins::kCall_ReceiverIsAny, masm->isolate()))); |
| 1882 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |
| 1883 __ jmp(ecx); |
| 1884 } |
| 1885 |
| 1886 |
1776 // static | 1887 // static |
1777 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { | 1888 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { |
1778 // ----------- S t a t e ------------- | 1889 // ----------- S t a t e ------------- |
1779 // -- eax : the number of arguments (not including the receiver) | 1890 // -- eax : the number of arguments (not including the receiver) |
1780 // -- edi : the target to call (can be any Object). | 1891 // -- edi : the target to call (can be any Object). |
1781 // ----------------------------------- | 1892 // ----------------------------------- |
1782 | 1893 |
1783 Label non_callable, non_function, non_smi; | 1894 Label non_callable, non_function, non_smi; |
1784 __ JumpIfSmi(edi, &non_callable); | 1895 __ JumpIfSmi(edi, &non_callable); |
1785 __ bind(&non_smi); | 1896 __ bind(&non_smi); |
1786 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 1897 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
1787 __ j(equal, masm->isolate()->builtins()->CallFunction(mode), | 1898 __ j(equal, masm->isolate()->builtins()->CallFunction(mode), |
1788 RelocInfo::CODE_TARGET); | 1899 RelocInfo::CODE_TARGET); |
| 1900 __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); |
| 1901 __ j(equal, masm->isolate()->builtins()->CallBoundFunction(), |
| 1902 RelocInfo::CODE_TARGET); |
1789 __ CmpInstanceType(ecx, JS_PROXY_TYPE); | 1903 __ CmpInstanceType(ecx, JS_PROXY_TYPE); |
1790 __ j(not_equal, &non_function); | 1904 __ j(not_equal, &non_function); |
1791 | 1905 |
1792 // 1. Runtime fallback for Proxy [[Call]]. | 1906 // 1. Runtime fallback for Proxy [[Call]]. |
1793 __ PopReturnAddressTo(ecx); | 1907 __ PopReturnAddressTo(ecx); |
1794 __ Push(edi); | 1908 __ Push(edi); |
1795 __ PushReturnAddressFrom(ecx); | 1909 __ PushReturnAddressFrom(ecx); |
1796 // Increase the arguments size to include the pushed function and the | 1910 // Increase the arguments size to include the pushed function and the |
1797 // existing receiver on the stack. | 1911 // existing receiver on the stack. |
1798 __ add(eax, Immediate(2)); | 1912 __ add(eax, Immediate(2)); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1840 // Tail call to the function-specific construct stub (still in the caller | 1954 // Tail call to the function-specific construct stub (still in the caller |
1841 // context at this point). | 1955 // context at this point). |
1842 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 1956 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
1843 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); | 1957 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); |
1844 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); | 1958 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |
1845 __ jmp(ecx); | 1959 __ jmp(ecx); |
1846 } | 1960 } |
1847 | 1961 |
1848 | 1962 |
1849 // static | 1963 // static |
| 1964 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { |
| 1965 // ----------- S t a t e ------------- |
| 1966 // -- eax : the number of arguments (not including the receiver) |
| 1967 // -- edx : the new target (checked to be a constructor) |
| 1968 // -- edi : the constructor to call (checked to be a JSBoundFunction) |
| 1969 // ----------------------------------- |
| 1970 __ AssertBoundFunction(edi); |
| 1971 |
| 1972 // Push the [[BoundArguments]] onto the stack. |
| 1973 Generate_PushBoundArguments(masm); |
| 1974 |
| 1975 // Patch new.target to [[BoundTargetFunction]] if new.target equals target. |
| 1976 { |
| 1977 Label done; |
| 1978 __ cmp(edi, edx); |
| 1979 __ j(not_equal, &done, Label::kNear); |
| 1980 __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); |
| 1981 __ bind(&done); |
| 1982 } |
| 1983 |
| 1984 // Construct the [[BoundTargetFunction]] via the Construct builtin. |
| 1985 __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); |
| 1986 __ mov(ecx, Operand::StaticVariable( |
| 1987 ExternalReference(Builtins::kConstruct, masm->isolate()))); |
| 1988 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |
| 1989 __ jmp(ecx); |
| 1990 } |
| 1991 |
| 1992 |
| 1993 // static |
1850 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { | 1994 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { |
1851 // ----------- S t a t e ------------- | 1995 // ----------- S t a t e ------------- |
1852 // -- eax : the number of arguments (not including the receiver) | 1996 // -- eax : the number of arguments (not including the receiver) |
1853 // -- edi : the constructor to call (checked to be a JSProxy) | 1997 // -- edi : the constructor to call (checked to be a JSProxy) |
1854 // -- edx : the new target (either the same as the constructor or | 1998 // -- edx : the new target (either the same as the constructor or |
1855 // the JSFunction on which new was invoked initially) | 1999 // the JSFunction on which new was invoked initially) |
1856 // ----------------------------------- | 2000 // ----------------------------------- |
1857 | 2001 |
1858 // Call into the Runtime for Proxy [[Construct]]. | 2002 // Call into the Runtime for Proxy [[Construct]]. |
1859 __ PopReturnAddressTo(ecx); | 2003 __ PopReturnAddressTo(ecx); |
(...skipping 23 matching lines...) Expand all Loading... |
1883 | 2027 |
1884 // Dispatch based on instance type. | 2028 // Dispatch based on instance type. |
1885 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 2029 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
1886 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), | 2030 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), |
1887 RelocInfo::CODE_TARGET); | 2031 RelocInfo::CODE_TARGET); |
1888 | 2032 |
1889 // Check if target has a [[Construct]] internal method. | 2033 // Check if target has a [[Construct]] internal method. |
1890 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor); | 2034 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor); |
1891 __ j(zero, &non_constructor, Label::kNear); | 2035 __ j(zero, &non_constructor, Label::kNear); |
1892 | 2036 |
| 2037 // Only dispatch to bound functions after checking whether they are |
| 2038 // constructors. |
| 2039 __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); |
| 2040 __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(), |
| 2041 RelocInfo::CODE_TARGET); |
| 2042 |
1893 // Only dispatch to proxies after checking whether they are constructors. | 2043 // Only dispatch to proxies after checking whether they are constructors. |
1894 __ CmpInstanceType(ecx, JS_PROXY_TYPE); | 2044 __ CmpInstanceType(ecx, JS_PROXY_TYPE); |
1895 __ j(equal, masm->isolate()->builtins()->ConstructProxy(), | 2045 __ j(equal, masm->isolate()->builtins()->ConstructProxy(), |
1896 RelocInfo::CODE_TARGET); | 2046 RelocInfo::CODE_TARGET); |
1897 | 2047 |
1898 // Called Construct on an exotic Object with a [[Construct]] internal method. | 2048 // Called Construct on an exotic Object with a [[Construct]] internal method. |
1899 { | 2049 { |
1900 // Overwrite the original receiver with the (original) target. | 2050 // Overwrite the original receiver with the (original) target. |
1901 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); | 2051 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); |
1902 // Let the "call_as_constructor_delegate" take care of the rest. | 2052 // Let the "call_as_constructor_delegate" take care of the rest. |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2223 | 2373 |
2224 __ bind(&ok); | 2374 __ bind(&ok); |
2225 __ ret(0); | 2375 __ ret(0); |
2226 } | 2376 } |
2227 | 2377 |
2228 #undef __ | 2378 #undef __ |
2229 } // namespace internal | 2379 } // namespace internal |
2230 } // namespace v8 | 2380 } // namespace v8 |
2231 | 2381 |
2232 #endif // V8_TARGET_ARCH_X87 | 2382 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |