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_MIPS64 | 5 #if V8_TARGET_ARCH_MIPS64 |
6 | 6 |
7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.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 1741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1752 // static | 1752 // static |
1753 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { | 1753 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { |
1754 // ----------- S t a t e ------------- | 1754 // ----------- S t a t e ------------- |
1755 // -- a0 : argc | 1755 // -- a0 : argc |
1756 // -- sp[0] : argArray | 1756 // -- sp[0] : argArray |
1757 // -- sp[4] : thisArg | 1757 // -- sp[4] : thisArg |
1758 // -- sp[8] : receiver | 1758 // -- sp[8] : receiver |
1759 // ----------------------------------- | 1759 // ----------------------------------- |
1760 | 1760 |
1761 Register argc = a0; | 1761 Register argc = a0; |
1762 Register arg_array = a0; | 1762 Register arg_array = a2; |
1763 Register receiver = a1; | 1763 Register receiver = a1; |
1764 Register this_arg = a2; | 1764 Register this_arg = a5; |
1765 Register undefined_value = a3; | 1765 Register undefined_value = a3; |
1766 Register scratch = a4; | 1766 Register scratch = a4; |
1767 | 1767 |
1768 __ LoadRoot(undefined_value, Heap::kUndefinedValueRootIndex); | 1768 __ LoadRoot(undefined_value, Heap::kUndefinedValueRootIndex); |
1769 // 1. Load receiver into a1, argArray into a0 (if present), remove all | 1769 // 1. Load receiver into a1, argArray into a2 (if present), remove all |
1770 // arguments from the stack (including the receiver), and push thisArg (if | 1770 // arguments from the stack (including the receiver), and push thisArg (if |
1771 // present) instead. | 1771 // present) instead. |
1772 { | 1772 { |
1773 // Claim (2 - argc) dummy arguments form the stack, to put the stack in a | 1773 // Claim (2 - argc) dummy arguments form the stack, to put the stack in a |
1774 // consistent state for a simple pop operation. | 1774 // consistent state for a simple pop operation. |
1775 | 1775 |
1776 __ Dsubu(sp, sp, Operand(2 * kPointerSize)); | 1776 __ Dsubu(sp, sp, Operand(2 * kPointerSize)); |
1777 __ Dlsa(sp, sp, argc, kPointerSizeLog2); | 1777 __ Dlsa(sp, sp, argc, kPointerSizeLog2); |
1778 __ mov(scratch, argc); | 1778 __ mov(scratch, argc); |
1779 __ Pop(this_arg, arg_array); // Overwrite argc | 1779 __ Pop(this_arg, arg_array); // Overwrite argc |
1780 __ Movz(arg_array, undefined_value, scratch); // if argc == 0 | 1780 __ Movz(arg_array, undefined_value, scratch); // if argc == 0 |
1781 __ Movz(this_arg, undefined_value, scratch); // if argc == 0 | 1781 __ Movz(this_arg, undefined_value, scratch); // if argc == 0 |
1782 __ Dsubu(scratch, scratch, Operand(1)); | 1782 __ Dsubu(scratch, scratch, Operand(1)); |
1783 __ Movz(arg_array, undefined_value, scratch); // if argc == 1 | 1783 __ Movz(arg_array, undefined_value, scratch); // if argc == 1 |
1784 __ Ld(receiver, MemOperand(sp)); | 1784 __ Ld(receiver, MemOperand(sp)); |
1785 __ Sd(this_arg, MemOperand(sp)); | 1785 __ Sd(this_arg, MemOperand(sp)); |
1786 } | 1786 } |
1787 | 1787 |
1788 // ----------- S t a t e ------------- | 1788 // ----------- S t a t e ------------- |
1789 // -- a0 : argArray | 1789 // -- a2 : argArray |
1790 // -- a1 : receiver | 1790 // -- a1 : receiver |
1791 // -- a3 : undefined root value | 1791 // -- a3 : undefined root value |
1792 // -- sp[0] : thisArg | 1792 // -- sp[0] : thisArg |
1793 // ----------------------------------- | 1793 // ----------------------------------- |
1794 | 1794 |
1795 // 2. Make sure the receiver is actually callable. | 1795 // 2. Make sure the receiver is actually callable. |
1796 Label receiver_not_callable; | 1796 Label receiver_not_callable; |
1797 __ JumpIfSmi(receiver, &receiver_not_callable); | 1797 __ JumpIfSmi(receiver, &receiver_not_callable); |
1798 __ Ld(a4, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1798 __ Ld(a4, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
1799 __ Lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset)); | 1799 __ Lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset)); |
1800 __ And(a4, a4, Operand(1 << Map::kIsCallable)); | 1800 __ And(a4, a4, Operand(1 << Map::kIsCallable)); |
1801 __ Branch(&receiver_not_callable, eq, a4, Operand(zero_reg)); | 1801 __ Branch(&receiver_not_callable, eq, a4, Operand(zero_reg)); |
1802 | 1802 |
1803 // 3. Tail call with no arguments if argArray is null or undefined. | 1803 // 3. Tail call with no arguments if argArray is null or undefined. |
1804 Label no_arguments; | 1804 Label no_arguments; |
1805 __ JumpIfRoot(arg_array, Heap::kNullValueRootIndex, &no_arguments); | 1805 __ JumpIfRoot(arg_array, Heap::kNullValueRootIndex, &no_arguments); |
1806 __ Branch(&no_arguments, eq, arg_array, Operand(undefined_value)); | 1806 __ Branch(&no_arguments, eq, arg_array, Operand(undefined_value)); |
1807 | 1807 |
1808 // 4a. Apply the receiver to the given argArray (passing undefined for | 1808 // 4a. Apply the receiver to the given argArray. |
1809 // new.target). | 1809 __ Jump(masm->isolate()->builtins()->CallWithArrayLike(), |
1810 DCHECK(undefined_value.is(a3)); | 1810 RelocInfo::CODE_TARGET); |
1811 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | |
1812 | 1811 |
1813 // 4b. The argArray is either null or undefined, so we tail call without any | 1812 // 4b. The argArray is either null or undefined, so we tail call without any |
1814 // arguments to the receiver. | 1813 // arguments to the receiver. |
1815 __ bind(&no_arguments); | 1814 __ bind(&no_arguments); |
1816 { | 1815 { |
1817 __ mov(a0, zero_reg); | 1816 __ mov(a0, zero_reg); |
1818 DCHECK(receiver.is(a1)); | 1817 DCHECK(receiver.is(a1)); |
1819 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1818 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
1820 } | 1819 } |
1821 | 1820 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1872 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { | 1871 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { |
1873 // ----------- S t a t e ------------- | 1872 // ----------- S t a t e ------------- |
1874 // -- a0 : argc | 1873 // -- a0 : argc |
1875 // -- sp[0] : argumentsList (if argc ==3) | 1874 // -- sp[0] : argumentsList (if argc ==3) |
1876 // -- sp[4] : thisArgument (if argc >=2) | 1875 // -- sp[4] : thisArgument (if argc >=2) |
1877 // -- sp[8] : target (if argc >=1) | 1876 // -- sp[8] : target (if argc >=1) |
1878 // -- sp[12] : receiver | 1877 // -- sp[12] : receiver |
1879 // ----------------------------------- | 1878 // ----------------------------------- |
1880 | 1879 |
1881 Register argc = a0; | 1880 Register argc = a0; |
1882 Register arguments_list = a0; | 1881 Register arguments_list = a2; |
1883 Register target = a1; | 1882 Register target = a1; |
1884 Register this_argument = a2; | 1883 Register this_argument = a5; |
1885 Register undefined_value = a3; | 1884 Register undefined_value = a3; |
1886 Register scratch = a4; | 1885 Register scratch = a4; |
1887 | 1886 |
1888 __ LoadRoot(undefined_value, Heap::kUndefinedValueRootIndex); | 1887 __ LoadRoot(undefined_value, Heap::kUndefinedValueRootIndex); |
1889 // 1. Load target into a1 (if present), argumentsList into a0 (if present), | 1888 // 1. Load target into a1 (if present), argumentsList into a2 (if present), |
1890 // remove all arguments from the stack (including the receiver), and push | 1889 // remove all arguments from the stack (including the receiver), and push |
1891 // thisArgument (if present) instead. | 1890 // thisArgument (if present) instead. |
1892 { | 1891 { |
1893 // Claim (3 - argc) dummy arguments form the stack, to put the stack in a | 1892 // Claim (3 - argc) dummy arguments form the stack, to put the stack in a |
1894 // consistent state for a simple pop operation. | 1893 // consistent state for a simple pop operation. |
1895 | 1894 |
1896 __ Dsubu(sp, sp, Operand(3 * kPointerSize)); | 1895 __ Dsubu(sp, sp, Operand(3 * kPointerSize)); |
1897 __ Dlsa(sp, sp, argc, kPointerSizeLog2); | 1896 __ Dlsa(sp, sp, argc, kPointerSizeLog2); |
1898 __ mov(scratch, argc); | 1897 __ mov(scratch, argc); |
1899 __ Pop(target, this_argument, arguments_list); | 1898 __ Pop(target, this_argument, arguments_list); |
1900 __ Movz(arguments_list, undefined_value, scratch); // if argc == 0 | 1899 __ Movz(arguments_list, undefined_value, scratch); // if argc == 0 |
1901 __ Movz(this_argument, undefined_value, scratch); // if argc == 0 | 1900 __ Movz(this_argument, undefined_value, scratch); // if argc == 0 |
1902 __ Movz(target, undefined_value, scratch); // if argc == 0 | 1901 __ Movz(target, undefined_value, scratch); // if argc == 0 |
1903 __ Dsubu(scratch, scratch, Operand(1)); | 1902 __ Dsubu(scratch, scratch, Operand(1)); |
1904 __ Movz(arguments_list, undefined_value, scratch); // if argc == 1 | 1903 __ Movz(arguments_list, undefined_value, scratch); // if argc == 1 |
1905 __ Movz(this_argument, undefined_value, scratch); // if argc == 1 | 1904 __ Movz(this_argument, undefined_value, scratch); // if argc == 1 |
1906 __ Dsubu(scratch, scratch, Operand(1)); | 1905 __ Dsubu(scratch, scratch, Operand(1)); |
1907 __ Movz(arguments_list, undefined_value, scratch); // if argc == 2 | 1906 __ Movz(arguments_list, undefined_value, scratch); // if argc == 2 |
1908 | 1907 |
1909 __ Sd(this_argument, MemOperand(sp, 0)); // Overwrite receiver | 1908 __ Sd(this_argument, MemOperand(sp, 0)); // Overwrite receiver |
1910 } | 1909 } |
1911 | 1910 |
1912 // ----------- S t a t e ------------- | 1911 // ----------- S t a t e ------------- |
1913 // -- a0 : argumentsList | 1912 // -- a2 : argumentsList |
1914 // -- a1 : target | 1913 // -- a1 : target |
1915 // -- a3 : undefined root value | 1914 // -- a3 : undefined root value |
1916 // -- sp[0] : thisArgument | 1915 // -- sp[0] : thisArgument |
1917 // ----------------------------------- | 1916 // ----------------------------------- |
1918 | 1917 |
1919 // 2. Make sure the target is actually callable. | 1918 // 2. Make sure the target is actually callable. |
1920 Label target_not_callable; | 1919 Label target_not_callable; |
1921 __ JumpIfSmi(target, &target_not_callable); | 1920 __ JumpIfSmi(target, &target_not_callable); |
1922 __ Ld(a4, FieldMemOperand(target, HeapObject::kMapOffset)); | 1921 __ Ld(a4, FieldMemOperand(target, HeapObject::kMapOffset)); |
1923 __ Lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset)); | 1922 __ Lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset)); |
1924 __ And(a4, a4, Operand(1 << Map::kIsCallable)); | 1923 __ And(a4, a4, Operand(1 << Map::kIsCallable)); |
1925 __ Branch(&target_not_callable, eq, a4, Operand(zero_reg)); | 1924 __ Branch(&target_not_callable, eq, a4, Operand(zero_reg)); |
1926 | 1925 |
1927 // 3a. Apply the target to the given argumentsList (passing undefined for | 1926 // 3a. Apply the target to the given argumentsList. |
1928 // new.target). | 1927 __ Jump(masm->isolate()->builtins()->CallWithArrayLike(), |
1929 DCHECK(undefined_value.is(a3)); | 1928 RelocInfo::CODE_TARGET); |
1930 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | |
1931 | 1929 |
1932 // 3b. The target is not callable, throw an appropriate TypeError. | 1930 // 3b. The target is not callable, throw an appropriate TypeError. |
1933 __ bind(&target_not_callable); | 1931 __ bind(&target_not_callable); |
1934 { | 1932 { |
1935 __ Sd(target, MemOperand(sp)); | 1933 __ Sd(target, MemOperand(sp)); |
1936 __ TailCallRuntime(Runtime::kThrowApplyNonFunction); | 1934 __ TailCallRuntime(Runtime::kThrowApplyNonFunction); |
1937 } | 1935 } |
1938 } | 1936 } |
1939 | 1937 |
1940 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { | 1938 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { |
1941 // ----------- S t a t e ------------- | 1939 // ----------- S t a t e ------------- |
1942 // -- a0 : argc | 1940 // -- a0 : argc |
1943 // -- sp[0] : new.target (optional) (dummy value if argc <= 2) | 1941 // -- sp[0] : new.target (optional) (dummy value if argc <= 2) |
1944 // -- sp[4] : argumentsList (dummy value if argc <= 1) | 1942 // -- sp[4] : argumentsList (dummy value if argc <= 1) |
1945 // -- sp[8] : target (dummy value if argc == 0) | 1943 // -- sp[8] : target (dummy value if argc == 0) |
1946 // -- sp[12] : receiver | 1944 // -- sp[12] : receiver |
1947 // ----------------------------------- | 1945 // ----------------------------------- |
1948 Register argc = a0; | 1946 Register argc = a0; |
1949 Register arguments_list = a0; | 1947 Register arguments_list = a2; |
1950 Register target = a1; | 1948 Register target = a1; |
1951 Register new_target = a3; | 1949 Register new_target = a3; |
1952 Register undefined_value = a4; | 1950 Register undefined_value = a4; |
1953 Register scratch = a5; | 1951 Register scratch = a5; |
1954 | 1952 |
1955 // 1. Load target into a1 (if present), argumentsList into a0 (if present), | 1953 // 1. Load target into a1 (if present), argumentsList into a2 (if present), |
1956 // new.target into a3 (if present, otherwise use target), remove all | 1954 // new.target into a3 (if present, otherwise use target), remove all |
1957 // arguments from the stack (including the receiver), and push thisArgument | 1955 // arguments from the stack (including the receiver), and push thisArgument |
1958 // (if present) instead. | 1956 // (if present) instead. |
1959 { | 1957 { |
1960 // Claim (3 - argc) dummy arguments form the stack, to put the stack in a | 1958 // Claim (3 - argc) dummy arguments form the stack, to put the stack in a |
1961 // consistent state for a simple pop operation. | 1959 // consistent state for a simple pop operation. |
1962 | 1960 |
1963 __ Dsubu(sp, sp, Operand(3 * kPointerSize)); | 1961 __ Dsubu(sp, sp, Operand(3 * kPointerSize)); |
1964 __ Dlsa(sp, sp, argc, kPointerSizeLog2); | 1962 __ Dlsa(sp, sp, argc, kPointerSizeLog2); |
1965 __ mov(scratch, argc); | 1963 __ mov(scratch, argc); |
1966 __ Pop(target, arguments_list, new_target); | 1964 __ Pop(target, arguments_list, new_target); |
1967 __ Movz(arguments_list, undefined_value, scratch); // if argc == 0 | 1965 __ Movz(arguments_list, undefined_value, scratch); // if argc == 0 |
1968 __ Movz(new_target, undefined_value, scratch); // if argc == 0 | 1966 __ Movz(new_target, undefined_value, scratch); // if argc == 0 |
1969 __ Movz(target, undefined_value, scratch); // if argc == 0 | 1967 __ Movz(target, undefined_value, scratch); // if argc == 0 |
1970 __ Dsubu(scratch, scratch, Operand(1)); | 1968 __ Dsubu(scratch, scratch, Operand(1)); |
1971 __ Movz(arguments_list, undefined_value, scratch); // if argc == 1 | 1969 __ Movz(arguments_list, undefined_value, scratch); // if argc == 1 |
1972 __ Movz(new_target, target, scratch); // if argc == 1 | 1970 __ Movz(new_target, target, scratch); // if argc == 1 |
1973 __ Dsubu(scratch, scratch, Operand(1)); | 1971 __ Dsubu(scratch, scratch, Operand(1)); |
1974 __ Movz(new_target, target, scratch); // if argc == 2 | 1972 __ Movz(new_target, target, scratch); // if argc == 2 |
1975 | 1973 |
1976 __ Sd(undefined_value, MemOperand(sp, 0)); // Overwrite receiver | 1974 __ Sd(undefined_value, MemOperand(sp, 0)); // Overwrite receiver |
1977 } | 1975 } |
1978 | 1976 |
1979 // ----------- S t a t e ------------- | 1977 // ----------- S t a t e ------------- |
1980 // -- a0 : argumentsList | 1978 // -- a2 : argumentsList |
1981 // -- a1 : target | 1979 // -- a1 : target |
1982 // -- a3 : new.target | 1980 // -- a3 : new.target |
1983 // -- sp[0] : receiver (undefined) | 1981 // -- sp[0] : receiver (undefined) |
1984 // ----------------------------------- | 1982 // ----------------------------------- |
1985 | 1983 |
1986 // 2. Make sure the target is actually a constructor. | 1984 // 2. Make sure the target is actually a constructor. |
1987 Label target_not_constructor; | 1985 Label target_not_constructor; |
1988 __ JumpIfSmi(target, &target_not_constructor); | 1986 __ JumpIfSmi(target, &target_not_constructor); |
1989 __ Ld(a4, FieldMemOperand(target, HeapObject::kMapOffset)); | 1987 __ Ld(a4, FieldMemOperand(target, HeapObject::kMapOffset)); |
1990 __ Lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset)); | 1988 __ Lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset)); |
1991 __ And(a4, a4, Operand(1 << Map::kIsConstructor)); | 1989 __ And(a4, a4, Operand(1 << Map::kIsConstructor)); |
1992 __ Branch(&target_not_constructor, eq, a4, Operand(zero_reg)); | 1990 __ Branch(&target_not_constructor, eq, a4, Operand(zero_reg)); |
1993 | 1991 |
1994 // 3. Make sure the target is actually a constructor. | 1992 // 3. Make sure the target is actually a constructor. |
1995 Label new_target_not_constructor; | 1993 Label new_target_not_constructor; |
1996 __ JumpIfSmi(new_target, &new_target_not_constructor); | 1994 __ JumpIfSmi(new_target, &new_target_not_constructor); |
1997 __ Ld(a4, FieldMemOperand(new_target, HeapObject::kMapOffset)); | 1995 __ Ld(a4, FieldMemOperand(new_target, HeapObject::kMapOffset)); |
1998 __ Lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset)); | 1996 __ Lbu(a4, FieldMemOperand(a4, Map::kBitFieldOffset)); |
1999 __ And(a4, a4, Operand(1 << Map::kIsConstructor)); | 1997 __ And(a4, a4, Operand(1 << Map::kIsConstructor)); |
2000 __ Branch(&new_target_not_constructor, eq, a4, Operand(zero_reg)); | 1998 __ Branch(&new_target_not_constructor, eq, a4, Operand(zero_reg)); |
2001 | 1999 |
2002 // 4a. Construct the target with the given new.target and argumentsList. | 2000 // 4a. Construct the target with the given new.target and argumentsList. |
2003 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | 2001 __ Jump(masm->isolate()->builtins()->ConstructWithArrayLike(), |
| 2002 RelocInfo::CODE_TARGET); |
2004 | 2003 |
2005 // 4b. The target is not a constructor, throw an appropriate TypeError. | 2004 // 4b. The target is not a constructor, throw an appropriate TypeError. |
2006 __ bind(&target_not_constructor); | 2005 __ bind(&target_not_constructor); |
2007 { | 2006 { |
2008 __ Sd(target, MemOperand(sp)); | 2007 __ Sd(target, MemOperand(sp)); |
2009 __ TailCallRuntime(Runtime::kThrowNotConstructor); | 2008 __ TailCallRuntime(Runtime::kThrowNotConstructor); |
2010 } | 2009 } |
2011 | 2010 |
2012 // 4c. The new.target is not a constructor, throw an appropriate TypeError. | 2011 // 4c. The new.target is not a constructor, throw an appropriate TypeError. |
2013 __ bind(&new_target_not_constructor); | 2012 __ bind(&new_target_not_constructor); |
(...skipping 22 matching lines...) Expand all Loading... |
2036 kPointerSize))); | 2035 kPointerSize))); |
2037 __ mov(sp, fp); | 2036 __ mov(sp, fp); |
2038 __ MultiPop(fp.bit() | ra.bit()); | 2037 __ MultiPop(fp.bit() | ra.bit()); |
2039 __ SmiScale(a4, a1, kPointerSizeLog2); | 2038 __ SmiScale(a4, a1, kPointerSizeLog2); |
2040 __ Daddu(sp, sp, a4); | 2039 __ Daddu(sp, sp, a4); |
2041 // Adjust for the receiver. | 2040 // Adjust for the receiver. |
2042 __ Daddu(sp, sp, Operand(kPointerSize)); | 2041 __ Daddu(sp, sp, Operand(kPointerSize)); |
2043 } | 2042 } |
2044 | 2043 |
2045 // static | 2044 // static |
2046 void Builtins::Generate_Apply(MacroAssembler* masm) { | 2045 void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm, |
| 2046 Handle<Code> code) { |
2047 // ----------- S t a t e ------------- | 2047 // ----------- S t a t e ------------- |
2048 // -- a0 : argumentsList | 2048 // -- a1 : target |
2049 // -- a1 : target | 2049 // -- a0 : number of parameters on the stack (not including the receiver) |
2050 // -- a3 : new.target (checked to be constructor or undefined) | 2050 // -- a2 : arguments list (a FixedArray) |
2051 // -- sp[0] : thisArgument | 2051 // -- a4 : len (number of elements to push from args) |
| 2052 // -- a3 : new.target (for [[Construct]]) |
2052 // ----------------------------------- | 2053 // ----------------------------------- |
| 2054 __ AssertFixedArray(a2); |
2053 | 2055 |
2054 Register arguments_list = a0; | 2056 Register args = a2; |
2055 Register target = a1; | 2057 Register len = a4; |
2056 Register new_target = a3; | |
2057 | |
2058 Register args = a0; | |
2059 Register len = a2; | |
2060 | |
2061 // Create the list of arguments from the array-like argumentsList. | |
2062 { | |
2063 Label create_arguments, create_array, create_holey_array, create_runtime, | |
2064 done_create; | |
2065 __ JumpIfSmi(arguments_list, &create_runtime); | |
2066 | |
2067 // Load the map of argumentsList into a2. | |
2068 Register arguments_list_map = a2; | |
2069 __ Ld(arguments_list_map, | |
2070 FieldMemOperand(arguments_list, HeapObject::kMapOffset)); | |
2071 | |
2072 // Load native context into a4. | |
2073 Register native_context = a4; | |
2074 __ Ld(native_context, NativeContextMemOperand()); | |
2075 | |
2076 // Check if argumentsList is an (unmodified) arguments object. | |
2077 __ Ld(at, ContextMemOperand(native_context, | |
2078 Context::SLOPPY_ARGUMENTS_MAP_INDEX)); | |
2079 __ Branch(&create_arguments, eq, arguments_list_map, Operand(at)); | |
2080 __ Ld(at, ContextMemOperand(native_context, | |
2081 Context::STRICT_ARGUMENTS_MAP_INDEX)); | |
2082 __ Branch(&create_arguments, eq, arguments_list_map, Operand(at)); | |
2083 | |
2084 // Check if argumentsList is a fast JSArray. | |
2085 __ Lbu(v0, FieldMemOperand(a2, Map::kInstanceTypeOffset)); | |
2086 __ Branch(&create_array, eq, v0, Operand(JS_ARRAY_TYPE)); | |
2087 | |
2088 // Ask the runtime to create the list (actually a FixedArray). | |
2089 __ bind(&create_runtime); | |
2090 { | |
2091 FrameScope scope(masm, StackFrame::INTERNAL); | |
2092 __ Push(target, new_target, arguments_list); | |
2093 __ CallRuntime(Runtime::kCreateListFromArrayLike); | |
2094 __ mov(arguments_list, v0); | |
2095 __ Pop(target, new_target); | |
2096 __ Lw(len, UntagSmiFieldMemOperand(v0, FixedArray::kLengthOffset)); | |
2097 } | |
2098 __ Branch(&done_create); | |
2099 | |
2100 // Try to create the list from an arguments object. | |
2101 __ bind(&create_arguments); | |
2102 __ Lw(len, UntagSmiFieldMemOperand(arguments_list, | |
2103 JSArgumentsObject::kLengthOffset)); | |
2104 __ Ld(a4, FieldMemOperand(arguments_list, JSObject::kElementsOffset)); | |
2105 __ Lw(at, UntagSmiFieldMemOperand(a4, FixedArray::kLengthOffset)); | |
2106 __ Branch(&create_runtime, ne, len, Operand(at)); | |
2107 __ mov(args, a4); | |
2108 | |
2109 __ Branch(&done_create); | |
2110 | |
2111 // For holey JSArrays we need to check that the array prototype chain | |
2112 // protector is intact and our prototype is the Array.prototype actually. | |
2113 __ bind(&create_holey_array); | |
2114 __ Ld(a2, FieldMemOperand(a2, Map::kPrototypeOffset)); | |
2115 __ Ld(at, ContextMemOperand(native_context, | |
2116 Context::INITIAL_ARRAY_PROTOTYPE_INDEX)); | |
2117 __ Branch(&create_runtime, ne, a2, Operand(at)); | |
2118 __ LoadRoot(at, Heap::kArrayProtectorRootIndex); | |
2119 __ Lw(a2, FieldMemOperand(at, PropertyCell::kValueOffset)); | |
2120 __ Branch(&create_runtime, ne, a2, | |
2121 Operand(Smi::FromInt(Isolate::kProtectorValid))); | |
2122 __ Lw(a2, UntagSmiFieldMemOperand(a0, JSArray::kLengthOffset)); | |
2123 __ Ld(a0, FieldMemOperand(a0, JSArray::kElementsOffset)); | |
2124 __ Branch(&done_create); | |
2125 | |
2126 // Try to create the list from a JSArray object. | |
2127 __ bind(&create_array); | |
2128 __ Lbu(t1, FieldMemOperand(a2, Map::kBitField2Offset)); | |
2129 __ DecodeField<Map::ElementsKindBits>(t1); | |
2130 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | |
2131 STATIC_ASSERT(FAST_ELEMENTS == 2); | |
2132 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); | |
2133 __ Branch(&create_holey_array, eq, t1, Operand(FAST_HOLEY_SMI_ELEMENTS)); | |
2134 __ Branch(&create_holey_array, eq, t1, Operand(FAST_HOLEY_ELEMENTS)); | |
2135 __ Branch(&create_runtime, hi, t1, Operand(FAST_ELEMENTS)); | |
2136 __ Lw(a2, UntagSmiFieldMemOperand(arguments_list, JSArray::kLengthOffset)); | |
2137 __ Ld(a0, FieldMemOperand(arguments_list, JSArray::kElementsOffset)); | |
2138 | |
2139 __ bind(&done_create); | |
2140 } | |
2141 | 2058 |
2142 // Check for stack overflow. | 2059 // Check for stack overflow. |
2143 { | 2060 { |
2144 // Check the stack for overflow. We are not trying to catch interruptions | 2061 // Check the stack for overflow. We are not trying to catch interruptions |
2145 // (i.e. debug break and preemption) here, so check the "real stack limit". | 2062 // (i.e. debug break and preemption) here, so check the "real stack limit". |
2146 Label done; | 2063 Label done; |
2147 __ LoadRoot(a4, Heap::kRealStackLimitRootIndex); | 2064 __ LoadRoot(a5, Heap::kRealStackLimitRootIndex); |
2148 // Make ip the space we have left. The stack might already be overflowed | 2065 // Make ip the space we have left. The stack might already be overflowed |
2149 // here which will cause ip to become negative. | 2066 // here which will cause ip to become negative. |
2150 __ Dsubu(a4, sp, a4); | 2067 __ Dsubu(a5, sp, a5); |
2151 // Check if the arguments will overflow the stack. | 2068 // Check if the arguments will overflow the stack. |
2152 __ dsll(at, len, kPointerSizeLog2); | 2069 __ dsll(at, len, kPointerSizeLog2); |
2153 __ Branch(&done, gt, a4, Operand(at)); // Signed comparison. | 2070 __ Branch(&done, gt, a5, Operand(at)); // Signed comparison. |
2154 __ TailCallRuntime(Runtime::kThrowStackOverflow); | 2071 __ TailCallRuntime(Runtime::kThrowStackOverflow); |
2155 __ bind(&done); | 2072 __ bind(&done); |
2156 } | 2073 } |
2157 | 2074 |
2158 // ----------- S t a t e ------------- | |
2159 // -- a1 : target | |
2160 // -- a0 : args (a FixedArray built from argumentsList) | |
2161 // -- a2 : len (number of elements to push from args) | |
2162 // -- a3 : new.target (checked to be constructor or undefined) | |
2163 // -- sp[0] : thisArgument | |
2164 // ----------------------------------- | |
2165 | |
2166 // Push arguments onto the stack (thisArgument is already on the stack). | 2075 // Push arguments onto the stack (thisArgument is already on the stack). |
2167 { | 2076 { |
2168 Label done, push, loop; | 2077 Label done, push, loop; |
2169 Register src = a4; | 2078 Register src = a6; |
2170 Register scratch = len; | 2079 Register scratch = len; |
2171 | 2080 |
2172 __ daddiu(src, args, FixedArray::kHeaderSize - kHeapObjectTag); | 2081 __ daddiu(src, args, FixedArray::kHeaderSize - kHeapObjectTag); |
2173 __ Branch(&done, eq, len, Operand(zero_reg), i::USE_DELAY_SLOT); | 2082 __ Branch(&done, eq, len, Operand(zero_reg), i::USE_DELAY_SLOT); |
2174 __ mov(a0, len); // The 'len' argument for Call() or Construct(). | 2083 __ Daddu(a0, a0, len); // The 'len' argument for Call() or Construct(). |
2175 __ dsll(scratch, len, kPointerSizeLog2); | 2084 __ dsll(scratch, len, kPointerSizeLog2); |
2176 __ Dsubu(scratch, sp, Operand(scratch)); | 2085 __ Dsubu(scratch, sp, Operand(scratch)); |
2177 __ LoadRoot(t1, Heap::kTheHoleValueRootIndex); | 2086 __ LoadRoot(t1, Heap::kTheHoleValueRootIndex); |
2178 __ bind(&loop); | 2087 __ bind(&loop); |
2179 __ Ld(a5, MemOperand(src)); | 2088 __ Ld(a5, MemOperand(src)); |
2180 __ Branch(&push, ne, a5, Operand(t1)); | 2089 __ Branch(&push, ne, a5, Operand(t1)); |
2181 __ LoadRoot(a5, Heap::kUndefinedValueRootIndex); | 2090 __ LoadRoot(a5, Heap::kUndefinedValueRootIndex); |
2182 __ bind(&push); | 2091 __ bind(&push); |
2183 __ daddiu(src, src, kPointerSize); | 2092 __ daddiu(src, src, kPointerSize); |
2184 __ Push(a5); | 2093 __ Push(a5); |
2185 __ Branch(&loop, ne, scratch, Operand(sp)); | 2094 __ Branch(&loop, ne, scratch, Operand(sp)); |
2186 __ bind(&done); | 2095 __ bind(&done); |
2187 } | 2096 } |
2188 | 2097 |
2189 // ----------- S t a t e ------------- | 2098 // Tail-call to the actual Call or Construct builtin. |
2190 // -- a0 : argument count (len) | 2099 __ Jump(code, RelocInfo::CODE_TARGET); |
2191 // -- a1 : target | |
2192 // -- a3 : new.target (checked to be constructor or undefinded) | |
2193 // -- sp[0] : args[len-1] | |
2194 // -- sp[8] : args[len-2] | |
2195 // ... : ... | |
2196 // -- sp[8*(len-2)] : args[1] | |
2197 // -- sp[8*(len-1)] : args[0] | |
2198 // ---------------------------------- | |
2199 | |
2200 // Dispatch to Call or Construct depending on whether new.target is undefined. | |
2201 { | |
2202 Label construct; | |
2203 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | |
2204 __ Branch(&construct, ne, a3, Operand(at)); | |
2205 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | |
2206 __ bind(&construct); | |
2207 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | |
2208 } | |
2209 } | 2100 } |
2210 | 2101 |
2211 // static | 2102 // static |
2212 void Builtins::Generate_ForwardVarargs(MacroAssembler* masm, | 2103 void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm, |
2213 Handle<Code> code) { | 2104 Handle<Code> code) { |
2214 // ----------- S t a t e ------------- | 2105 // ----------- S t a t e ------------- |
2215 // -- a0 : the number of arguments (not including the receiver) | 2106 // -- a0 : the number of arguments (not including the receiver) |
2216 // -- a3 : the new.target (for [[Construct]] calls) | 2107 // -- a3 : the new.target (for [[Construct]] calls) |
2217 // -- a1 : the target to call (can be any Object) | 2108 // -- a1 : the target to call (can be any Object) |
2218 // -- a2 : start index (to support rest parameters) | 2109 // -- a2 : start index (to support rest parameters) |
2219 // ----------------------------------- | 2110 // ----------------------------------- |
2220 | 2111 |
2221 // Check if we have an arguments adaptor frame below the function frame. | 2112 // Check if we have an arguments adaptor frame below the function frame. |
2222 Label arguments_adaptor, arguments_done; | 2113 Label arguments_adaptor, arguments_done; |
2223 __ Ld(a6, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 2114 __ Ld(a6, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
(...skipping 927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3151 __ Daddu(at, v0, Operand(Code::kHeaderSize - kHeapObjectTag)); | 3042 __ Daddu(at, v0, Operand(Code::kHeaderSize - kHeapObjectTag)); |
3152 __ Jump(at); | 3043 __ Jump(at); |
3153 } | 3044 } |
3154 | 3045 |
3155 #undef __ | 3046 #undef __ |
3156 | 3047 |
3157 } // namespace internal | 3048 } // namespace internal |
3158 } // namespace v8 | 3049 } // namespace v8 |
3159 | 3050 |
3160 #endif // V8_TARGET_ARCH_MIPS64 | 3051 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |