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 |