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