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_X64 | 5 #if V8_TARGET_ARCH_X64 |
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 1305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1316 __ Move(arg_reg_2, Smi::FromInt(field_index)); | 1316 __ Move(arg_reg_2, Smi::FromInt(field_index)); |
1317 __ CallCFunction( | 1317 __ CallCFunction( |
1318 ExternalReference::get_date_field_function(masm->isolate()), 2); | 1318 ExternalReference::get_date_field_function(masm->isolate()), 2); |
1319 } | 1319 } |
1320 __ ret(1 * kPointerSize); | 1320 __ ret(1 * kPointerSize); |
1321 | 1321 |
1322 // 3. Raise a TypeError if the receiver is not a date. | 1322 // 3. Raise a TypeError if the receiver is not a date. |
1323 __ bind(&receiver_not_date); | 1323 __ bind(&receiver_not_date); |
1324 { | 1324 { |
1325 FrameScope scope(masm, StackFrame::MANUAL); | 1325 FrameScope scope(masm, StackFrame::MANUAL); |
1326 __ Push(rbp); | 1326 __ Move(rbx, Smi::FromInt(0)); |
1327 __ Move(rbp, rsp); | 1327 __ EnterBuiltinFrame(rsi, rdi, rbx); |
1328 __ Push(rsi); | |
1329 __ Push(rdi); | |
1330 __ Push(Immediate(0)); | |
1331 __ CallRuntime(Runtime::kThrowNotDateError); | 1328 __ CallRuntime(Runtime::kThrowNotDateError); |
1332 } | 1329 } |
1333 } | 1330 } |
1334 | 1331 |
1335 // static | 1332 // static |
1336 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { | 1333 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { |
1337 // ----------- S t a t e ------------- | 1334 // ----------- S t a t e ------------- |
1338 // -- rax : argc | 1335 // -- rax : argc |
1339 // -- rsp[0] : return address | 1336 // -- rsp[0] : return address |
1340 // -- rsp[8] : argArray | 1337 // -- rsp[8] : argArray |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1666 } | 1663 } |
1667 | 1664 |
1668 __ movp(rdx, rdi); | 1665 __ movp(rdx, rdi); |
1669 // Run the native code for the Array function called as a normal function. | 1666 // Run the native code for the Array function called as a normal function. |
1670 // tail call a stub | 1667 // tail call a stub |
1671 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); | 1668 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); |
1672 ArrayConstructorStub stub(masm->isolate()); | 1669 ArrayConstructorStub stub(masm->isolate()); |
1673 __ TailCallStub(&stub); | 1670 __ TailCallStub(&stub); |
1674 } | 1671 } |
1675 | 1672 |
1676 | |
1677 // static | 1673 // static |
1678 void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { | 1674 void Builtins::Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind) { |
1679 // ----------- S t a t e ------------- | 1675 // ----------- S t a t e ------------- |
1680 // -- rax : number of arguments | 1676 // -- rax : number of arguments |
1681 // -- rdi : function | 1677 // -- rdi : function |
1682 // -- rsi : context | 1678 // -- rsi : context |
1683 // -- rsp[0] : return address | 1679 // -- rsp[0] : return address |
1684 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1680 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
1685 // -- rsp[(argc + 1) * 8] : receiver | 1681 // -- rsp[(argc + 1) * 8] : receiver |
1686 // ----------------------------------- | 1682 // ----------------------------------- |
(...skipping 22 matching lines...) Expand all Loading... | |
1709 // Load the double value of the parameter into xmm1, maybe converting the | 1705 // Load the double value of the parameter into xmm1, maybe converting the |
1710 // parameter to a number first using the ToNumber builtin if necessary. | 1706 // parameter to a number first using the ToNumber builtin if necessary. |
1711 Label convert, convert_smi, convert_number, done_convert; | 1707 Label convert, convert_smi, convert_number, done_convert; |
1712 __ bind(&convert); | 1708 __ bind(&convert); |
1713 __ JumpIfSmi(rbx, &convert_smi); | 1709 __ JumpIfSmi(rbx, &convert_smi); |
1714 __ JumpIfRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 1710 __ JumpIfRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
1715 Heap::kHeapNumberMapRootIndex, &convert_number); | 1711 Heap::kHeapNumberMapRootIndex, &convert_number); |
1716 { | 1712 { |
1717 // Parameter is not a Number, use the ToNumber builtin to convert it. | 1713 // Parameter is not a Number, use the ToNumber builtin to convert it. |
1718 FrameScope scope(masm, StackFrame::MANUAL); | 1714 FrameScope scope(masm, StackFrame::MANUAL); |
1719 __ Push(rbp); | |
1720 __ Move(rbp, rsp); | |
1721 __ Push(rsi); | |
1722 __ Push(rdi); | |
1723 __ Integer32ToSmi(rax, rax); | 1715 __ Integer32ToSmi(rax, rax); |
1724 __ Integer32ToSmi(rcx, rcx); | 1716 __ Integer32ToSmi(rcx, rcx); |
1725 __ Push(rax); | 1717 __ EnterBuiltinFrame(rsi, rdi, rax); |
1726 __ Push(rcx); | 1718 __ Push(rcx); |
1727 __ Push(rdx); | 1719 __ Push(rdx); |
1728 __ movp(rax, rbx); | 1720 __ movp(rax, rbx); |
1729 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); | 1721 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); |
1730 __ movp(rbx, rax); | 1722 __ movp(rbx, rax); |
1731 __ Pop(rdx); | 1723 __ Pop(rdx); |
1732 __ Pop(rcx); | 1724 __ Pop(rcx); |
1733 __ Pop(rax); | 1725 __ LeaveBuiltinFrame(rsi, rdi, rax); |
1734 __ Pop(rdi); | 1726 __ SmiToInteger32(rcx, rcx); |
1735 __ Pop(rsi); | 1727 __ SmiToInteger32(rax, rax); |
1736 { | 1728 { |
1737 // Restore the double accumulator value (xmm0). | 1729 // Restore the double accumulator value (xmm0). |
1738 Label restore_smi, done_restore; | 1730 Label restore_smi, done_restore; |
1739 __ JumpIfSmi(rdx, &restore_smi, Label::kNear); | 1731 __ JumpIfSmi(rdx, &restore_smi, Label::kNear); |
1740 __ Movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); | 1732 __ Movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); |
1741 __ jmp(&done_restore, Label::kNear); | 1733 __ jmp(&done_restore, Label::kNear); |
1742 __ bind(&restore_smi); | 1734 __ bind(&restore_smi); |
1743 __ SmiToDouble(xmm0, rdx); | 1735 __ SmiToDouble(xmm0, rdx); |
1744 __ bind(&done_restore); | 1736 __ bind(&done_restore); |
1745 } | 1737 } |
1746 __ SmiToInteger32(rcx, rcx); | |
1747 __ SmiToInteger32(rax, rax); | |
1748 __ leave(); | |
1749 } | 1738 } |
1750 __ jmp(&convert); | 1739 __ jmp(&convert); |
1751 __ bind(&convert_number); | 1740 __ bind(&convert_number); |
1752 __ Movsd(xmm1, FieldOperand(rbx, HeapNumber::kValueOffset)); | 1741 __ Movsd(xmm1, FieldOperand(rbx, HeapNumber::kValueOffset)); |
1753 __ jmp(&done_convert, Label::kNear); | 1742 __ jmp(&done_convert, Label::kNear); |
1754 __ bind(&convert_smi); | 1743 __ bind(&convert_smi); |
1755 __ SmiToDouble(xmm1, rbx); | 1744 __ SmiToDouble(xmm1, rbx); |
1756 __ bind(&done_convert); | 1745 __ bind(&done_convert); |
1757 | 1746 |
1758 // Perform the actual comparison with the accumulator value on the left hand | 1747 // Perform the actual comparison with the accumulator value on the left hand |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1792 __ PushReturnAddressFrom(rcx); | 1781 __ PushReturnAddressFrom(rcx); |
1793 __ movp(rax, rdx); | 1782 __ movp(rax, rdx); |
1794 __ Ret(); | 1783 __ Ret(); |
1795 } | 1784 } |
1796 | 1785 |
1797 // static | 1786 // static |
1798 void Builtins::Generate_NumberConstructor(MacroAssembler* masm) { | 1787 void Builtins::Generate_NumberConstructor(MacroAssembler* masm) { |
1799 // ----------- S t a t e ------------- | 1788 // ----------- S t a t e ------------- |
1800 // -- rax : number of arguments | 1789 // -- rax : number of arguments |
1801 // -- rdi : constructor function | 1790 // -- rdi : constructor function |
1791 // -- rsi : context | |
1802 // -- rsp[0] : return address | 1792 // -- rsp[0] : return address |
1803 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1793 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
1804 // -- rsp[(argc + 1) * 8] : receiver | 1794 // -- rsp[(argc + 1) * 8] : receiver |
1805 // ----------------------------------- | 1795 // ----------------------------------- |
1806 | 1796 |
1807 // 1. Load the first argument into rax and get rid of the rest (including the | 1797 // 1. Load the first argument into rbx. |
1808 // receiver). | |
1809 Label no_arguments; | 1798 Label no_arguments; |
1810 { | 1799 { |
1811 StackArgumentsAccessor args(rsp, rax); | 1800 StackArgumentsAccessor args(rsp, rax); |
1812 __ testp(rax, rax); | 1801 __ testp(rax, rax); |
1813 __ j(zero, &no_arguments, Label::kNear); | 1802 __ j(zero, &no_arguments, Label::kNear); |
1814 __ movp(rbx, args.GetArgumentOperand(1)); | 1803 __ movp(rbx, args.GetArgumentOperand(1)); |
1815 __ PopReturnAddressTo(rcx); | |
1816 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); | |
1817 __ PushReturnAddressFrom(rcx); | |
1818 __ movp(rax, rbx); | |
1819 } | 1804 } |
1820 | 1805 |
1821 // 2a. Convert the first argument to a number. | 1806 // 2a. Convert the first argument to a number. |
1822 __ Jump(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); | 1807 { |
1808 FrameScope scope(masm, StackFrame::MANUAL); | |
1809 __ Integer32ToSmi(rax, rax); | |
1810 __ EnterBuiltinFrame(rsi, rdi, rax); | |
1811 __ movp(rax, rbx); | |
1812 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); | |
1813 __ LeaveBuiltinFrame(rsi, rdi, rbx); // Argc popped to rbc. | |
1814 __ SmiToInteger32(rbx, rbx); | |
1815 } | |
1816 | |
1817 __ PopReturnAddressTo(rcx); | |
1818 __ leap(rsp, Operand(rsp, rbx, times_pointer_size, kPointerSize)); | |
1819 __ PushReturnAddressFrom(rcx); | |
1820 __ Ret(); | |
1823 | 1821 |
1824 // 2b. No arguments, return +0 (already in rax). | 1822 // 2b. No arguments, return +0 (already in rax). |
1825 __ bind(&no_arguments); | 1823 __ bind(&no_arguments); |
1826 __ ret(1 * kPointerSize); | 1824 __ ret(1 * kPointerSize); |
1827 } | 1825 } |
1828 | 1826 |
1829 | 1827 |
1830 // static | 1828 // static |
1831 void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) { | 1829 void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) { |
1832 // ----------- S t a t e ------------- | 1830 // ----------- S t a t e ------------- |
1833 // -- rax : number of arguments | 1831 // -- rax : number of arguments |
1834 // -- rdi : constructor function | 1832 // -- rdi : constructor function |
1833 // -- rsi : context | |
1835 // -- rdx : new target | 1834 // -- rdx : new target |
1836 // -- rsp[0] : return address | 1835 // -- rsp[0] : return address |
1837 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1836 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
1838 // -- rsp[(argc + 1) * 8] : receiver | 1837 // -- rsp[(argc + 1) * 8] : receiver |
1839 // ----------------------------------- | 1838 // ----------------------------------- |
1840 | 1839 |
1841 // 1. Make sure we operate in the context of the called function. | 1840 // 1. Make sure we operate in the context of the called function. |
1842 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 1841 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
1843 | 1842 |
1844 // 2. Load the first argument into rbx and get rid of the rest (including the | 1843 // 2. Load the first argument into rbx. |
1845 // receiver). | |
1846 { | 1844 { |
1847 StackArgumentsAccessor args(rsp, rax); | 1845 StackArgumentsAccessor args(rsp, rax); |
1848 Label no_arguments, done; | 1846 Label no_arguments, done; |
1849 __ testp(rax, rax); | 1847 __ testp(rax, rax); |
1850 __ j(zero, &no_arguments, Label::kNear); | 1848 __ j(zero, &no_arguments, Label::kNear); |
1851 __ movp(rbx, args.GetArgumentOperand(1)); | 1849 __ movp(rbx, args.GetArgumentOperand(1)); |
1852 __ jmp(&done, Label::kNear); | 1850 __ jmp(&done, Label::kNear); |
1853 __ bind(&no_arguments); | 1851 __ bind(&no_arguments); |
1854 __ Move(rbx, Smi::FromInt(0)); | 1852 __ Move(rbx, Smi::FromInt(0)); |
1855 __ bind(&done); | 1853 __ bind(&done); |
1856 __ PopReturnAddressTo(rcx); | |
1857 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); | |
1858 __ PushReturnAddressFrom(rcx); | |
1859 } | 1854 } |
1860 | 1855 |
1861 // 3. Make sure rbx is a number. | 1856 // 3. Make sure rbx is a number. |
1862 { | 1857 { |
1863 Label done_convert; | 1858 Label done_convert; |
1864 __ JumpIfSmi(rbx, &done_convert); | 1859 __ JumpIfSmi(rbx, &done_convert); |
1865 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 1860 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
1866 Heap::kHeapNumberMapRootIndex); | 1861 Heap::kHeapNumberMapRootIndex); |
1867 __ j(equal, &done_convert); | 1862 __ j(equal, &done_convert); |
1868 { | 1863 { |
1869 FrameScope scope(masm, StackFrame::INTERNAL); | 1864 FrameScope scope(masm, StackFrame::MANUAL); |
1865 __ Integer32ToSmi(rax, rax); | |
1866 __ EnterBuiltinFrame(rsi, rdi, rax); | |
1870 __ Push(rdx); | 1867 __ Push(rdx); |
1871 __ Push(rdi); | |
1872 __ Move(rax, rbx); | 1868 __ Move(rax, rbx); |
1873 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); | 1869 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); |
1874 __ Move(rbx, rax); | 1870 __ Move(rbx, rax); |
1875 __ Pop(rdi); | |
1876 __ Pop(rdx); | 1871 __ Pop(rdx); |
1872 __ LeaveBuiltinFrame(rsi, rdi, rax); | |
1873 __ SmiToInteger32(rax, rax); | |
1877 } | 1874 } |
1878 __ bind(&done_convert); | 1875 __ bind(&done_convert); |
1876 | |
1877 // Drop all arguments including the receiver. | |
1878 __ PopReturnAddressTo(rcx); | |
1879 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); | |
1880 __ PushReturnAddressFrom(rcx); | |
1879 } | 1881 } |
1880 | 1882 |
1881 // 4. Check if new target and constructor differ. | 1883 // 4. Check if new target and constructor differ. |
1882 Label new_object; | 1884 Label new_object; |
1883 __ cmpp(rdx, rdi); | 1885 __ cmpp(rdx, rdi); |
1884 __ j(not_equal, &new_object); | 1886 __ j(not_equal, &new_object); |
1885 | 1887 |
1886 // 5. Allocate a JSValue wrapper for the number. | 1888 // 5. Allocate a JSValue wrapper for the number. |
1887 __ AllocateJSValue(rax, rdi, rbx, rcx, &new_object); | 1889 __ AllocateJSValue(rax, rdi, rbx, rcx, &new_object); |
1888 __ Ret(); | 1890 __ Ret(); |
1889 | 1891 |
1890 // 6. Fallback to the runtime to create new object. | 1892 // 6. Fallback to the runtime to create new object. |
1891 __ bind(&new_object); | 1893 __ bind(&new_object); |
1892 { | 1894 { |
1895 // TODO(jgruber): Is a builtin frame needed here? | |
jgruber
2016/07/04 13:25:45
Just double-checking - do we want a builtin frame
Benedikt Meurer
2016/07/04 16:45:36
Yes because of new.target this is actually observa
jgruber
2016/07/07 11:50:52
Done.
| |
1893 FrameScope scope(masm, StackFrame::INTERNAL); | 1896 FrameScope scope(masm, StackFrame::INTERNAL); |
1894 __ Push(rbx); // the first argument | 1897 __ Push(rbx); // the first argument |
1895 FastNewObjectStub stub(masm->isolate()); | 1898 FastNewObjectStub stub(masm->isolate()); |
1896 __ CallStub(&stub); | 1899 __ CallStub(&stub); |
1897 __ Pop(FieldOperand(rax, JSValue::kValueOffset)); | 1900 __ Pop(FieldOperand(rax, JSValue::kValueOffset)); |
1898 } | 1901 } |
1902 | |
1899 __ Ret(); | 1903 __ Ret(); |
1900 } | 1904 } |
1901 | 1905 |
1902 | 1906 |
1903 // static | 1907 // static |
1904 void Builtins::Generate_StringConstructor(MacroAssembler* masm) { | 1908 void Builtins::Generate_StringConstructor(MacroAssembler* masm) { |
1905 // ----------- S t a t e ------------- | 1909 // ----------- S t a t e ------------- |
1906 // -- rax : number of arguments | 1910 // -- rax : number of arguments |
1907 // -- rdi : constructor function | 1911 // -- rdi : constructor function |
1912 // -- rsi : context | |
1908 // -- rsp[0] : return address | 1913 // -- rsp[0] : return address |
1909 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1914 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
1910 // -- rsp[(argc + 1) * 8] : receiver | 1915 // -- rsp[(argc + 1) * 8] : receiver |
1911 // ----------------------------------- | 1916 // ----------------------------------- |
1912 | 1917 |
1913 // 1. Load the first argument into rax and get rid of the rest (including the | 1918 // 1. Load the first argument into rax and get rid of the rest (including the |
1914 // receiver). | 1919 // receiver). |
1915 Label no_arguments; | 1920 Label no_arguments; |
1916 { | 1921 { |
1917 StackArgumentsAccessor args(rsp, rax); | 1922 StackArgumentsAccessor args(rsp, rax); |
1923 __ movp(r8, rax); // Store argc in r8. | |
1918 __ testp(rax, rax); | 1924 __ testp(rax, rax); |
1919 __ j(zero, &no_arguments, Label::kNear); | 1925 __ j(zero, &no_arguments, Label::kNear); |
1920 __ movp(rbx, args.GetArgumentOperand(1)); | 1926 __ movp(rax, args.GetArgumentOperand(1)); |
1921 __ PopReturnAddressTo(rcx); | |
1922 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); | |
1923 __ PushReturnAddressFrom(rcx); | |
1924 __ movp(rax, rbx); | |
1925 } | 1927 } |
1926 | 1928 |
1927 // 2a. At least one argument, return rax if it's a string, otherwise | 1929 // 2a. At least one argument, return rax if it's a string, otherwise |
1928 // dispatch to appropriate conversion. | 1930 // dispatch to appropriate conversion. |
1929 Label to_string, symbol_descriptive_string; | 1931 Label done, to_string, symbol_descriptive_string; |
1930 { | 1932 { |
1931 __ JumpIfSmi(rax, &to_string, Label::kNear); | 1933 __ JumpIfSmi(rax, &to_string, Label::kNear); |
1932 STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE); | 1934 STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE); |
1933 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); | 1935 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); |
1934 __ j(above, &to_string, Label::kNear); | 1936 __ j(above, &to_string, Label::kNear); |
1935 __ j(equal, &symbol_descriptive_string, Label::kNear); | 1937 __ j(equal, &symbol_descriptive_string, Label::kNear); |
1936 __ Ret(); | 1938 __ jmp(&done, Label::kNear); |
1937 } | 1939 } |
1938 | 1940 |
1939 // 2b. No arguments, return the empty string (and pop the receiver). | 1941 // 2b. No arguments, return the empty string (and pop the receiver). |
1940 __ bind(&no_arguments); | 1942 __ bind(&no_arguments); |
1941 { | 1943 { |
1942 __ LoadRoot(rax, Heap::kempty_stringRootIndex); | 1944 __ LoadRoot(rax, Heap::kempty_stringRootIndex); |
1943 __ ret(1 * kPointerSize); | 1945 __ ret(1 * kPointerSize); |
1944 } | 1946 } |
1945 | 1947 |
1946 // 3a. Convert rax to a string. | 1948 // 3a. Convert rax to a string. |
1947 __ bind(&to_string); | 1949 __ bind(&to_string); |
1948 { | 1950 { |
1951 FrameScope scope(masm, StackFrame::MANUAL); | |
1949 ToStringStub stub(masm->isolate()); | 1952 ToStringStub stub(masm->isolate()); |
1950 __ TailCallStub(&stub); | 1953 __ Integer32ToSmi(r8, r8); |
1954 __ EnterBuiltinFrame(rsi, rdi, r8); | |
1955 __ CallStub(&stub); | |
1956 __ LeaveBuiltinFrame(rsi, rdi, r8); | |
1957 __ SmiToInteger32(r8, r8); | |
1951 } | 1958 } |
1959 __ jmp(&done, Label::kNear); | |
1952 | 1960 |
1953 // 3b. Convert symbol in rax to a string. | 1961 // 3b. Convert symbol in rax to a string. |
1954 __ bind(&symbol_descriptive_string); | 1962 __ bind(&symbol_descriptive_string); |
1955 { | 1963 { |
1956 __ PopReturnAddressTo(rcx); | 1964 __ PopReturnAddressTo(rcx); |
1965 __ leap(rsp, Operand(rsp, r8, times_pointer_size, kPointerSize)); | |
1957 __ Push(rax); | 1966 __ Push(rax); |
1958 __ PushReturnAddressFrom(rcx); | 1967 __ PushReturnAddressFrom(rcx); |
1959 __ TailCallRuntime(Runtime::kSymbolDescriptiveString); | 1968 __ TailCallRuntime(Runtime::kSymbolDescriptiveString); |
jgruber
2016/07/04 13:25:44
No builtin frame here because SymbolDescriptiveStr
Benedikt Meurer
2016/07/04 16:45:36
Acknowledged.
| |
1960 } | 1969 } |
1970 | |
1971 __ bind(&done); | |
1972 { | |
1973 __ PopReturnAddressTo(rcx); | |
1974 __ leap(rsp, Operand(rsp, r8, times_pointer_size, kPointerSize)); | |
1975 __ PushReturnAddressFrom(rcx); | |
1976 __ Ret(); | |
1977 } | |
1961 } | 1978 } |
1962 | 1979 |
1963 | 1980 |
1964 // static | 1981 // static |
1965 void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) { | 1982 void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) { |
1966 // ----------- S t a t e ------------- | 1983 // ----------- S t a t e ------------- |
1967 // -- rax : number of arguments | 1984 // -- rax : number of arguments |
1968 // -- rdi : constructor function | 1985 // -- rdi : constructor function |
1969 // -- rdx : new target | 1986 // -- rdx : new target |
1987 // -- rsi : context | |
1970 // -- rsp[0] : return address | 1988 // -- rsp[0] : return address |
1971 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1989 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
1972 // -- rsp[(argc + 1) * 8] : receiver | 1990 // -- rsp[(argc + 1) * 8] : receiver |
1973 // ----------------------------------- | 1991 // ----------------------------------- |
1974 | 1992 |
1975 // 1. Make sure we operate in the context of the called function. | 1993 // 1. Make sure we operate in the context of the called function. |
1976 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 1994 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
1977 | 1995 |
1978 // 2. Load the first argument into rbx and get rid of the rest (including the | 1996 // 2. Load the first argument into rbx. |
1979 // receiver). | |
1980 { | 1997 { |
1981 StackArgumentsAccessor args(rsp, rax); | 1998 StackArgumentsAccessor args(rsp, rax); |
1982 Label no_arguments, done; | 1999 Label no_arguments, done; |
1983 __ testp(rax, rax); | 2000 __ testp(rax, rax); |
1984 __ j(zero, &no_arguments, Label::kNear); | 2001 __ j(zero, &no_arguments, Label::kNear); |
1985 __ movp(rbx, args.GetArgumentOperand(1)); | 2002 __ movp(rbx, args.GetArgumentOperand(1)); |
1986 __ jmp(&done, Label::kNear); | 2003 __ jmp(&done, Label::kNear); |
1987 __ bind(&no_arguments); | 2004 __ bind(&no_arguments); |
1988 __ LoadRoot(rbx, Heap::kempty_stringRootIndex); | 2005 __ LoadRoot(rbx, Heap::kempty_stringRootIndex); |
1989 __ bind(&done); | 2006 __ bind(&done); |
1990 __ PopReturnAddressTo(rcx); | |
1991 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); | |
1992 __ PushReturnAddressFrom(rcx); | |
1993 } | 2007 } |
1994 | 2008 |
1995 // 3. Make sure rbx is a string. | 2009 // 3. Make sure rbx is a string. |
1996 { | 2010 { |
1997 Label convert, done_convert; | 2011 Label convert, done_convert; |
1998 __ JumpIfSmi(rbx, &convert, Label::kNear); | 2012 __ JumpIfSmi(rbx, &convert, Label::kNear); |
1999 __ CmpObjectType(rbx, FIRST_NONSTRING_TYPE, rcx); | 2013 __ CmpObjectType(rbx, FIRST_NONSTRING_TYPE, rcx); |
2000 __ j(below, &done_convert); | 2014 __ j(below, &done_convert); |
2001 __ bind(&convert); | 2015 __ bind(&convert); |
2002 { | 2016 { |
2003 FrameScope scope(masm, StackFrame::INTERNAL); | 2017 FrameScope scope(masm, StackFrame::MANUAL); |
2004 ToStringStub stub(masm->isolate()); | 2018 ToStringStub stub(masm->isolate()); |
2019 __ Integer32ToSmi(rax, rax); | |
2020 __ EnterBuiltinFrame(rsi, rdi, rax); | |
2005 __ Push(rdx); | 2021 __ Push(rdx); |
2006 __ Push(rdi); | |
2007 __ Move(rax, rbx); | 2022 __ Move(rax, rbx); |
2008 __ CallStub(&stub); | 2023 __ CallStub(&stub); |
2009 __ Move(rbx, rax); | 2024 __ Move(rbx, rax); |
2010 __ Pop(rdi); | |
2011 __ Pop(rdx); | 2025 __ Pop(rdx); |
2026 __ LeaveBuiltinFrame(rsi, rdi, rax); | |
2027 __ SmiToInteger32(rax, rax); | |
2012 } | 2028 } |
2013 __ bind(&done_convert); | 2029 __ bind(&done_convert); |
2030 | |
2031 // Drop all arguments including the receiver. | |
2032 __ PopReturnAddressTo(rcx); | |
2033 __ leap(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize)); | |
2034 __ PushReturnAddressFrom(rcx); | |
2014 } | 2035 } |
2015 | 2036 |
2016 // 4. Check if new target and constructor differ. | 2037 // 4. Check if new target and constructor differ. |
2017 Label new_object; | 2038 Label new_object; |
2018 __ cmpp(rdx, rdi); | 2039 __ cmpp(rdx, rdi); |
2019 __ j(not_equal, &new_object); | 2040 __ j(not_equal, &new_object); |
2020 | 2041 |
2021 // 5. Allocate a JSValue wrapper for the string. | 2042 // 5. Allocate a JSValue wrapper for the string. |
2022 __ AllocateJSValue(rax, rdi, rbx, rcx, &new_object); | 2043 __ AllocateJSValue(rax, rdi, rbx, rcx, &new_object); |
2023 __ Ret(); | 2044 __ Ret(); |
2024 | 2045 |
2025 // 6. Fallback to the runtime to create new object. | 2046 // 6. Fallback to the runtime to create new object. |
2026 __ bind(&new_object); | 2047 __ bind(&new_object); |
2027 { | 2048 { |
2028 FrameScope scope(masm, StackFrame::INTERNAL); | 2049 FrameScope scope(masm, StackFrame::INTERNAL); |
2029 __ Push(rbx); // the first argument | 2050 __ Push(rbx); // the first argument |
jgruber
2016/07/04 13:25:44
As above.
Benedikt Meurer
2016/07/04 16:45:36
Yes, this is observable (thx to new.target...)
jgruber
2016/07/07 11:50:52
Done.
| |
2030 FastNewObjectStub stub(masm->isolate()); | 2051 FastNewObjectStub stub(masm->isolate()); |
2031 __ CallStub(&stub); | 2052 __ CallStub(&stub); |
2032 __ Pop(FieldOperand(rax, JSValue::kValueOffset)); | 2053 __ Pop(FieldOperand(rax, JSValue::kValueOffset)); |
2033 } | 2054 } |
2034 __ Ret(); | 2055 __ Ret(); |
2035 } | 2056 } |
2036 | 2057 |
2037 | 2058 |
2038 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm, | 2059 static void ArgumentsAdaptorStackCheck(MacroAssembler* masm, |
2039 Label* stack_overflow) { | 2060 Label* stack_overflow) { |
(...skipping 1044 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3084 __ ret(0); | 3105 __ ret(0); |
3085 } | 3106 } |
3086 | 3107 |
3087 | 3108 |
3088 #undef __ | 3109 #undef __ |
3089 | 3110 |
3090 } // namespace internal | 3111 } // namespace internal |
3091 } // namespace v8 | 3112 } // namespace v8 |
3092 | 3113 |
3093 #endif // V8_TARGET_ARCH_X64 | 3114 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |