| 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/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 1718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1729 CallStubInRecordCallTarget(masm, &create_stub, is_super); | 1729 CallStubInRecordCallTarget(masm, &create_stub, is_super); |
| 1730 __ jmp(&done); | 1730 __ jmp(&done); |
| 1731 | 1731 |
| 1732 __ bind(¬_array_function); | 1732 __ bind(¬_array_function); |
| 1733 CreateWeakCellStub weak_cell_stub(isolate); | 1733 CreateWeakCellStub weak_cell_stub(isolate); |
| 1734 CallStubInRecordCallTarget(masm, &weak_cell_stub, is_super); | 1734 CallStubInRecordCallTarget(masm, &weak_cell_stub, is_super); |
| 1735 __ bind(&done); | 1735 __ bind(&done); |
| 1736 } | 1736 } |
| 1737 | 1737 |
| 1738 | 1738 |
| 1739 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { | |
| 1740 // ----------- S t a t e ------------- | |
| 1741 // -- edi : the function to call | |
| 1742 // -- edx : the function's shared function info | |
| 1743 // ----------------------------------- | |
| 1744 // Do not transform the receiver for strict mode functions. | |
| 1745 __ test_b(FieldOperand(edx, SharedFunctionInfo::kStrictModeByteOffset), | |
| 1746 1 << SharedFunctionInfo::kStrictModeBitWithinByte); | |
| 1747 __ j(not_equal, cont); | |
| 1748 | |
| 1749 // Do not transform the receiver for natives (shared already in ecx). | |
| 1750 __ test_b(FieldOperand(edx, SharedFunctionInfo::kNativeByteOffset), | |
| 1751 1 << SharedFunctionInfo::kNativeBitWithinByte); | |
| 1752 __ j(not_equal, cont); | |
| 1753 } | |
| 1754 | |
| 1755 | |
| 1756 static void EmitSlowCase(Isolate* isolate, MacroAssembler* masm, int argc) { | |
| 1757 __ Set(eax, argc); | |
| 1758 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | |
| 1759 } | |
| 1760 | |
| 1761 | |
| 1762 static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) { | |
| 1763 // Wrap the receiver and patch it back onto the stack. | |
| 1764 { FrameScope frame_scope(masm, StackFrame::INTERNAL); | |
| 1765 __ push(edi); | |
| 1766 ToObjectStub stub(masm->isolate()); | |
| 1767 __ CallStub(&stub); | |
| 1768 __ pop(edi); | |
| 1769 } | |
| 1770 __ mov(Operand(esp, (argc + 1) * kPointerSize), eax); | |
| 1771 __ jmp(cont); | |
| 1772 } | |
| 1773 | |
| 1774 | |
| 1775 static void EmitClassConstructorCallCheck(MacroAssembler* masm) { | |
| 1776 // ----------- S t a t e ------------- | |
| 1777 // -- edi : the function to call | |
| 1778 // -- edx : the function's shared function info | |
| 1779 // ----------------------------------- | |
| 1780 // ClassConstructor Check: ES6 section 9.2.1 [[Call]] | |
| 1781 Label non_class_constructor; | |
| 1782 // Check whether the current function is a classConstructor. | |
| 1783 __ test_b(FieldOperand(edx, SharedFunctionInfo::kFunctionKindByteOffset), | |
| 1784 SharedFunctionInfo::kClassConstructorBitsWithinByte); | |
| 1785 __ j(zero, &non_class_constructor, Label::kNear); | |
| 1786 // If we call a classConstructor Function throw a TypeError | |
| 1787 // indirectly via the CallFunction builtin. | |
| 1788 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); | |
| 1789 __ bind(&non_class_constructor); | |
| 1790 } | |
| 1791 | |
| 1792 | |
| 1793 static void CallFunctionNoFeedback(MacroAssembler* masm, | |
| 1794 int argc, bool needs_checks, | |
| 1795 bool call_as_method) { | |
| 1796 // edi : the function to call | |
| 1797 Label slow, wrap, cont; | |
| 1798 | |
| 1799 if (needs_checks) { | |
| 1800 // Check that the function really is a JavaScript function. | |
| 1801 __ JumpIfSmi(edi, &slow); | |
| 1802 | |
| 1803 // Goto slow case if we do not have a function. | |
| 1804 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | |
| 1805 __ j(not_equal, &slow); | |
| 1806 } | |
| 1807 | |
| 1808 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | |
| 1809 EmitClassConstructorCallCheck(masm); | |
| 1810 | |
| 1811 // Fast-case: Just invoke the function. | |
| 1812 ParameterCount actual(argc); | |
| 1813 | |
| 1814 if (call_as_method) { | |
| 1815 if (needs_checks) { | |
| 1816 EmitContinueIfStrictOrNative(masm, &cont); | |
| 1817 } | |
| 1818 | |
| 1819 // Load the receiver from the stack. | |
| 1820 __ mov(eax, Operand(esp, (argc + 1) * kPointerSize)); | |
| 1821 | |
| 1822 if (needs_checks) { | |
| 1823 __ JumpIfSmi(eax, &wrap); | |
| 1824 | |
| 1825 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); | |
| 1826 __ j(below, &wrap); | |
| 1827 } else { | |
| 1828 __ jmp(&wrap); | |
| 1829 } | |
| 1830 | |
| 1831 __ bind(&cont); | |
| 1832 } | |
| 1833 | |
| 1834 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); | |
| 1835 | |
| 1836 if (needs_checks) { | |
| 1837 // Slow-case: Non-function called. | |
| 1838 __ bind(&slow); | |
| 1839 EmitSlowCase(masm->isolate(), masm, argc); | |
| 1840 } | |
| 1841 | |
| 1842 if (call_as_method) { | |
| 1843 __ bind(&wrap); | |
| 1844 EmitWrapCase(masm, argc, &cont); | |
| 1845 } | |
| 1846 } | |
| 1847 | |
| 1848 | |
| 1849 void CallFunctionStub::Generate(MacroAssembler* masm) { | |
| 1850 CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod()); | |
| 1851 } | |
| 1852 | |
| 1853 | |
| 1854 void CallConstructStub::Generate(MacroAssembler* masm) { | 1739 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 1855 // eax : number of arguments | 1740 // eax : number of arguments |
| 1856 // ebx : feedback vector | 1741 // ebx : feedback vector |
| 1857 // ecx : original constructor (for IsSuperConstructorCall) | 1742 // ecx : original constructor (for IsSuperConstructorCall) |
| 1858 // edx : slot in feedback vector (Smi, for RecordCallTarget) | 1743 // edx : slot in feedback vector (Smi, for RecordCallTarget) |
| 1859 // edi : constructor function | 1744 // edi : constructor function |
| 1860 | 1745 |
| 1861 if (IsSuperConstructorCall()) { | 1746 if (IsSuperConstructorCall()) { |
| 1862 __ push(ecx); | 1747 __ push(ecx); |
| 1863 } | 1748 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1936 | 1821 |
| 1937 void CallICStub::Generate(MacroAssembler* masm) { | 1822 void CallICStub::Generate(MacroAssembler* masm) { |
| 1938 // edi - function | 1823 // edi - function |
| 1939 // edx - slot id | 1824 // edx - slot id |
| 1940 // ebx - vector | 1825 // ebx - vector |
| 1941 Isolate* isolate = masm->isolate(); | 1826 Isolate* isolate = masm->isolate(); |
| 1942 const int with_types_offset = | 1827 const int with_types_offset = |
| 1943 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); | 1828 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); |
| 1944 const int generic_offset = | 1829 const int generic_offset = |
| 1945 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); | 1830 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); |
| 1946 Label extra_checks_or_miss, slow_start; | 1831 Label extra_checks_or_miss, call; |
| 1947 Label slow, wrap, cont; | |
| 1948 Label have_js_function; | |
| 1949 int argc = arg_count(); | 1832 int argc = arg_count(); |
| 1950 ParameterCount actual(argc); | 1833 ParameterCount actual(argc); |
| 1951 | 1834 |
| 1952 // The checks. First, does edi match the recorded monomorphic target? | 1835 // The checks. First, does edi match the recorded monomorphic target? |
| 1953 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, | 1836 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, |
| 1954 FixedArray::kHeaderSize)); | 1837 FixedArray::kHeaderSize)); |
| 1955 | 1838 |
| 1956 // We don't know that we have a weak cell. We might have a private symbol | 1839 // We don't know that we have a weak cell. We might have a private symbol |
| 1957 // or an AllocationSite, but the memory is safe to examine. | 1840 // or an AllocationSite, but the memory is safe to examine. |
| 1958 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to | 1841 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1972 | 1855 |
| 1973 // The compare above could have been a SMI/SMI comparison. Guard against this | 1856 // The compare above could have been a SMI/SMI comparison. Guard against this |
| 1974 // convincing us that we have a monomorphic JSFunction. | 1857 // convincing us that we have a monomorphic JSFunction. |
| 1975 __ JumpIfSmi(edi, &extra_checks_or_miss); | 1858 __ JumpIfSmi(edi, &extra_checks_or_miss); |
| 1976 | 1859 |
| 1977 // Increment the call count for monomorphic function calls. | 1860 // Increment the call count for monomorphic function calls. |
| 1978 __ add(FieldOperand(ebx, edx, times_half_pointer_size, | 1861 __ add(FieldOperand(ebx, edx, times_half_pointer_size, |
| 1979 FixedArray::kHeaderSize + kPointerSize), | 1862 FixedArray::kHeaderSize + kPointerSize), |
| 1980 Immediate(Smi::FromInt(CallICNexus::kCallCountIncrement))); | 1863 Immediate(Smi::FromInt(CallICNexus::kCallCountIncrement))); |
| 1981 | 1864 |
| 1982 __ bind(&have_js_function); | 1865 __ bind(&call); |
| 1983 | 1866 __ Set(eax, argc); |
| 1984 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 1867 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1985 EmitClassConstructorCallCheck(masm); | |
| 1986 | |
| 1987 if (CallAsMethod()) { | |
| 1988 EmitContinueIfStrictOrNative(masm, &cont); | |
| 1989 | |
| 1990 // Load the receiver from the stack. | |
| 1991 __ mov(eax, Operand(esp, (argc + 1) * kPointerSize)); | |
| 1992 | |
| 1993 __ JumpIfSmi(eax, &wrap); | |
| 1994 | |
| 1995 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); | |
| 1996 __ j(below, &wrap); | |
| 1997 | |
| 1998 __ bind(&cont); | |
| 1999 } | |
| 2000 | |
| 2001 __ InvokeFunction(edi, actual, JUMP_FUNCTION, NullCallWrapper()); | |
| 2002 | |
| 2003 __ bind(&slow); | |
| 2004 EmitSlowCase(isolate, masm, argc); | |
| 2005 | |
| 2006 if (CallAsMethod()) { | |
| 2007 __ bind(&wrap); | |
| 2008 EmitWrapCase(masm, argc, &cont); | |
| 2009 } | |
| 2010 | 1868 |
| 2011 __ bind(&extra_checks_or_miss); | 1869 __ bind(&extra_checks_or_miss); |
| 2012 Label uninitialized, miss, not_allocation_site; | 1870 Label uninitialized, miss, not_allocation_site; |
| 2013 | 1871 |
| 2014 __ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); | 1872 __ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); |
| 2015 __ j(equal, &slow_start); | 1873 __ j(equal, &call); |
| 2016 | 1874 |
| 2017 // Check if we have an allocation site. | 1875 // Check if we have an allocation site. |
| 2018 __ CompareRoot(FieldOperand(ecx, HeapObject::kMapOffset), | 1876 __ CompareRoot(FieldOperand(ecx, HeapObject::kMapOffset), |
| 2019 Heap::kAllocationSiteMapRootIndex); | 1877 Heap::kAllocationSiteMapRootIndex); |
| 2020 __ j(not_equal, ¬_allocation_site); | 1878 __ j(not_equal, ¬_allocation_site); |
| 2021 | 1879 |
| 2022 // We have an allocation site. | 1880 // We have an allocation site. |
| 2023 HandleArrayCase(masm, &miss); | 1881 HandleArrayCase(masm, &miss); |
| 2024 | 1882 |
| 2025 __ bind(¬_allocation_site); | 1883 __ bind(¬_allocation_site); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2037 // to handle it here. More complex cases are dealt with in the runtime. | 1895 // to handle it here. More complex cases are dealt with in the runtime. |
| 2038 __ AssertNotSmi(ecx); | 1896 __ AssertNotSmi(ecx); |
| 2039 __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx); | 1897 __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx); |
| 2040 __ j(not_equal, &miss); | 1898 __ j(not_equal, &miss); |
| 2041 __ mov( | 1899 __ mov( |
| 2042 FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize), | 1900 FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize), |
| 2043 Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); | 1901 Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); |
| 2044 // We have to update statistics for runtime profiling. | 1902 // We have to update statistics for runtime profiling. |
| 2045 __ sub(FieldOperand(ebx, with_types_offset), Immediate(Smi::FromInt(1))); | 1903 __ sub(FieldOperand(ebx, with_types_offset), Immediate(Smi::FromInt(1))); |
| 2046 __ add(FieldOperand(ebx, generic_offset), Immediate(Smi::FromInt(1))); | 1904 __ add(FieldOperand(ebx, generic_offset), Immediate(Smi::FromInt(1))); |
| 2047 __ jmp(&slow_start); | 1905 __ jmp(&call); |
| 2048 | 1906 |
| 2049 __ bind(&uninitialized); | 1907 __ bind(&uninitialized); |
| 2050 | 1908 |
| 2051 // We are going monomorphic, provided we actually have a JSFunction. | 1909 // We are going monomorphic, provided we actually have a JSFunction. |
| 2052 __ JumpIfSmi(edi, &miss); | 1910 __ JumpIfSmi(edi, &miss); |
| 2053 | 1911 |
| 2054 // Goto miss case if we do not have a function. | 1912 // Goto miss case if we do not have a function. |
| 2055 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 1913 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
| 2056 __ j(not_equal, &miss); | 1914 __ j(not_equal, &miss); |
| 2057 | 1915 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2074 // edx - slot | 1932 // edx - slot |
| 2075 // edi - function | 1933 // edi - function |
| 2076 { | 1934 { |
| 2077 FrameScope scope(masm, StackFrame::INTERNAL); | 1935 FrameScope scope(masm, StackFrame::INTERNAL); |
| 2078 CreateWeakCellStub create_stub(isolate); | 1936 CreateWeakCellStub create_stub(isolate); |
| 2079 __ push(edi); | 1937 __ push(edi); |
| 2080 __ CallStub(&create_stub); | 1938 __ CallStub(&create_stub); |
| 2081 __ pop(edi); | 1939 __ pop(edi); |
| 2082 } | 1940 } |
| 2083 | 1941 |
| 2084 __ jmp(&have_js_function); | 1942 __ jmp(&call); |
| 2085 | 1943 |
| 2086 // We are here because tracing is on or we encountered a MISS case we can't | 1944 // We are here because tracing is on or we encountered a MISS case we can't |
| 2087 // handle here. | 1945 // handle here. |
| 2088 __ bind(&miss); | 1946 __ bind(&miss); |
| 2089 GenerateMiss(masm); | 1947 GenerateMiss(masm); |
| 2090 | 1948 |
| 2091 // the slow case | 1949 __ jmp(&call); |
| 2092 __ bind(&slow_start); | |
| 2093 | |
| 2094 // Check that the function really is a JavaScript function. | |
| 2095 __ JumpIfSmi(edi, &slow); | |
| 2096 | |
| 2097 // Goto slow case if we do not have a function. | |
| 2098 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | |
| 2099 __ j(not_equal, &slow); | |
| 2100 __ jmp(&have_js_function); | |
| 2101 | 1950 |
| 2102 // Unreachable | 1951 // Unreachable |
| 2103 __ int3(); | 1952 __ int3(); |
| 2104 } | 1953 } |
| 2105 | 1954 |
| 2106 | 1955 |
| 2107 void CallICStub::GenerateMiss(MacroAssembler* masm) { | 1956 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
| 2108 FrameScope scope(masm, StackFrame::INTERNAL); | 1957 FrameScope scope(masm, StackFrame::INTERNAL); |
| 2109 | 1958 |
| 2110 // Push the function and feedback info. | 1959 // Push the function and feedback info. |
| (...skipping 3465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5576 Operand(ebp, 7 * kPointerSize), NULL); | 5425 Operand(ebp, 7 * kPointerSize), NULL); |
| 5577 } | 5426 } |
| 5578 | 5427 |
| 5579 | 5428 |
| 5580 #undef __ | 5429 #undef __ |
| 5581 | 5430 |
| 5582 } // namespace internal | 5431 } // namespace internal |
| 5583 } // namespace v8 | 5432 } // namespace v8 |
| 5584 | 5433 |
| 5585 #endif // V8_TARGET_ARCH_X87 | 5434 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |