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 1749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 // static | 1769 // static |
| 1770 void Builtins::Generate_CallBoundFunction(MacroAssembler* masm) { |
| 1771 // ----------- S t a t e ------------- |
| 1772 // -- eax : the number of arguments (not including the receiver) |
| 1773 // -- edi : the function to call (checked to be a JSBoundFunction) |
| 1774 // ----------------------------------- |
| 1775 __ AssertBoundFunction(edi); |
| 1776 |
| 1777 // Patch the receiver to [[BoundThis]]. |
| 1778 { |
| 1779 __ mov(ebx, FieldOperand(edi, JSBoundFunction::kBoundThisOffset)); |
| 1780 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), ebx); |
| 1781 } |
| 1782 |
| 1783 // Load [[BoundArguments]] into edx and length of that into ecx. |
| 1784 __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundArgumentsOffset)); |
| 1785 __ mov(ecx, FieldOperand(edx, FixedArray::kLengthOffset)); |
| 1786 __ SmiUntag(ecx); |
| 1787 |
| 1788 // ----------- S t a t e ------------- |
| 1789 // -- eax : the number of arguments (not including the receiver) |
| 1790 // -- edi : the function to call (checked to be a JSBoundFunction) |
| 1791 // -- edx : the [[BoundArguments]] (implemented as FixedArray) |
| 1792 // -- ecx : the number of [[BoundArguments]] |
| 1793 // ----------------------------------- |
| 1794 |
| 1795 // Reserve stack space for the [[BoundArguments]]. |
| 1796 { |
| 1797 Label done; |
| 1798 __ lea(ebx, Operand(ecx, times_pointer_size, 0)); |
| 1799 __ sub(esp, ebx); |
| 1800 // Check the stack for overflow. We are not trying to catch interruptions |
| 1801 // (i.e. debug break and preemption) here, so check the "real stack limit". |
| 1802 __ CompareRoot(esp, ebx, Heap::kRealStackLimitRootIndex); |
| 1803 __ j(greater, &done, Label::kNear); // Signed comparison. |
| 1804 // Restore the stack pointer. |
| 1805 __ lea(esp, Operand(esp, ecx, 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 // Relocate arguments and return address down the stack. |
| 1815 { |
| 1816 Label loop; |
| 1817 __ inc(eax); // arguments plus return address |
| 1818 __ Set(ebx, 0); |
| 1819 __ bind(&loop); |
| 1820 __ movd(xmm0, Operand(esp, ecx, times_pointer_size, 0)); |
| 1821 __ inc(ecx); |
| 1822 __ movd(Operand(esp, ebx, times_pointer_size, 0), xmm0); |
| 1823 __ inc(ebx); |
| 1824 __ cmp(ebx, eax); |
| 1825 __ j(less, &loop); |
| 1826 } |
| 1827 |
| 1828 // Copy [[BoundArguments]] to the stack (below the arguments). |
| 1829 { |
| 1830 Label loop, done_loop; |
| 1831 __ mov(ecx, FieldOperand(edx, FixedArray::kLengthOffset)); |
| 1832 __ SmiUntag(ecx); |
| 1833 __ bind(&loop); |
| 1834 __ sub(ecx, Immediate(1)); |
| 1835 __ j(less, &done_loop, Label::kNear); |
| 1836 __ mov(ebx, |
| 1837 FieldOperand(edx, ecx, times_pointer_size, FixedArray::kHeaderSize)); |
| 1838 __ mov(Operand(esp, eax, times_pointer_size, 0), ebx); |
| 1839 __ inc(eax); |
| 1840 __ jmp(&loop); |
| 1841 __ bind(&done_loop); |
| 1842 } |
| 1843 |
| 1844 // Adjust effective number of arguments (eax contains the number of arguments |
| 1845 // from the call plus return address plus the number of [[BoundArguments]]), |
| 1846 // so we need to subtract one for the return address. |
| 1847 __ dec(eax); |
| 1848 |
| 1849 // Call the [[BoundTargetFunction]] via the Call builtin. |
| 1850 __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); |
| 1851 __ mov(ecx, Operand::StaticVariable(ExternalReference( |
| 1852 Builtins::kCall_ReceiverIsAny, masm->isolate()))); |
| 1853 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |
| 1854 __ jmp(ecx); |
| 1855 } |
| 1856 |
| 1857 |
| 1858 // static |
1770 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { | 1859 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { |
1771 // ----------- S t a t e ------------- | 1860 // ----------- S t a t e ------------- |
1772 // -- eax : the number of arguments (not including the receiver) | 1861 // -- eax : the number of arguments (not including the receiver) |
1773 // -- edi : the target to call (can be any Object). | 1862 // -- edi : the target to call (can be any Object). |
1774 // ----------------------------------- | 1863 // ----------------------------------- |
1775 | 1864 |
1776 Label non_callable, non_function, non_smi; | 1865 Label non_callable, non_function, non_smi; |
1777 __ JumpIfSmi(edi, &non_callable); | 1866 __ JumpIfSmi(edi, &non_callable); |
1778 __ bind(&non_smi); | 1867 __ bind(&non_smi); |
1779 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 1868 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
1780 __ j(equal, masm->isolate()->builtins()->CallFunction(mode), | 1869 __ j(equal, masm->isolate()->builtins()->CallFunction(mode), |
1781 RelocInfo::CODE_TARGET); | 1870 RelocInfo::CODE_TARGET); |
| 1871 __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); |
| 1872 __ j(equal, masm->isolate()->builtins()->CallBoundFunction(), |
| 1873 RelocInfo::CODE_TARGET); |
1782 __ CmpInstanceType(ecx, JS_PROXY_TYPE); | 1874 __ CmpInstanceType(ecx, JS_PROXY_TYPE); |
1783 __ j(not_equal, &non_function); | 1875 __ j(not_equal, &non_function); |
1784 | 1876 |
1785 // 1. Runtime fallback for Proxy [[Call]]. | 1877 // 1. Runtime fallback for Proxy [[Call]]. |
1786 __ PopReturnAddressTo(ecx); | 1878 __ PopReturnAddressTo(ecx); |
1787 __ Push(edi); | 1879 __ Push(edi); |
1788 __ PushReturnAddressFrom(ecx); | 1880 __ PushReturnAddressFrom(ecx); |
1789 // Increase the arguments size to include the pushed function and the | 1881 // Increase the arguments size to include the pushed function and the |
1790 // existing receiver on the stack. | 1882 // existing receiver on the stack. |
1791 __ add(eax, Immediate(2)); | 1883 __ add(eax, Immediate(2)); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1833 // Tail call to the function-specific construct stub (still in the caller | 1925 // Tail call to the function-specific construct stub (still in the caller |
1834 // context at this point). | 1926 // context at this point). |
1835 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 1927 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
1836 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); | 1928 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); |
1837 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); | 1929 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |
1838 __ jmp(ecx); | 1930 __ jmp(ecx); |
1839 } | 1931 } |
1840 | 1932 |
1841 | 1933 |
1842 // static | 1934 // static |
| 1935 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { |
| 1936 // ----------- S t a t e ------------- |
| 1937 // -- eax : the number of arguments (not including the receiver) |
| 1938 // -- edx : the new target (checked to be a constructor) |
| 1939 // -- edi : the constructor to call (checked to be a JSBoundFunction) |
| 1940 // ----------------------------------- |
| 1941 __ AssertBoundFunction(edi); |
| 1942 |
| 1943 // Save new.target in receiver slot, which is unused for [[Construct]]. |
| 1944 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edx); |
| 1945 |
| 1946 // Load [[BoundArguments]] into edx and length of that into ecx. |
| 1947 __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundArgumentsOffset)); |
| 1948 __ mov(ecx, FieldOperand(edx, FixedArray::kLengthOffset)); |
| 1949 __ SmiUntag(ecx); |
| 1950 |
| 1951 // ----------- S t a t e ------------- |
| 1952 // -- eax : the number of arguments (not including the receiver) |
| 1953 // -- edi : the function to call (checked to be a JSBoundFunction) |
| 1954 // -- edx : the [[BoundArguments]] (implemented as FixedArray) |
| 1955 // -- ecx : the number of [[BoundArguments]] |
| 1956 // ----------------------------------- |
| 1957 |
| 1958 // Reserve stack space for the [[BoundArguments]]. |
| 1959 { |
| 1960 Label done; |
| 1961 __ lea(ebx, Operand(ecx, times_pointer_size, 0)); |
| 1962 __ sub(esp, ebx); |
| 1963 // Check the stack for overflow. We are not trying to catch interruptions |
| 1964 // (i.e. debug break and preemption) here, so check the "real stack limit". |
| 1965 __ CompareRoot(esp, ebx, Heap::kRealStackLimitRootIndex); |
| 1966 __ j(greater, &done, Label::kNear); // Signed comparison. |
| 1967 // Restore the stack pointer. |
| 1968 __ lea(esp, Operand(esp, ecx, times_pointer_size, 0)); |
| 1969 { |
| 1970 FrameScope scope(masm, StackFrame::MANUAL); |
| 1971 __ EnterFrame(StackFrame::INTERNAL); |
| 1972 __ CallRuntime(Runtime::kThrowStackOverflow, 0); |
| 1973 } |
| 1974 __ bind(&done); |
| 1975 } |
| 1976 |
| 1977 // Relocate arguments and return address down the stack. |
| 1978 { |
| 1979 Label loop; |
| 1980 __ inc(eax); // arguments plus return address |
| 1981 __ Set(ebx, 0); |
| 1982 __ bind(&loop); |
| 1983 __ movd(xmm0, Operand(esp, ecx, times_pointer_size, 0)); |
| 1984 __ inc(ecx); |
| 1985 __ movd(Operand(esp, ebx, times_pointer_size, 0), xmm0); |
| 1986 __ inc(ebx); |
| 1987 __ cmp(ebx, eax); |
| 1988 __ j(less, &loop); |
| 1989 } |
| 1990 |
| 1991 // Copy [[BoundArguments]] to the stack (below the arguments). |
| 1992 { |
| 1993 Label loop, done_loop; |
| 1994 __ mov(ecx, FieldOperand(edx, FixedArray::kLengthOffset)); |
| 1995 __ SmiUntag(ecx); |
| 1996 __ bind(&loop); |
| 1997 __ sub(ecx, Immediate(1)); |
| 1998 __ j(less, &done_loop, Label::kNear); |
| 1999 __ mov(ebx, |
| 2000 FieldOperand(edx, ecx, times_pointer_size, FixedArray::kHeaderSize)); |
| 2001 __ mov(Operand(esp, eax, times_pointer_size, 0), ebx); |
| 2002 __ inc(eax); |
| 2003 __ jmp(&loop); |
| 2004 __ bind(&done_loop); |
| 2005 } |
| 2006 |
| 2007 // Adjust effective number of arguments (eax contains the number of arguments |
| 2008 // from the call plus return address plus the number of [[BoundArguments]]), |
| 2009 // so we need to subtract one for the return address. |
| 2010 __ dec(eax); |
| 2011 |
| 2012 // Patch new.target to [[BoundTargetFunction]] if new.target equals target. |
| 2013 { |
| 2014 Label done; |
| 2015 __ mov(edx, Operand(esp, eax, times_pointer_size, kPointerSize)); |
| 2016 __ cmp(edi, edx); |
| 2017 __ j(not_equal, &done, Label::kNear); |
| 2018 __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); |
| 2019 __ bind(&done); |
| 2020 } |
| 2021 |
| 2022 // Construct the [[BoundTargetFunction]] via the Construct builtin. |
| 2023 __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); |
| 2024 __ mov(ecx, Operand::StaticVariable( |
| 2025 ExternalReference(Builtins::kConstruct, masm->isolate()))); |
| 2026 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |
| 2027 __ jmp(ecx); |
| 2028 } |
| 2029 |
| 2030 |
| 2031 // static |
1843 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { | 2032 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { |
1844 // ----------- S t a t e ------------- | 2033 // ----------- S t a t e ------------- |
1845 // -- eax : the number of arguments (not including the receiver) | 2034 // -- eax : the number of arguments (not including the receiver) |
1846 // -- edi : the constructor to call (checked to be a JSProxy) | 2035 // -- edi : the constructor to call (checked to be a JSProxy) |
1847 // -- edx : the new target (either the same as the constructor or | 2036 // -- edx : the new target (either the same as the constructor or |
1848 // the JSFunction on which new was invoked initially) | 2037 // the JSFunction on which new was invoked initially) |
1849 // ----------------------------------- | 2038 // ----------------------------------- |
1850 | 2039 |
1851 // Call into the Runtime for Proxy [[Construct]]. | 2040 // Call into the Runtime for Proxy [[Construct]]. |
1852 __ PopReturnAddressTo(ecx); | 2041 __ PopReturnAddressTo(ecx); |
(...skipping 23 matching lines...) Expand all Loading... |
1876 | 2065 |
1877 // Dispatch based on instance type. | 2066 // Dispatch based on instance type. |
1878 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 2067 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
1879 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), | 2068 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), |
1880 RelocInfo::CODE_TARGET); | 2069 RelocInfo::CODE_TARGET); |
1881 | 2070 |
1882 // Check if target has a [[Construct]] internal method. | 2071 // Check if target has a [[Construct]] internal method. |
1883 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor); | 2072 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsConstructor); |
1884 __ j(zero, &non_constructor, Label::kNear); | 2073 __ j(zero, &non_constructor, Label::kNear); |
1885 | 2074 |
| 2075 // Only dispatch to bound functions after checking whether they are |
| 2076 // constructors. |
| 2077 __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); |
| 2078 __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(), |
| 2079 RelocInfo::CODE_TARGET); |
| 2080 |
1886 // Only dispatch to proxies after checking whether they are constructors. | 2081 // Only dispatch to proxies after checking whether they are constructors. |
1887 __ CmpInstanceType(ecx, JS_PROXY_TYPE); | 2082 __ CmpInstanceType(ecx, JS_PROXY_TYPE); |
1888 __ j(equal, masm->isolate()->builtins()->ConstructProxy(), | 2083 __ j(equal, masm->isolate()->builtins()->ConstructProxy(), |
1889 RelocInfo::CODE_TARGET); | 2084 RelocInfo::CODE_TARGET); |
1890 | 2085 |
1891 // Called Construct on an exotic Object with a [[Construct]] internal method. | 2086 // Called Construct on an exotic Object with a [[Construct]] internal method. |
1892 { | 2087 { |
1893 // Overwrite the original receiver with the (original) target. | 2088 // Overwrite the original receiver with the (original) target. |
1894 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); | 2089 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); |
1895 // Let the "call_as_constructor_delegate" take care of the rest. | 2090 // Let the "call_as_constructor_delegate" take care of the rest. |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2216 | 2411 |
2217 __ bind(&ok); | 2412 __ bind(&ok); |
2218 __ ret(0); | 2413 __ ret(0); |
2219 } | 2414 } |
2220 | 2415 |
2221 #undef __ | 2416 #undef __ |
2222 } // namespace internal | 2417 } // namespace internal |
2223 } // namespace v8 | 2418 } // namespace v8 |
2224 | 2419 |
2225 #endif // V8_TARGET_ARCH_IA32 | 2420 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |