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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 1585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1596 | 1596 |
1597 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 1597 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
1598 // tagged as a small integer. | 1598 // tagged as a small integer. |
1599 __ InvokeBuiltin(builtin, JUMP_FUNCTION); | 1599 __ InvokeBuiltin(builtin, JUMP_FUNCTION); |
1600 | 1600 |
1601 __ bind(&miss); | 1601 __ bind(&miss); |
1602 GenerateMiss(masm); | 1602 GenerateMiss(masm); |
1603 } | 1603 } |
1604 | 1604 |
1605 | 1605 |
1606 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { | 1606 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub, |
| 1607 bool is_super) { |
1607 // eax : number of arguments to the construct function | 1608 // eax : number of arguments to the construct function |
1608 // ebx : Feedback vector | 1609 // ebx : feedback vector |
1609 // edx : slot in feedback vector (Smi) | 1610 // edx : slot in feedback vector (Smi) |
1610 // edi : the function to call | 1611 // edi : the function to call |
1611 FrameScope scope(masm, StackFrame::INTERNAL); | 1612 // esp[0]: original receiver (for IsSuperConstructorCall) |
| 1613 if (is_super) { |
| 1614 __ pop(ecx); |
| 1615 } |
1612 | 1616 |
1613 // Number-of-arguments register must be smi-tagged to call out. | 1617 { |
1614 __ SmiTag(eax); | 1618 FrameScope scope(masm, StackFrame::INTERNAL); |
1615 __ push(eax); | |
1616 __ push(edi); | |
1617 __ push(edx); | |
1618 __ push(ebx); | |
1619 | 1619 |
1620 __ CallStub(stub); | 1620 // Number-of-arguments register must be smi-tagged to call out. |
| 1621 __ SmiTag(eax); |
| 1622 __ push(eax); |
| 1623 __ push(edi); |
| 1624 __ push(edx); |
| 1625 __ push(ebx); |
| 1626 if (is_super) { |
| 1627 __ push(ecx); |
| 1628 } |
1621 | 1629 |
1622 __ pop(ebx); | 1630 __ CallStub(stub); |
1623 __ pop(edx); | 1631 |
1624 __ pop(edi); | 1632 if (is_super) { |
1625 __ pop(eax); | 1633 __ pop(ecx); |
1626 __ SmiUntag(eax); | 1634 } |
| 1635 __ pop(ebx); |
| 1636 __ pop(edx); |
| 1637 __ pop(edi); |
| 1638 __ pop(eax); |
| 1639 __ SmiUntag(eax); |
| 1640 } |
| 1641 |
| 1642 if (is_super) { |
| 1643 __ push(ecx); |
| 1644 } |
1627 } | 1645 } |
1628 | 1646 |
1629 | 1647 |
1630 static void GenerateRecordCallTarget(MacroAssembler* masm) { | 1648 static void GenerateRecordCallTarget(MacroAssembler* masm, bool is_super) { |
1631 // Cache the called function in a feedback vector slot. Cache states | 1649 // Cache the called function in a feedback vector slot. Cache states |
1632 // are uninitialized, monomorphic (indicated by a JSFunction), and | 1650 // are uninitialized, monomorphic (indicated by a JSFunction), and |
1633 // megamorphic. | 1651 // megamorphic. |
1634 // eax : number of arguments to the construct function | 1652 // eax : number of arguments to the construct function |
1635 // ebx : Feedback vector | 1653 // ebx : feedback vector |
1636 // edx : slot in feedback vector (Smi) | 1654 // edx : slot in feedback vector (Smi) |
1637 // edi : the function to call | 1655 // edi : the function to call |
| 1656 // esp[0]: original receiver (for IsSuperConstructorCall) |
1638 Isolate* isolate = masm->isolate(); | 1657 Isolate* isolate = masm->isolate(); |
1639 Label initialize, done, miss, megamorphic, not_array_function; | 1658 Label initialize, done, miss, megamorphic, not_array_function; |
1640 | 1659 |
1641 // Load the cache state into ecx. | 1660 // Load the cache state into ecx. |
1642 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, | 1661 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, |
1643 FixedArray::kHeaderSize)); | 1662 FixedArray::kHeaderSize)); |
1644 | 1663 |
1645 // A monomorphic cache hit or an already megamorphic state: invoke the | 1664 // A monomorphic cache hit or an already megamorphic state: invoke the |
1646 // function without changing the state. | 1665 // function without changing the state. |
1647 // We don't know if ecx is a WeakCell or a Symbol, but it's harmless to read | 1666 // We don't know if ecx is a WeakCell or a Symbol, but it's harmless to read |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1696 if (!FLAG_pretenuring_call_new) { | 1715 if (!FLAG_pretenuring_call_new) { |
1697 // Make sure the function is the Array() function | 1716 // Make sure the function is the Array() function |
1698 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx); | 1717 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx); |
1699 __ cmp(edi, ecx); | 1718 __ cmp(edi, ecx); |
1700 __ j(not_equal, ¬_array_function); | 1719 __ j(not_equal, ¬_array_function); |
1701 | 1720 |
1702 // The target function is the Array constructor, | 1721 // The target function is the Array constructor, |
1703 // Create an AllocationSite if we don't already have it, store it in the | 1722 // Create an AllocationSite if we don't already have it, store it in the |
1704 // slot. | 1723 // slot. |
1705 CreateAllocationSiteStub create_stub(isolate); | 1724 CreateAllocationSiteStub create_stub(isolate); |
1706 CallStubInRecordCallTarget(masm, &create_stub); | 1725 CallStubInRecordCallTarget(masm, &create_stub, is_super); |
1707 __ jmp(&done); | 1726 __ jmp(&done); |
1708 | 1727 |
1709 __ bind(¬_array_function); | 1728 __ bind(¬_array_function); |
1710 } | 1729 } |
1711 | 1730 |
1712 CreateWeakCellStub create_stub(isolate); | 1731 CreateWeakCellStub create_stub(isolate); |
1713 CallStubInRecordCallTarget(masm, &create_stub); | 1732 CallStubInRecordCallTarget(masm, &create_stub, is_super); |
1714 __ bind(&done); | 1733 __ bind(&done); |
1715 } | 1734 } |
1716 | 1735 |
1717 | 1736 |
1718 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { | 1737 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { |
1719 // Do not transform the receiver for strict mode functions. | 1738 // Do not transform the receiver for strict mode functions. |
1720 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 1739 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
1721 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), | 1740 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), |
1722 1 << SharedFunctionInfo::kStrictModeBitWithinByte); | 1741 1 << SharedFunctionInfo::kStrictModeBitWithinByte); |
1723 __ j(not_equal, cont); | 1742 __ j(not_equal, cont); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1843 __ push(ecx); | 1862 __ push(ecx); |
1844 } | 1863 } |
1845 | 1864 |
1846 // Check that function is not a smi. | 1865 // Check that function is not a smi. |
1847 __ JumpIfSmi(edi, &non_function_call); | 1866 __ JumpIfSmi(edi, &non_function_call); |
1848 // Check that function is a JSFunction. | 1867 // Check that function is a JSFunction. |
1849 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 1868 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
1850 __ j(not_equal, &slow); | 1869 __ j(not_equal, &slow); |
1851 | 1870 |
1852 if (RecordCallTarget()) { | 1871 if (RecordCallTarget()) { |
1853 GenerateRecordCallTarget(masm); | 1872 GenerateRecordCallTarget(masm, IsSuperConstructorCall()); |
1854 | 1873 |
1855 if (FLAG_pretenuring_call_new) { | 1874 if (FLAG_pretenuring_call_new) { |
1856 // Put the AllocationSite from the feedback vector into ebx. | 1875 // Put the AllocationSite from the feedback vector into ebx. |
1857 // By adding kPointerSize we encode that we know the AllocationSite | 1876 // By adding kPointerSize we encode that we know the AllocationSite |
1858 // entry is at the feedback vector slot given by edx + 1. | 1877 // entry is at the feedback vector slot given by edx + 1. |
1859 __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size, | 1878 __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size, |
1860 FixedArray::kHeaderSize + kPointerSize)); | 1879 FixedArray::kHeaderSize + kPointerSize)); |
1861 } else { | 1880 } else { |
1862 Label feedback_register_initialized; | 1881 Label feedback_register_initialized; |
1863 // Put the AllocationSite from the feedback vector into ebx, or undefined. | 1882 // Put the AllocationSite from the feedback vector into ebx, or undefined. |
(...skipping 21 matching lines...) Expand all Loading... |
1885 Register jmp_reg = ecx; | 1904 Register jmp_reg = ecx; |
1886 __ mov(jmp_reg, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 1905 __ mov(jmp_reg, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
1887 __ mov(jmp_reg, FieldOperand(jmp_reg, | 1906 __ mov(jmp_reg, FieldOperand(jmp_reg, |
1888 SharedFunctionInfo::kConstructStubOffset)); | 1907 SharedFunctionInfo::kConstructStubOffset)); |
1889 __ lea(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize)); | 1908 __ lea(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize)); |
1890 __ jmp(jmp_reg); | 1909 __ jmp(jmp_reg); |
1891 | 1910 |
1892 // edi: called object | 1911 // edi: called object |
1893 // eax: number of arguments | 1912 // eax: number of arguments |
1894 // ecx: object map | 1913 // ecx: object map |
1895 // esp[0]: original receiver | 1914 // esp[0]: original receiver (for IsSuperConstructorCall) |
1896 Label do_call; | 1915 Label do_call; |
1897 __ bind(&slow); | 1916 __ bind(&slow); |
1898 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); | 1917 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); |
1899 __ j(not_equal, &non_function_call); | 1918 __ j(not_equal, &non_function_call); |
1900 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); | 1919 __ GetBuiltinEntry(edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); |
1901 __ jmp(&do_call); | 1920 __ jmp(&do_call); |
1902 | 1921 |
1903 __ bind(&non_function_call); | 1922 __ bind(&non_function_call); |
1904 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); | 1923 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); |
1905 __ bind(&do_call); | 1924 __ bind(&do_call); |
(...skipping 3239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5145 Operand(ebp, 7 * kPointerSize), NULL); | 5164 Operand(ebp, 7 * kPointerSize), NULL); |
5146 } | 5165 } |
5147 | 5166 |
5148 | 5167 |
5149 #undef __ | 5168 #undef __ |
5150 | 5169 |
5151 } // namespace internal | 5170 } // namespace internal |
5152 } // namespace v8 | 5171 } // namespace v8 |
5153 | 5172 |
5154 #endif // V8_TARGET_ARCH_X87 | 5173 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |