| 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 |