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/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 1255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 Immediate(Smi::FromInt(field_index))); | 1266 Immediate(Smi::FromInt(field_index))); |
1267 __ CallCFunction( | 1267 __ CallCFunction( |
1268 ExternalReference::get_date_field_function(masm->isolate()), 2); | 1268 ExternalReference::get_date_field_function(masm->isolate()), 2); |
1269 } | 1269 } |
1270 __ ret(1 * kPointerSize); | 1270 __ ret(1 * kPointerSize); |
1271 | 1271 |
1272 // 3. Raise a TypeError if the receiver is not a date. | 1272 // 3. Raise a TypeError if the receiver is not a date. |
1273 __ bind(&receiver_not_date); | 1273 __ bind(&receiver_not_date); |
1274 { | 1274 { |
1275 FrameScope scope(masm, StackFrame::MANUAL); | 1275 FrameScope scope(masm, StackFrame::MANUAL); |
1276 __ Push(ebp); | 1276 __ Move(ebx, Immediate(0)); |
1277 __ Move(ebp, esp); | 1277 __ EnterBuiltinFrame(esi, edi, ebx); |
1278 __ Push(esi); | |
1279 __ Push(edi); | |
1280 __ Push(Immediate(0)); | |
1281 __ CallRuntime(Runtime::kThrowNotDateError); | 1278 __ CallRuntime(Runtime::kThrowNotDateError); |
1282 } | 1279 } |
1283 } | 1280 } |
1284 | 1281 |
1285 // static | 1282 // static |
1286 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { | 1283 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { |
1287 // ----------- S t a t e ------------- | 1284 // ----------- S t a t e ------------- |
1288 // -- eax : argc | 1285 // -- eax : argc |
1289 // -- esp[0] : return address | 1286 // -- esp[0] : return address |
1290 // -- esp[4] : argArray | 1287 // -- esp[4] : argArray |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1642 // Load the double value of the parameter into stx_1, maybe converting the | 1639 // Load the double value of the parameter into stx_1, maybe converting the |
1643 // parameter to a number first using the ToNumber builtin if necessary. | 1640 // parameter to a number first using the ToNumber builtin if necessary. |
1644 Label convert, convert_smi, convert_number, done_convert; | 1641 Label convert, convert_smi, convert_number, done_convert; |
1645 __ bind(&convert); | 1642 __ bind(&convert); |
1646 __ JumpIfSmi(ebx, &convert_smi); | 1643 __ JumpIfSmi(ebx, &convert_smi); |
1647 __ JumpIfRoot(FieldOperand(ebx, HeapObject::kMapOffset), | 1644 __ JumpIfRoot(FieldOperand(ebx, HeapObject::kMapOffset), |
1648 Heap::kHeapNumberMapRootIndex, &convert_number); | 1645 Heap::kHeapNumberMapRootIndex, &convert_number); |
1649 { | 1646 { |
1650 // Parameter is not a Number, use the ToNumber builtin to convert it. | 1647 // Parameter is not a Number, use the ToNumber builtin to convert it. |
1651 FrameScope scope(masm, StackFrame::MANUAL); | 1648 FrameScope scope(masm, StackFrame::MANUAL); |
1652 __ Push(ebp); | |
1653 __ Move(ebp, esp); | |
1654 __ Push(esi); | |
1655 __ Push(edi); | |
1656 __ SmiTag(eax); | 1649 __ SmiTag(eax); |
1657 __ SmiTag(ecx); | 1650 __ SmiTag(ecx); |
1658 __ Push(eax); | 1651 __ EnterBuiltinFrame(esi, edi, eax); |
1659 __ Push(ecx); | 1652 __ Push(ecx); |
1660 __ Push(edx); | 1653 __ Push(edx); |
1661 __ mov(eax, ebx); | 1654 __ mov(eax, ebx); |
1662 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); | 1655 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); |
1663 __ mov(ebx, eax); | 1656 __ mov(ebx, eax); |
1664 __ Pop(edx); | 1657 __ Pop(edx); |
1665 __ Pop(ecx); | 1658 __ Pop(ecx); |
1666 __ Pop(eax); | 1659 __ LeaveBuiltinFrame(esi, edi, eax); |
1667 __ Pop(edi); | 1660 __ SmiUntag(ecx); |
1668 __ Pop(esi); | 1661 __ SmiUntag(eax); |
1669 { | 1662 { |
1670 // Restore the double accumulator value (stX_0). | 1663 // Restore the double accumulator value (stX_0). |
1671 Label restore_smi, done_restore; | 1664 Label restore_smi, done_restore; |
1672 __ JumpIfSmi(edx, &restore_smi, Label::kNear); | 1665 __ JumpIfSmi(edx, &restore_smi, Label::kNear); |
1673 __ fld_d(FieldOperand(edx, HeapNumber::kValueOffset)); | 1666 __ fld_d(FieldOperand(edx, HeapNumber::kValueOffset)); |
1674 __ jmp(&done_restore, Label::kNear); | 1667 __ jmp(&done_restore, Label::kNear); |
1675 __ bind(&restore_smi); | 1668 __ bind(&restore_smi); |
1676 __ SmiUntag(edx); | 1669 __ SmiUntag(edx); |
1677 __ push(edx); | 1670 __ push(edx); |
1678 __ fild_s(Operand(esp, 0)); | 1671 __ fild_s(Operand(esp, 0)); |
1679 __ pop(edx); | 1672 __ pop(edx); |
1680 __ SmiTag(edx); | 1673 __ SmiTag(edx); |
1681 __ bind(&done_restore); | 1674 __ bind(&done_restore); |
1682 } | 1675 } |
1683 __ SmiUntag(ecx); | |
1684 __ SmiUntag(eax); | |
1685 __ leave(); | |
1686 } | 1676 } |
1687 __ jmp(&convert); | 1677 __ jmp(&convert); |
1688 __ bind(&convert_number); | 1678 __ bind(&convert_number); |
1689 // Load another value into stx_1 | 1679 // Load another value into stx_1 |
1690 __ fld_d(FieldOperand(ebx, HeapNumber::kValueOffset)); | 1680 __ fld_d(FieldOperand(ebx, HeapNumber::kValueOffset)); |
1691 __ fxch(); | 1681 __ fxch(); |
1692 __ jmp(&done_convert, Label::kNear); | 1682 __ jmp(&done_convert, Label::kNear); |
1693 __ bind(&convert_smi); | 1683 __ bind(&convert_smi); |
1694 __ SmiUntag(ebx); | 1684 __ SmiUntag(ebx); |
1695 __ push(ebx); | 1685 __ push(ebx); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1747 __ PushReturnAddressFrom(ecx); | 1737 __ PushReturnAddressFrom(ecx); |
1748 __ mov(eax, edx); | 1738 __ mov(eax, edx); |
1749 __ Ret(); | 1739 __ Ret(); |
1750 } | 1740 } |
1751 | 1741 |
1752 // static | 1742 // static |
1753 void Builtins::Generate_NumberConstructor(MacroAssembler* masm) { | 1743 void Builtins::Generate_NumberConstructor(MacroAssembler* masm) { |
1754 // ----------- S t a t e ------------- | 1744 // ----------- S t a t e ------------- |
1755 // -- eax : number of arguments | 1745 // -- eax : number of arguments |
1756 // -- edi : constructor function | 1746 // -- edi : constructor function |
| 1747 // -- esi : context |
1757 // -- esp[0] : return address | 1748 // -- esp[0] : return address |
1758 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1749 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1759 // -- esp[(argc + 1) * 4] : receiver | 1750 // -- esp[(argc + 1) * 4] : receiver |
1760 // ----------------------------------- | 1751 // ----------------------------------- |
1761 | 1752 |
1762 // 1. Load the first argument into eax and get rid of the rest (including the | 1753 // 1. Load the first argument into ebx. |
1763 // receiver). | |
1764 Label no_arguments; | 1754 Label no_arguments; |
1765 { | 1755 { |
1766 __ test(eax, eax); | 1756 __ test(eax, eax); |
1767 __ j(zero, &no_arguments, Label::kNear); | 1757 __ j(zero, &no_arguments, Label::kNear); |
1768 __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); | 1758 __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); |
1769 __ PopReturnAddressTo(ecx); | |
1770 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); | |
1771 __ PushReturnAddressFrom(ecx); | |
1772 __ mov(eax, ebx); | |
1773 } | 1759 } |
1774 | 1760 |
1775 // 2a. Convert the first argument to a number. | 1761 // 2a. Convert the first argument to a number. |
1776 __ Jump(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); | 1762 { |
| 1763 FrameScope scope(masm, StackFrame::MANUAL); |
| 1764 __ SmiTag(eax); |
| 1765 __ EnterBuiltinFrame(esi, edi, eax); |
| 1766 __ mov(eax, ebx); |
| 1767 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); |
| 1768 __ LeaveBuiltinFrame(esi, edi, ebx); // Argc popped to ebx. |
| 1769 __ SmiUntag(ebx); |
| 1770 } |
| 1771 |
| 1772 { |
| 1773 // Drop all arguments including the receiver. |
| 1774 __ PopReturnAddressTo(ecx); |
| 1775 __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize)); |
| 1776 __ PushReturnAddressFrom(ecx); |
| 1777 __ Ret(); |
| 1778 } |
1777 | 1779 |
1778 // 2b. No arguments, return +0 (already in eax). | 1780 // 2b. No arguments, return +0 (already in eax). |
1779 __ bind(&no_arguments); | 1781 __ bind(&no_arguments); |
1780 __ ret(1 * kPointerSize); | 1782 __ ret(1 * kPointerSize); |
1781 } | 1783 } |
1782 | 1784 |
1783 | 1785 |
1784 // static | 1786 // static |
1785 void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) { | 1787 void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) { |
1786 // ----------- S t a t e ------------- | 1788 // ----------- S t a t e ------------- |
1787 // -- eax : number of arguments | 1789 // -- eax : number of arguments |
1788 // -- edi : constructor function | 1790 // -- edi : constructor function |
1789 // -- edx : new target | 1791 // -- edx : new target |
| 1792 // -- esi : context |
1790 // -- esp[0] : return address | 1793 // -- esp[0] : return address |
1791 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1794 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1792 // -- esp[(argc + 1) * 4] : receiver | 1795 // -- esp[(argc + 1) * 4] : receiver |
1793 // ----------------------------------- | 1796 // ----------------------------------- |
1794 | 1797 |
1795 // 1. Make sure we operate in the context of the called function. | 1798 // 1. Make sure we operate in the context of the called function. |
1796 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 1799 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
1797 | 1800 |
1798 // 2. Load the first argument into ebx and get rid of the rest (including the | 1801 // Store argc in r8. |
1799 // receiver). | 1802 __ mov(ecx, eax); |
| 1803 __ SmiTag(ecx); |
| 1804 |
| 1805 // 2. Load the first argument into ebx. |
1800 { | 1806 { |
1801 Label no_arguments, done; | 1807 Label no_arguments, done; |
1802 __ test(eax, eax); | 1808 __ test(eax, eax); |
1803 __ j(zero, &no_arguments, Label::kNear); | 1809 __ j(zero, &no_arguments, Label::kNear); |
1804 __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); | 1810 __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); |
1805 __ jmp(&done, Label::kNear); | 1811 __ jmp(&done, Label::kNear); |
1806 __ bind(&no_arguments); | 1812 __ bind(&no_arguments); |
1807 __ Move(ebx, Smi::FromInt(0)); | 1813 __ Move(ebx, Smi::FromInt(0)); |
1808 __ bind(&done); | 1814 __ bind(&done); |
1809 __ PopReturnAddressTo(ecx); | |
1810 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); | |
1811 __ PushReturnAddressFrom(ecx); | |
1812 } | 1815 } |
1813 | 1816 |
1814 // 3. Make sure ebx is a number. | 1817 // 3. Make sure ebx is a number. |
1815 { | 1818 { |
1816 Label done_convert; | 1819 Label done_convert; |
1817 __ JumpIfSmi(ebx, &done_convert); | 1820 __ JumpIfSmi(ebx, &done_convert); |
1818 __ CompareRoot(FieldOperand(ebx, HeapObject::kMapOffset), | 1821 __ CompareRoot(FieldOperand(ebx, HeapObject::kMapOffset), |
1819 Heap::kHeapNumberMapRootIndex); | 1822 Heap::kHeapNumberMapRootIndex); |
1820 __ j(equal, &done_convert); | 1823 __ j(equal, &done_convert); |
1821 { | 1824 { |
1822 FrameScope scope(masm, StackFrame::INTERNAL); | 1825 FrameScope scope(masm, StackFrame::MANUAL); |
1823 __ Push(edi); | 1826 __ EnterBuiltinFrame(esi, edi, ecx); |
1824 __ Push(edx); | 1827 __ Push(edx); |
1825 __ Move(eax, ebx); | 1828 __ Move(eax, ebx); |
1826 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); | 1829 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); |
1827 __ Move(ebx, eax); | 1830 __ Move(ebx, eax); |
1828 __ Pop(edx); | 1831 __ Pop(edx); |
1829 __ Pop(edi); | 1832 __ LeaveBuiltinFrame(esi, edi, ecx); |
1830 } | 1833 } |
1831 __ bind(&done_convert); | 1834 __ bind(&done_convert); |
1832 } | 1835 } |
1833 | 1836 |
1834 // 4. Check if new target and constructor differ. | 1837 // 4. Check if new target and constructor differ. |
1835 Label new_object; | 1838 Label drop_frame_and_ret, done_alloc, new_object; |
1836 __ cmp(edx, edi); | 1839 __ cmp(edx, edi); |
1837 __ j(not_equal, &new_object); | 1840 __ j(not_equal, &new_object); |
1838 | 1841 |
1839 // 5. Allocate a JSValue wrapper for the number. | 1842 // 5. Allocate a JSValue wrapper for the number. |
1840 __ AllocateJSValue(eax, edi, ebx, ecx, &new_object); | 1843 __ AllocateJSValue(eax, edi, ebx, esi, &done_alloc); |
1841 __ Ret(); | 1844 __ jmp(&drop_frame_and_ret); |
| 1845 |
| 1846 __ bind(&done_alloc); |
| 1847 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); // Restore esi. |
1842 | 1848 |
1843 // 6. Fallback to the runtime to create new object. | 1849 // 6. Fallback to the runtime to create new object. |
1844 __ bind(&new_object); | 1850 __ bind(&new_object); |
1845 { | 1851 { |
1846 FrameScope scope(masm, StackFrame::INTERNAL); | 1852 FrameScope scope(masm, StackFrame::MANUAL); |
| 1853 __ EnterBuiltinFrame(esi, edi, ecx); |
1847 __ Push(ebx); // the first argument | 1854 __ Push(ebx); // the first argument |
1848 FastNewObjectStub stub(masm->isolate()); | 1855 FastNewObjectStub stub(masm->isolate()); |
1849 __ CallStub(&stub); | 1856 __ CallStub(&stub); |
1850 __ Pop(FieldOperand(eax, JSValue::kValueOffset)); | 1857 __ Pop(FieldOperand(eax, JSValue::kValueOffset)); |
| 1858 __ LeaveBuiltinFrame(esi, edi, ecx); |
1851 } | 1859 } |
1852 __ Ret(); | 1860 |
| 1861 __ bind(&drop_frame_and_ret); |
| 1862 { |
| 1863 // Drop all arguments including the receiver. |
| 1864 __ PopReturnAddressTo(esi); |
| 1865 __ SmiUntag(ecx); |
| 1866 __ lea(esp, Operand(esp, ecx, times_pointer_size, kPointerSize)); |
| 1867 __ PushReturnAddressFrom(esi); |
| 1868 __ Ret(); |
| 1869 } |
1853 } | 1870 } |
1854 | 1871 |
1855 | 1872 |
1856 // static | 1873 // static |
1857 void Builtins::Generate_StringConstructor(MacroAssembler* masm) { | 1874 void Builtins::Generate_StringConstructor(MacroAssembler* masm) { |
1858 // ----------- S t a t e ------------- | 1875 // ----------- S t a t e ------------- |
1859 // -- eax : number of arguments | 1876 // -- eax : number of arguments |
1860 // -- edi : constructor function | 1877 // -- edi : constructor function |
| 1878 // -- esi : context |
1861 // -- esp[0] : return address | 1879 // -- esp[0] : return address |
1862 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1880 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1863 // -- esp[(argc + 1) * 4] : receiver | 1881 // -- esp[(argc + 1) * 4] : receiver |
1864 // ----------------------------------- | 1882 // ----------------------------------- |
1865 | 1883 |
1866 // 1. Load the first argument into eax and get rid of the rest (including the | 1884 // 1. Load the first argument into eax. |
1867 // receiver). | |
1868 Label no_arguments; | 1885 Label no_arguments; |
1869 { | 1886 { |
| 1887 __ mov(ebx, eax); // Store argc in ebx. |
1870 __ test(eax, eax); | 1888 __ test(eax, eax); |
1871 __ j(zero, &no_arguments, Label::kNear); | 1889 __ j(zero, &no_arguments, Label::kNear); |
1872 __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); | 1890 __ mov(eax, Operand(esp, eax, times_pointer_size, 0)); |
1873 __ PopReturnAddressTo(ecx); | |
1874 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); | |
1875 __ PushReturnAddressFrom(ecx); | |
1876 __ mov(eax, ebx); | |
1877 } | 1891 } |
1878 | 1892 |
1879 // 2a. At least one argument, return eax if it's a string, otherwise | 1893 // 2a. At least one argument, return eax if it's a string, otherwise |
1880 // dispatch to appropriate conversion. | 1894 // dispatch to appropriate conversion. |
1881 Label to_string, symbol_descriptive_string; | 1895 Label drop_frame_and_ret, to_string, symbol_descriptive_string; |
1882 { | 1896 { |
1883 __ JumpIfSmi(eax, &to_string, Label::kNear); | 1897 __ JumpIfSmi(eax, &to_string, Label::kNear); |
1884 STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE); | 1898 STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE); |
1885 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); | 1899 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); |
1886 __ j(above, &to_string, Label::kNear); | 1900 __ j(above, &to_string, Label::kNear); |
1887 __ j(equal, &symbol_descriptive_string, Label::kNear); | 1901 __ j(equal, &symbol_descriptive_string, Label::kNear); |
1888 __ Ret(); | 1902 __ jmp(&drop_frame_and_ret, Label::kNear); |
1889 } | 1903 } |
1890 | 1904 |
1891 // 2b. No arguments, return the empty string (and pop the receiver). | 1905 // 2b. No arguments, return the empty string (and pop the receiver). |
1892 __ bind(&no_arguments); | 1906 __ bind(&no_arguments); |
1893 { | 1907 { |
1894 __ LoadRoot(eax, Heap::kempty_stringRootIndex); | 1908 __ LoadRoot(eax, Heap::kempty_stringRootIndex); |
1895 __ ret(1 * kPointerSize); | 1909 __ ret(1 * kPointerSize); |
1896 } | 1910 } |
1897 | 1911 |
1898 // 3a. Convert eax to a string. | 1912 // 3a. Convert eax to a string. |
1899 __ bind(&to_string); | 1913 __ bind(&to_string); |
1900 { | 1914 { |
| 1915 FrameScope scope(masm, StackFrame::MANUAL); |
1901 ToStringStub stub(masm->isolate()); | 1916 ToStringStub stub(masm->isolate()); |
1902 __ TailCallStub(&stub); | 1917 __ SmiTag(ebx); |
| 1918 __ EnterBuiltinFrame(esi, edi, ebx); |
| 1919 __ CallStub(&stub); |
| 1920 __ LeaveBuiltinFrame(esi, edi, ebx); |
| 1921 __ SmiUntag(ebx); |
1903 } | 1922 } |
| 1923 __ jmp(&drop_frame_and_ret, Label::kNear); |
1904 | 1924 |
1905 // 3b. Convert symbol in eax to a string. | 1925 // 3b. Convert symbol in eax to a string. |
1906 __ bind(&symbol_descriptive_string); | 1926 __ bind(&symbol_descriptive_string); |
1907 { | 1927 { |
1908 __ PopReturnAddressTo(ecx); | 1928 __ PopReturnAddressTo(ecx); |
| 1929 __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize)); |
1909 __ Push(eax); | 1930 __ Push(eax); |
1910 __ PushReturnAddressFrom(ecx); | 1931 __ PushReturnAddressFrom(ecx); |
1911 __ TailCallRuntime(Runtime::kSymbolDescriptiveString); | 1932 __ TailCallRuntime(Runtime::kSymbolDescriptiveString); |
1912 } | 1933 } |
| 1934 |
| 1935 __ bind(&drop_frame_and_ret); |
| 1936 { |
| 1937 // Drop all arguments including the receiver. |
| 1938 __ PopReturnAddressTo(ecx); |
| 1939 __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize)); |
| 1940 __ PushReturnAddressFrom(ecx); |
| 1941 __ Ret(); |
| 1942 } |
1913 } | 1943 } |
1914 | 1944 |
1915 | 1945 |
1916 // static | 1946 // static |
1917 void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) { | 1947 void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) { |
1918 // ----------- S t a t e ------------- | 1948 // ----------- S t a t e ------------- |
1919 // -- eax : number of arguments | 1949 // -- eax : number of arguments |
1920 // -- edi : constructor function | 1950 // -- edi : constructor function |
1921 // -- edx : new target | 1951 // -- edx : new target |
| 1952 // -- esi : context |
1922 // -- esp[0] : return address | 1953 // -- esp[0] : return address |
1923 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1954 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1924 // -- esp[(argc + 1) * 4] : receiver | 1955 // -- esp[(argc + 1) * 4] : receiver |
1925 // ----------------------------------- | 1956 // ----------------------------------- |
1926 | 1957 |
1927 // 1. Make sure we operate in the context of the called function. | 1958 // 1. Make sure we operate in the context of the called function. |
1928 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 1959 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
1929 | 1960 |
1930 // 2. Load the first argument into ebx and get rid of the rest (including the | 1961 __ mov(ebx, eax); |
1931 // receiver). | 1962 |
| 1963 // 2. Load the first argument into eax. |
1932 { | 1964 { |
1933 Label no_arguments, done; | 1965 Label no_arguments, done; |
1934 __ test(eax, eax); | 1966 __ test(ebx, ebx); |
1935 __ j(zero, &no_arguments, Label::kNear); | 1967 __ j(zero, &no_arguments, Label::kNear); |
1936 __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); | 1968 __ mov(eax, Operand(esp, ebx, times_pointer_size, 0)); |
1937 __ jmp(&done, Label::kNear); | 1969 __ jmp(&done, Label::kNear); |
1938 __ bind(&no_arguments); | 1970 __ bind(&no_arguments); |
1939 __ LoadRoot(ebx, Heap::kempty_stringRootIndex); | 1971 __ LoadRoot(eax, Heap::kempty_stringRootIndex); |
1940 __ bind(&done); | 1972 __ bind(&done); |
1941 __ PopReturnAddressTo(ecx); | |
1942 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); | |
1943 __ PushReturnAddressFrom(ecx); | |
1944 } | 1973 } |
1945 | 1974 |
1946 // 3. Make sure ebx is a string. | 1975 // 3. Make sure eax is a string. |
1947 { | 1976 { |
1948 Label convert, done_convert; | 1977 Label convert, done_convert; |
1949 __ JumpIfSmi(ebx, &convert, Label::kNear); | 1978 __ JumpIfSmi(eax, &convert, Label::kNear); |
1950 __ CmpObjectType(ebx, FIRST_NONSTRING_TYPE, ecx); | 1979 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx); |
1951 __ j(below, &done_convert); | 1980 __ j(below, &done_convert); |
1952 __ bind(&convert); | 1981 __ bind(&convert); |
1953 { | 1982 { |
1954 FrameScope scope(masm, StackFrame::INTERNAL); | 1983 FrameScope scope(masm, StackFrame::MANUAL); |
1955 ToStringStub stub(masm->isolate()); | 1984 ToStringStub stub(masm->isolate()); |
1956 __ Push(edi); | 1985 __ SmiTag(ebx); |
| 1986 __ EnterBuiltinFrame(esi, edi, ebx); |
1957 __ Push(edx); | 1987 __ Push(edx); |
1958 __ Move(eax, ebx); | |
1959 __ CallStub(&stub); | 1988 __ CallStub(&stub); |
1960 __ Move(ebx, eax); | |
1961 __ Pop(edx); | 1989 __ Pop(edx); |
1962 __ Pop(edi); | 1990 __ LeaveBuiltinFrame(esi, edi, ebx); |
| 1991 __ SmiUntag(ebx); |
1963 } | 1992 } |
1964 __ bind(&done_convert); | 1993 __ bind(&done_convert); |
1965 } | 1994 } |
1966 | 1995 |
1967 // 4. Check if new target and constructor differ. | 1996 // 4. Check if new target and constructor differ. |
1968 Label new_object; | 1997 Label drop_frame_and_ret, done_alloc, new_object; |
1969 __ cmp(edx, edi); | 1998 __ cmp(edx, edi); |
1970 __ j(not_equal, &new_object); | 1999 __ j(not_equal, &new_object); |
1971 | 2000 |
1972 // 5. Allocate a JSValue wrapper for the string. | 2001 // 5. Allocate a JSValue wrapper for the string. |
1973 __ AllocateJSValue(eax, edi, ebx, ecx, &new_object); | 2002 // AllocateJSValue can't handle src == dst register. Reuse esi and restore it |
1974 __ Ret(); | 2003 // as needed after the call. |
| 2004 __ mov(esi, eax); |
| 2005 __ AllocateJSValue(eax, edi, esi, ecx, &done_alloc); |
| 2006 __ jmp(&drop_frame_and_ret); |
| 2007 |
| 2008 __ bind(&done_alloc); |
| 2009 { |
| 2010 // Restore eax to the first argument and esi to the context. |
| 2011 __ mov(eax, esi); |
| 2012 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 2013 } |
1975 | 2014 |
1976 // 6. Fallback to the runtime to create new object. | 2015 // 6. Fallback to the runtime to create new object. |
1977 __ bind(&new_object); | 2016 __ bind(&new_object); |
1978 { | 2017 { |
1979 FrameScope scope(masm, StackFrame::INTERNAL); | 2018 FrameScope scope(masm, StackFrame::MANUAL); |
1980 __ Push(ebx); // the first argument | 2019 __ SmiTag(ebx); |
| 2020 __ EnterBuiltinFrame(esi, edi, ebx); |
| 2021 __ Push(eax); // the first argument |
1981 FastNewObjectStub stub(masm->isolate()); | 2022 FastNewObjectStub stub(masm->isolate()); |
1982 __ CallStub(&stub); | 2023 __ CallStub(&stub); |
1983 __ Pop(FieldOperand(eax, JSValue::kValueOffset)); | 2024 __ Pop(FieldOperand(eax, JSValue::kValueOffset)); |
| 2025 __ LeaveBuiltinFrame(esi, edi, ebx); |
| 2026 __ SmiUntag(ebx); |
1984 } | 2027 } |
1985 __ Ret(); | 2028 |
| 2029 __ bind(&drop_frame_and_ret); |
| 2030 { |
| 2031 // Drop all arguments including the receiver. |
| 2032 __ PopReturnAddressTo(ecx); |
| 2033 __ lea(esp, Operand(esp, ebx, times_pointer_size, kPointerSize)); |
| 2034 __ PushReturnAddressFrom(ecx); |
| 2035 __ Ret(); |
| 2036 } |
1986 } | 2037 } |
1987 | 2038 |
1988 | 2039 |
1989 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm, | 2040 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm, |
1990 Label* stack_overflow) { | 2041 Label* stack_overflow) { |
1991 // ----------- S t a t e ------------- | 2042 // ----------- S t a t e ------------- |
1992 // -- eax : actual number of arguments | 2043 // -- eax : actual number of arguments |
1993 // -- ebx : expected number of arguments | 2044 // -- ebx : expected number of arguments |
1994 // -- edx : new target (passed through to callee) | 2045 // -- edx : new target (passed through to callee) |
1995 // ----------------------------------- | 2046 // ----------------------------------- |
(...skipping 1053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3049 // And "return" to the OSR entry point of the function. | 3100 // And "return" to the OSR entry point of the function. |
3050 __ ret(0); | 3101 __ ret(0); |
3051 } | 3102 } |
3052 | 3103 |
3053 | 3104 |
3054 #undef __ | 3105 #undef __ |
3055 } // namespace internal | 3106 } // namespace internal |
3056 } // namespace v8 | 3107 } // namespace v8 |
3057 | 3108 |
3058 #endif // V8_TARGET_ARCH_X87 | 3109 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |