| 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_X64 | 5 #if V8_TARGET_ARCH_X64 |
| 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 1699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1710 { | 1710 { |
| 1711 FrameScope frame(masm, StackFrame::MANUAL); | 1711 FrameScope frame(masm, StackFrame::MANUAL); |
| 1712 EnterArgumentsAdaptorFrame(masm); | 1712 EnterArgumentsAdaptorFrame(masm); |
| 1713 __ CallRuntime(Runtime::kThrowStackOverflow, 0); | 1713 __ CallRuntime(Runtime::kThrowStackOverflow, 0); |
| 1714 __ int3(); | 1714 __ int3(); |
| 1715 } | 1715 } |
| 1716 } | 1716 } |
| 1717 | 1717 |
| 1718 | 1718 |
| 1719 // static | 1719 // static |
| 1720 void Builtins::Generate_CallFunction(MacroAssembler* masm) { | 1720 void Builtins::Generate_CallFunction(MacroAssembler* masm, |
| 1721 // ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) | 1721 ConvertReceiverMode mode) { |
| 1722 // ----------- S t a t e ------------- | 1722 // ----------- S t a t e ------------- |
| 1723 // -- rax : the number of arguments (not including the receiver) | 1723 // -- rax : the number of arguments (not including the receiver) |
| 1724 // -- rdi : the function to call (checked to be a JSFunction) | 1724 // -- rdi : the function to call (checked to be a JSFunction) |
| 1725 // ----------------------------------- | 1725 // ----------------------------------- |
| 1726 | |
| 1727 Label convert, convert_global_proxy, convert_to_object, done_convert; | |
| 1728 StackArgumentsAccessor args(rsp, rax); | 1726 StackArgumentsAccessor args(rsp, rax); |
| 1729 __ AssertFunction(rdi); | 1727 __ AssertFunction(rdi); |
| 1728 |
| 1729 // ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) |
| 1730 // Check that the function is not a "classConstructor". |
| 1731 Label class_constructor; |
| 1730 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | 1732 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
| 1731 { | 1733 __ testb(FieldOperand(rdx, SharedFunctionInfo::kFunctionKindByteOffset), |
| 1732 Label non_class_constructor; | 1734 Immediate(SharedFunctionInfo::kClassConstructorBitsWithinByte)); |
| 1733 // Check whether the current function is a classConstructor | 1735 __ j(not_zero, &class_constructor); |
| 1734 __ testb(FieldOperand(rdx, SharedFunctionInfo::kFunctionKindByteOffset), | 1736 |
| 1735 Immediate(SharedFunctionInfo::kClassConstructorBitsWithinByte)); | 1737 // ----------- S t a t e ------------- |
| 1736 __ j(zero, &non_class_constructor); | 1738 // -- rax : the number of arguments (not including the receiver) |
| 1737 // Step: 2, If we call a classConstructor Function throw a TypeError. | 1739 // -- rdx : the shared function info. |
| 1738 { | 1740 // -- rdi : the function to call (checked to be a JSFunction) |
| 1739 FrameScope frame(masm, StackFrame::INTERNAL); | 1741 // ----------------------------------- |
| 1740 __ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0); | |
| 1741 } | |
| 1742 __ bind(&non_class_constructor); | |
| 1743 } | |
| 1744 | 1742 |
| 1745 // Enter the context of the function; ToObject has to run in the function | 1743 // Enter the context of the function; ToObject has to run in the function |
| 1746 // context, and we also need to take the global proxy from the function | 1744 // context, and we also need to take the global proxy from the function |
| 1747 // context in case of conversion. | 1745 // context in case of conversion. |
| 1748 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset == | 1746 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset == |
| 1749 SharedFunctionInfo::kStrictModeByteOffset); | 1747 SharedFunctionInfo::kStrictModeByteOffset); |
| 1750 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 1748 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 1751 // We need to convert the receiver for non-native sloppy mode functions. | 1749 // We need to convert the receiver for non-native sloppy mode functions. |
| 1750 Label done_convert; |
| 1752 __ testb(FieldOperand(rdx, SharedFunctionInfo::kNativeByteOffset), | 1751 __ testb(FieldOperand(rdx, SharedFunctionInfo::kNativeByteOffset), |
| 1753 Immediate((1 << SharedFunctionInfo::kNativeBitWithinByte) | | 1752 Immediate((1 << SharedFunctionInfo::kNativeBitWithinByte) | |
| 1754 (1 << SharedFunctionInfo::kStrictModeBitWithinByte))); | 1753 (1 << SharedFunctionInfo::kStrictModeBitWithinByte))); |
| 1755 __ j(not_zero, &done_convert); | 1754 __ j(not_zero, &done_convert); |
| 1756 { | 1755 { |
| 1757 __ movp(rcx, args.GetReceiverOperand()); | |
| 1758 | |
| 1759 // ----------- S t a t e ------------- | 1756 // ----------- S t a t e ------------- |
| 1760 // -- rax : the number of arguments (not including the receiver) | 1757 // -- rax : the number of arguments (not including the receiver) |
| 1761 // -- rcx : the receiver | |
| 1762 // -- rdx : the shared function info. | 1758 // -- rdx : the shared function info. |
| 1763 // -- rdi : the function to call (checked to be a JSFunction) | 1759 // -- rdi : the function to call (checked to be a JSFunction) |
| 1764 // -- rsi : the function context. | 1760 // -- rsi : the function context. |
| 1765 // ----------------------------------- | 1761 // ----------------------------------- |
| 1766 | 1762 |
| 1767 Label convert_receiver; | 1763 if (mode == ConvertReceiverMode::kNullOrUndefined) { |
| 1768 __ JumpIfSmi(rcx, &convert_to_object, Label::kNear); | |
| 1769 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | |
| 1770 __ CmpObjectType(rcx, FIRST_JS_RECEIVER_TYPE, rbx); | |
| 1771 __ j(above_equal, &done_convert); | |
| 1772 __ JumpIfRoot(rcx, Heap::kUndefinedValueRootIndex, &convert_global_proxy, | |
| 1773 Label::kNear); | |
| 1774 __ JumpIfNotRoot(rcx, Heap::kNullValueRootIndex, &convert_to_object, | |
| 1775 Label::kNear); | |
| 1776 __ bind(&convert_global_proxy); | |
| 1777 { | |
| 1778 // Patch receiver to global proxy. | 1764 // Patch receiver to global proxy. |
| 1779 __ LoadGlobalProxy(rcx); | 1765 __ LoadGlobalProxy(rcx); |
| 1766 } else { |
| 1767 Label convert_to_object, convert_receiver; |
| 1768 __ movp(rcx, args.GetReceiverOperand()); |
| 1769 __ JumpIfSmi(rcx, &convert_to_object, Label::kNear); |
| 1770 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
| 1771 __ CmpObjectType(rcx, FIRST_JS_RECEIVER_TYPE, rbx); |
| 1772 __ j(above_equal, &done_convert); |
| 1773 if (mode != ConvertReceiverMode::kNotNullOrUndefined) { |
| 1774 Label convert_global_proxy; |
| 1775 __ JumpIfRoot(rcx, Heap::kUndefinedValueRootIndex, |
| 1776 &convert_global_proxy, Label::kNear); |
| 1777 __ JumpIfNotRoot(rcx, Heap::kNullValueRootIndex, &convert_to_object, |
| 1778 Label::kNear); |
| 1779 __ bind(&convert_global_proxy); |
| 1780 { |
| 1781 // Patch receiver to global proxy. |
| 1782 __ LoadGlobalProxy(rcx); |
| 1783 } |
| 1784 __ jmp(&convert_receiver); |
| 1785 } |
| 1786 __ bind(&convert_to_object); |
| 1787 { |
| 1788 // Convert receiver using ToObject. |
| 1789 // TODO(bmeurer): Inline the allocation here to avoid building the frame |
| 1790 // in the fast case? (fall back to AllocateInNewSpace?) |
| 1791 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1792 __ Integer32ToSmi(rax, rax); |
| 1793 __ Push(rax); |
| 1794 __ Push(rdi); |
| 1795 __ movp(rax, rcx); |
| 1796 ToObjectStub stub(masm->isolate()); |
| 1797 __ CallStub(&stub); |
| 1798 __ movp(rcx, rax); |
| 1799 __ Pop(rdi); |
| 1800 __ Pop(rax); |
| 1801 __ SmiToInteger32(rax, rax); |
| 1802 } |
| 1803 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
| 1804 __ bind(&convert_receiver); |
| 1780 } | 1805 } |
| 1781 __ jmp(&convert_receiver); | |
| 1782 __ bind(&convert_to_object); | |
| 1783 { | |
| 1784 // Convert receiver using ToObject. | |
| 1785 // TODO(bmeurer): Inline the allocation here to avoid building the frame | |
| 1786 // in the fast case? (fall back to AllocateInNewSpace?) | |
| 1787 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 1788 __ Integer32ToSmi(rax, rax); | |
| 1789 __ Push(rax); | |
| 1790 __ Push(rdi); | |
| 1791 __ movp(rax, rcx); | |
| 1792 ToObjectStub stub(masm->isolate()); | |
| 1793 __ CallStub(&stub); | |
| 1794 __ movp(rcx, rax); | |
| 1795 __ Pop(rdi); | |
| 1796 __ Pop(rax); | |
| 1797 __ SmiToInteger32(rax, rax); | |
| 1798 } | |
| 1799 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | |
| 1800 __ bind(&convert_receiver); | |
| 1801 __ movp(args.GetReceiverOperand(), rcx); | 1806 __ movp(args.GetReceiverOperand(), rcx); |
| 1802 } | 1807 } |
| 1803 __ bind(&done_convert); | 1808 __ bind(&done_convert); |
| 1804 | 1809 |
| 1805 // ----------- S t a t e ------------- | 1810 // ----------- S t a t e ------------- |
| 1806 // -- rax : the number of arguments (not including the receiver) | 1811 // -- rax : the number of arguments (not including the receiver) |
| 1807 // -- rdx : the shared function info. | 1812 // -- rdx : the shared function info. |
| 1808 // -- rdi : the function to call (checked to be a JSFunction) | 1813 // -- rdi : the function to call (checked to be a JSFunction) |
| 1809 // -- rsi : the function context. | 1814 // -- rsi : the function context. |
| 1810 // ----------------------------------- | 1815 // ----------------------------------- |
| 1811 | 1816 |
| 1812 __ LoadSharedFunctionInfoSpecialField( | 1817 __ LoadSharedFunctionInfoSpecialField( |
| 1813 rbx, rdx, SharedFunctionInfo::kFormalParameterCountOffset); | 1818 rbx, rdx, SharedFunctionInfo::kFormalParameterCountOffset); |
| 1814 __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 1819 __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 1815 ParameterCount actual(rax); | 1820 ParameterCount actual(rax); |
| 1816 ParameterCount expected(rbx); | 1821 ParameterCount expected(rbx); |
| 1817 __ InvokeCode(rdx, expected, actual, JUMP_FUNCTION, NullCallWrapper()); | 1822 __ InvokeCode(rdx, expected, actual, JUMP_FUNCTION, NullCallWrapper()); |
| 1823 |
| 1824 // The function is a "classConstructor", need to raise an exception. |
| 1825 __ bind(&class_constructor); |
| 1826 { |
| 1827 FrameScope frame(masm, StackFrame::INTERNAL); |
| 1828 __ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0); |
| 1829 } |
| 1818 } | 1830 } |
| 1819 | 1831 |
| 1820 | 1832 |
| 1821 // static | 1833 // static |
| 1822 void Builtins::Generate_Call(MacroAssembler* masm) { | 1834 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { |
| 1823 // ----------- S t a t e ------------- | 1835 // ----------- S t a t e ------------- |
| 1824 // -- rax : the number of arguments (not including the receiver) | 1836 // -- rax : the number of arguments (not including the receiver) |
| 1825 // -- rdi : the target to call (can be any Object) | 1837 // -- rdi : the target to call (can be any Object) |
| 1826 // ----------------------------------- | 1838 // ----------------------------------- |
| 1827 StackArgumentsAccessor args(rsp, rax); | 1839 StackArgumentsAccessor args(rsp, rax); |
| 1828 | 1840 |
| 1829 Label non_callable, non_function, non_smi; | 1841 Label non_callable, non_function, non_smi; |
| 1830 __ JumpIfSmi(rdi, &non_callable); | 1842 __ JumpIfSmi(rdi, &non_callable); |
| 1831 __ bind(&non_smi); | 1843 __ bind(&non_smi); |
| 1832 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 1844 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
| 1833 __ j(equal, masm->isolate()->builtins()->CallFunction(), | 1845 __ j(equal, masm->isolate()->builtins()->CallFunction(mode), |
| 1834 RelocInfo::CODE_TARGET); | 1846 RelocInfo::CODE_TARGET); |
| 1835 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); | 1847 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); |
| 1836 __ j(not_equal, &non_function); | 1848 __ j(not_equal, &non_function); |
| 1837 | 1849 |
| 1838 // 1. Call to function proxy. | 1850 // 1. Call to function proxy. |
| 1839 // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies. | 1851 // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies. |
| 1840 __ movp(rdi, FieldOperand(rdi, JSFunctionProxy::kCallTrapOffset)); | 1852 __ movp(rdi, FieldOperand(rdi, JSFunctionProxy::kCallTrapOffset)); |
| 1841 __ AssertNotSmi(rdi); | 1853 __ AssertNotSmi(rdi); |
| 1842 __ jmp(&non_smi); | 1854 __ jmp(&non_smi); |
| 1843 | 1855 |
| 1844 // 2. Call to something else, which might have a [[Call]] internal method (if | 1856 // 2. Call to something else, which might have a [[Call]] internal method (if |
| 1845 // not we raise an exception). | 1857 // not we raise an exception). |
| 1846 __ bind(&non_function); | 1858 __ bind(&non_function); |
| 1847 // Check if target has a [[Call]] internal method. | 1859 // Check if target has a [[Call]] internal method. |
| 1848 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), | 1860 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), |
| 1849 Immediate(1 << Map::kIsCallable)); | 1861 Immediate(1 << Map::kIsCallable)); |
| 1850 __ j(zero, &non_callable, Label::kNear); | 1862 __ j(zero, &non_callable, Label::kNear); |
| 1851 // Overwrite the original receiver with the (original) target. | 1863 // Overwrite the original receiver with the (original) target. |
| 1852 __ movp(args.GetReceiverOperand(), rdi); | 1864 __ movp(args.GetReceiverOperand(), rdi); |
| 1853 // Let the "call_as_function_delegate" take care of the rest. | 1865 // Let the "call_as_function_delegate" take care of the rest. |
| 1854 __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, rdi); | 1866 __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, rdi); |
| 1855 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); | 1867 __ Jump(masm->isolate()->builtins()->CallFunction( |
| 1868 ConvertReceiverMode::kNotNullOrUndefined), |
| 1869 RelocInfo::CODE_TARGET); |
| 1856 | 1870 |
| 1857 // 3. Call to something that is not callable. | 1871 // 3. Call to something that is not callable. |
| 1858 __ bind(&non_callable); | 1872 __ bind(&non_callable); |
| 1859 { | 1873 { |
| 1860 FrameScope scope(masm, StackFrame::INTERNAL); | 1874 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1861 __ Push(rdi); | 1875 __ Push(rdi); |
| 1862 __ CallRuntime(Runtime::kThrowCalledNonCallable, 1); | 1876 __ CallRuntime(Runtime::kThrowCalledNonCallable, 1); |
| 1863 } | 1877 } |
| 1864 } | 1878 } |
| 1865 | 1879 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2001 __ ret(0); | 2015 __ ret(0); |
| 2002 } | 2016 } |
| 2003 | 2017 |
| 2004 | 2018 |
| 2005 #undef __ | 2019 #undef __ |
| 2006 | 2020 |
| 2007 } // namespace internal | 2021 } // namespace internal |
| 2008 } // namespace v8 | 2022 } // namespace v8 |
| 2009 | 2023 |
| 2010 #endif // V8_TARGET_ARCH_X64 | 2024 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |