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