OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
6 | 6 |
7 #include "src/arm64/frames-arm64.h" | 7 #include "src/arm64/frames-arm64.h" |
8 #include "src/arm64/macro-assembler-arm64-inl.h" | 8 #include "src/arm64/macro-assembler-arm64-inl.h" |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/counters.h" | 10 #include "src/counters.h" |
(...skipping 1793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1804 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { | 1804 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { |
1805 // ----------- S t a t e ------------- | 1805 // ----------- S t a t e ------------- |
1806 // -- x0 : argc | 1806 // -- x0 : argc |
1807 // -- jssp[0] : argArray (if argc == 2) | 1807 // -- jssp[0] : argArray (if argc == 2) |
1808 // -- jssp[8] : thisArg (if argc >= 1) | 1808 // -- jssp[8] : thisArg (if argc >= 1) |
1809 // -- jssp[16] : receiver | 1809 // -- jssp[16] : receiver |
1810 // ----------------------------------- | 1810 // ----------------------------------- |
1811 ASM_LOCATION("Builtins::Generate_FunctionPrototypeApply"); | 1811 ASM_LOCATION("Builtins::Generate_FunctionPrototypeApply"); |
1812 | 1812 |
1813 Register argc = x0; | 1813 Register argc = x0; |
1814 Register arg_array = x0; | 1814 Register arg_array = x2; |
1815 Register receiver = x1; | 1815 Register receiver = x1; |
1816 Register this_arg = x2; | 1816 Register this_arg = x0; |
1817 Register undefined_value = x3; | 1817 Register undefined_value = x3; |
1818 Register null_value = x4; | 1818 Register null_value = x4; |
1819 | 1819 |
1820 __ LoadRoot(undefined_value, Heap::kUndefinedValueRootIndex); | 1820 __ LoadRoot(undefined_value, Heap::kUndefinedValueRootIndex); |
1821 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 1821 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
1822 | 1822 |
1823 // 1. Load receiver into x1, argArray into x0 (if present), remove all | 1823 // 1. Load receiver into x1, argArray into x2 (if present), remove all |
1824 // arguments from the stack (including the receiver), and push thisArg (if | 1824 // arguments from the stack (including the receiver), and push thisArg (if |
1825 // present) instead. | 1825 // present) instead. |
1826 { | 1826 { |
1827 // Claim (2 - argc) dummy arguments from the stack, to put the stack in a | 1827 // Claim (2 - argc) dummy arguments from the stack, to put the stack in a |
1828 // consistent state for a simple pop operation. | 1828 // consistent state for a simple pop operation. |
1829 __ Claim(2); | 1829 __ Claim(2); |
1830 __ Drop(argc); | 1830 __ Drop(argc); |
1831 | 1831 |
1832 // ----------- S t a t e ------------- | 1832 // ----------- S t a t e ------------- |
1833 // -- x0 : argc | 1833 // -- x0 : argc |
1834 // -- jssp[0] : argArray (dummy value if argc <= 1) | 1834 // -- jssp[0] : argArray (dummy value if argc <= 1) |
1835 // -- jssp[8] : thisArg (dummy value if argc == 0) | 1835 // -- jssp[8] : thisArg (dummy value if argc == 0) |
1836 // -- jssp[16] : receiver | 1836 // -- jssp[16] : receiver |
1837 // ----------------------------------- | 1837 // ----------------------------------- |
1838 __ Cmp(argc, 1); | 1838 __ Cmp(argc, 1); |
1839 __ Pop(arg_array, this_arg); // Overwrites argc. | 1839 __ Pop(arg_array, this_arg); // Overwrites argc. |
1840 __ CmovX(this_arg, undefined_value, lo); // undefined if argc == 0. | 1840 __ CmovX(this_arg, undefined_value, lo); // undefined if argc == 0. |
1841 __ CmovX(arg_array, undefined_value, ls); // undefined if argc <= 1. | 1841 __ CmovX(arg_array, undefined_value, ls); // undefined if argc <= 1. |
1842 | 1842 |
1843 __ Peek(receiver, 0); | 1843 __ Peek(receiver, 0); |
1844 __ Poke(this_arg, 0); | 1844 __ Poke(this_arg, 0); |
1845 } | 1845 } |
1846 | 1846 |
1847 // ----------- S t a t e ------------- | 1847 // ----------- S t a t e ------------- |
1848 // -- x0 : argArray | 1848 // -- x2 : argArray |
1849 // -- x1 : receiver | 1849 // -- x1 : receiver |
1850 // -- x3 : undefined root value | |
1851 // -- jssp[0] : thisArg | 1850 // -- jssp[0] : thisArg |
1852 // ----------------------------------- | 1851 // ----------------------------------- |
1853 | 1852 |
1854 // 2. Make sure the receiver is actually callable. | 1853 // 2. Make sure the receiver is actually callable. |
1855 Label receiver_not_callable; | 1854 Label receiver_not_callable; |
1856 __ JumpIfSmi(receiver, &receiver_not_callable); | 1855 __ JumpIfSmi(receiver, &receiver_not_callable); |
1857 __ Ldr(x10, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1856 __ Ldr(x10, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
1858 __ Ldrb(w10, FieldMemOperand(x10, Map::kBitFieldOffset)); | 1857 __ Ldrb(w10, FieldMemOperand(x10, Map::kBitFieldOffset)); |
1859 __ TestAndBranchIfAllClear(x10, 1 << Map::kIsCallable, | 1858 __ TestAndBranchIfAllClear(x10, 1 << Map::kIsCallable, |
1860 &receiver_not_callable); | 1859 &receiver_not_callable); |
1861 | 1860 |
1862 // 3. Tail call with no arguments if argArray is null or undefined. | 1861 // 3. Tail call with no arguments if argArray is null or undefined. |
1863 Label no_arguments; | 1862 Label no_arguments; |
1864 __ Cmp(arg_array, null_value); | 1863 __ Cmp(arg_array, null_value); |
1865 __ Ccmp(arg_array, undefined_value, ZFlag, ne); | 1864 __ Ccmp(arg_array, undefined_value, ZFlag, ne); |
1866 __ B(eq, &no_arguments); | 1865 __ B(eq, &no_arguments); |
1867 | 1866 |
1868 // 4a. Apply the receiver to the given argArray (passing undefined for | 1867 // 4a. Apply the receiver to the given argArray. |
1869 // new.target in x3). | 1868 __ Jump(masm->isolate()->builtins()->CallWithArrayLike(), |
1870 DCHECK(undefined_value.Is(x3)); | 1869 RelocInfo::CODE_TARGET); |
1871 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | |
1872 | 1870 |
1873 // 4b. The argArray is either null or undefined, so we tail call without any | 1871 // 4b. The argArray is either null or undefined, so we tail call without any |
1874 // arguments to the receiver. | 1872 // arguments to the receiver. |
1875 __ Bind(&no_arguments); | 1873 __ Bind(&no_arguments); |
1876 { | 1874 { |
1877 __ Mov(x0, 0); | 1875 __ Mov(x0, 0); |
1878 DCHECK(receiver.Is(x1)); | 1876 DCHECK(receiver.Is(x1)); |
1879 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1877 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
1880 } | 1878 } |
1881 | 1879 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1937 // ----------- S t a t e ------------- | 1935 // ----------- S t a t e ------------- |
1938 // -- x0 : argc | 1936 // -- x0 : argc |
1939 // -- jssp[0] : argumentsList (if argc == 3) | 1937 // -- jssp[0] : argumentsList (if argc == 3) |
1940 // -- jssp[8] : thisArgument (if argc >= 2) | 1938 // -- jssp[8] : thisArgument (if argc >= 2) |
1941 // -- jssp[16] : target (if argc >= 1) | 1939 // -- jssp[16] : target (if argc >= 1) |
1942 // -- jssp[24] : receiver | 1940 // -- jssp[24] : receiver |
1943 // ----------------------------------- | 1941 // ----------------------------------- |
1944 ASM_LOCATION("Builtins::Generate_ReflectApply"); | 1942 ASM_LOCATION("Builtins::Generate_ReflectApply"); |
1945 | 1943 |
1946 Register argc = x0; | 1944 Register argc = x0; |
1947 Register arguments_list = x0; | 1945 Register arguments_list = x2; |
1948 Register target = x1; | 1946 Register target = x1; |
1949 Register this_argument = x2; | 1947 Register this_argument = x4; |
1950 Register undefined_value = x3; | 1948 Register undefined_value = x3; |
1951 | 1949 |
1952 __ LoadRoot(undefined_value, Heap::kUndefinedValueRootIndex); | 1950 __ LoadRoot(undefined_value, Heap::kUndefinedValueRootIndex); |
1953 | 1951 |
1954 // 1. Load target into x1 (if present), argumentsList into x0 (if present), | 1952 // 1. Load target into x1 (if present), argumentsList into x2 (if present), |
1955 // remove all arguments from the stack (including the receiver), and push | 1953 // remove all arguments from the stack (including the receiver), and push |
1956 // thisArgument (if present) instead. | 1954 // thisArgument (if present) instead. |
1957 { | 1955 { |
1958 // Claim (3 - argc) dummy arguments from the stack, to put the stack in a | 1956 // Claim (3 - argc) dummy arguments from the stack, to put the stack in a |
1959 // consistent state for a simple pop operation. | 1957 // consistent state for a simple pop operation. |
1960 __ Claim(3); | 1958 __ Claim(3); |
1961 __ Drop(argc); | 1959 __ Drop(argc); |
1962 | 1960 |
1963 // ----------- S t a t e ------------- | 1961 // ----------- S t a t e ------------- |
1964 // -- x0 : argc | 1962 // -- x0 : argc |
1965 // -- jssp[0] : argumentsList (dummy value if argc <= 2) | 1963 // -- jssp[0] : argumentsList (dummy value if argc <= 2) |
1966 // -- jssp[8] : thisArgument (dummy value if argc <= 1) | 1964 // -- jssp[8] : thisArgument (dummy value if argc <= 1) |
1967 // -- jssp[16] : target (dummy value if argc == 0) | 1965 // -- jssp[16] : target (dummy value if argc == 0) |
1968 // -- jssp[24] : receiver | 1966 // -- jssp[24] : receiver |
1969 // ----------------------------------- | 1967 // ----------------------------------- |
1970 __ Adds(x10, argc, 0); // Preserve argc, and set the Z flag if it is zero. | 1968 __ Adds(x10, argc, 0); // Preserve argc, and set the Z flag if it is zero. |
1971 __ Pop(arguments_list, this_argument, target); // Overwrites argc. | 1969 __ Pop(arguments_list, this_argument, target); // Overwrites argc. |
1972 __ CmovX(target, undefined_value, eq); // undefined if argc == 0. | 1970 __ CmovX(target, undefined_value, eq); // undefined if argc == 0. |
1973 __ Cmp(x10, 2); | 1971 __ Cmp(x10, 2); |
1974 __ CmovX(this_argument, undefined_value, lo); // undefined if argc <= 1. | 1972 __ CmovX(this_argument, undefined_value, lo); // undefined if argc <= 1. |
1975 __ CmovX(arguments_list, undefined_value, ls); // undefined if argc <= 2. | 1973 __ CmovX(arguments_list, undefined_value, ls); // undefined if argc <= 2. |
1976 | 1974 |
1977 __ Poke(this_argument, 0); // Overwrite receiver. | 1975 __ Poke(this_argument, 0); // Overwrite receiver. |
1978 } | 1976 } |
1979 | 1977 |
1980 // ----------- S t a t e ------------- | 1978 // ----------- S t a t e ------------- |
1981 // -- x0 : argumentsList | 1979 // -- x2 : argumentsList |
1982 // -- x1 : target | 1980 // -- x1 : target |
1983 // -- jssp[0] : thisArgument | 1981 // -- jssp[0] : thisArgument |
1984 // ----------------------------------- | 1982 // ----------------------------------- |
1985 | 1983 |
1986 // 2. Make sure the target is actually callable. | 1984 // 2. Make sure the target is actually callable. |
1987 Label target_not_callable; | 1985 Label target_not_callable; |
1988 __ JumpIfSmi(target, &target_not_callable); | 1986 __ JumpIfSmi(target, &target_not_callable); |
1989 __ Ldr(x10, FieldMemOperand(target, HeapObject::kMapOffset)); | 1987 __ Ldr(x10, FieldMemOperand(target, HeapObject::kMapOffset)); |
1990 __ Ldr(x10, FieldMemOperand(x10, Map::kBitFieldOffset)); | 1988 __ Ldr(x10, FieldMemOperand(x10, Map::kBitFieldOffset)); |
1991 __ TestAndBranchIfAllClear(x10, 1 << Map::kIsCallable, &target_not_callable); | 1989 __ TestAndBranchIfAllClear(x10, 1 << Map::kIsCallable, &target_not_callable); |
1992 | 1990 |
1993 // 3a. Apply the target to the given argumentsList (passing undefined for | 1991 // 3a. Apply the target to the given argumentsList. |
1994 // new.target in x3). | 1992 __ Jump(masm->isolate()->builtins()->CallWithArrayLike(), |
1995 DCHECK(undefined_value.Is(x3)); | 1993 RelocInfo::CODE_TARGET); |
1996 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | |
1997 | 1994 |
1998 // 3b. The target is not callable, throw an appropriate TypeError. | 1995 // 3b. The target is not callable, throw an appropriate TypeError. |
1999 __ Bind(&target_not_callable); | 1996 __ Bind(&target_not_callable); |
2000 { | 1997 { |
2001 __ Poke(target, 0); | 1998 __ Poke(target, 0); |
2002 __ TailCallRuntime(Runtime::kThrowApplyNonFunction); | 1999 __ TailCallRuntime(Runtime::kThrowApplyNonFunction); |
2003 } | 2000 } |
2004 } | 2001 } |
2005 | 2002 |
2006 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { | 2003 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { |
2007 // ----------- S t a t e ------------- | 2004 // ----------- S t a t e ------------- |
2008 // -- x0 : argc | 2005 // -- x0 : argc |
2009 // -- jssp[0] : new.target (optional) | 2006 // -- jssp[0] : new.target (optional) |
2010 // -- jssp[8] : argumentsList | 2007 // -- jssp[8] : argumentsList |
2011 // -- jssp[16] : target | 2008 // -- jssp[16] : target |
2012 // -- jssp[24] : receiver | 2009 // -- jssp[24] : receiver |
2013 // ----------------------------------- | 2010 // ----------------------------------- |
2014 ASM_LOCATION("Builtins::Generate_ReflectConstruct"); | 2011 ASM_LOCATION("Builtins::Generate_ReflectConstruct"); |
2015 | 2012 |
2016 Register argc = x0; | 2013 Register argc = x0; |
2017 Register arguments_list = x0; | 2014 Register arguments_list = x2; |
2018 Register target = x1; | 2015 Register target = x1; |
2019 Register new_target = x3; | 2016 Register new_target = x3; |
2020 Register undefined_value = x4; | 2017 Register undefined_value = x4; |
2021 | 2018 |
2022 __ LoadRoot(undefined_value, Heap::kUndefinedValueRootIndex); | 2019 __ LoadRoot(undefined_value, Heap::kUndefinedValueRootIndex); |
2023 | 2020 |
2024 // 1. Load target into x1 (if present), argumentsList into x0 (if present), | 2021 // 1. Load target into x1 (if present), argumentsList into x2 (if present), |
2025 // new.target into x3 (if present, otherwise use target), remove all | 2022 // new.target into x3 (if present, otherwise use target), remove all |
2026 // arguments from the stack (including the receiver), and push thisArgument | 2023 // arguments from the stack (including the receiver), and push thisArgument |
2027 // (if present) instead. | 2024 // (if present) instead. |
2028 { | 2025 { |
2029 // Claim (3 - argc) dummy arguments from the stack, to put the stack in a | 2026 // Claim (3 - argc) dummy arguments from the stack, to put the stack in a |
2030 // consistent state for a simple pop operation. | 2027 // consistent state for a simple pop operation. |
2031 __ Claim(3); | 2028 __ Claim(3); |
2032 __ Drop(argc); | 2029 __ Drop(argc); |
2033 | 2030 |
2034 // ----------- S t a t e ------------- | 2031 // ----------- S t a t e ------------- |
2035 // -- x0 : argc | 2032 // -- x0 : argc |
2036 // -- jssp[0] : new.target (dummy value if argc <= 2) | 2033 // -- jssp[0] : new.target (dummy value if argc <= 2) |
2037 // -- jssp[8] : argumentsList (dummy value if argc <= 1) | 2034 // -- jssp[8] : argumentsList (dummy value if argc <= 1) |
2038 // -- jssp[16] : target (dummy value if argc == 0) | 2035 // -- jssp[16] : target (dummy value if argc == 0) |
2039 // -- jssp[24] : receiver | 2036 // -- jssp[24] : receiver |
2040 // ----------------------------------- | 2037 // ----------------------------------- |
2041 __ Adds(x10, argc, 0); // Preserve argc, and set the Z flag if it is zero. | 2038 __ Adds(x10, argc, 0); // Preserve argc, and set the Z flag if it is zero. |
2042 __ Pop(new_target, arguments_list, target); // Overwrites argc. | 2039 __ Pop(new_target, arguments_list, target); // Overwrites argc. |
2043 __ CmovX(target, undefined_value, eq); // undefined if argc == 0. | 2040 __ CmovX(target, undefined_value, eq); // undefined if argc == 0. |
2044 __ Cmp(x10, 2); | 2041 __ Cmp(x10, 2); |
2045 __ CmovX(arguments_list, undefined_value, lo); // undefined if argc <= 1. | 2042 __ CmovX(arguments_list, undefined_value, lo); // undefined if argc <= 1. |
2046 __ CmovX(new_target, target, ls); // target if argc <= 2. | 2043 __ CmovX(new_target, target, ls); // target if argc <= 2. |
2047 | 2044 |
2048 __ Poke(undefined_value, 0); // Overwrite receiver. | 2045 __ Poke(undefined_value, 0); // Overwrite receiver. |
2049 } | 2046 } |
2050 | 2047 |
2051 // ----------- S t a t e ------------- | 2048 // ----------- S t a t e ------------- |
2052 // -- x0 : argumentsList | 2049 // -- x2 : argumentsList |
2053 // -- x1 : target | 2050 // -- x1 : target |
2054 // -- x3 : new.target | 2051 // -- x3 : new.target |
2055 // -- jssp[0] : receiver (undefined) | 2052 // -- jssp[0] : receiver (undefined) |
2056 // ----------------------------------- | 2053 // ----------------------------------- |
2057 | 2054 |
2058 // 2. Make sure the target is actually a constructor. | 2055 // 2. Make sure the target is actually a constructor. |
2059 Label target_not_constructor; | 2056 Label target_not_constructor; |
2060 __ JumpIfSmi(target, &target_not_constructor); | 2057 __ JumpIfSmi(target, &target_not_constructor); |
2061 __ Ldr(x10, FieldMemOperand(target, HeapObject::kMapOffset)); | 2058 __ Ldr(x10, FieldMemOperand(target, HeapObject::kMapOffset)); |
2062 __ Ldrb(x10, FieldMemOperand(x10, Map::kBitFieldOffset)); | 2059 __ Ldrb(x10, FieldMemOperand(x10, Map::kBitFieldOffset)); |
2063 __ TestAndBranchIfAllClear(x10, 1 << Map::kIsConstructor, | 2060 __ TestAndBranchIfAllClear(x10, 1 << Map::kIsConstructor, |
2064 &target_not_constructor); | 2061 &target_not_constructor); |
2065 | 2062 |
2066 // 3. Make sure the new.target is actually a constructor. | 2063 // 3. Make sure the new.target is actually a constructor. |
2067 Label new_target_not_constructor; | 2064 Label new_target_not_constructor; |
2068 __ JumpIfSmi(new_target, &new_target_not_constructor); | 2065 __ JumpIfSmi(new_target, &new_target_not_constructor); |
2069 __ Ldr(x10, FieldMemOperand(new_target, HeapObject::kMapOffset)); | 2066 __ Ldr(x10, FieldMemOperand(new_target, HeapObject::kMapOffset)); |
2070 __ Ldrb(x10, FieldMemOperand(x10, Map::kBitFieldOffset)); | 2067 __ Ldrb(x10, FieldMemOperand(x10, Map::kBitFieldOffset)); |
2071 __ TestAndBranchIfAllClear(x10, 1 << Map::kIsConstructor, | 2068 __ TestAndBranchIfAllClear(x10, 1 << Map::kIsConstructor, |
2072 &new_target_not_constructor); | 2069 &new_target_not_constructor); |
2073 | 2070 |
2074 // 4a. Construct the target with the given new.target and argumentsList. | 2071 // 4a. Construct the target with the given new.target and argumentsList. |
2075 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | 2072 __ Jump(masm->isolate()->builtins()->ConstructWithArrayLike(), |
| 2073 RelocInfo::CODE_TARGET); |
2076 | 2074 |
2077 // 4b. The target is not a constructor, throw an appropriate TypeError. | 2075 // 4b. The target is not a constructor, throw an appropriate TypeError. |
2078 __ Bind(&target_not_constructor); | 2076 __ Bind(&target_not_constructor); |
2079 { | 2077 { |
2080 __ Poke(target, 0); | 2078 __ Poke(target, 0); |
2081 __ TailCallRuntime(Runtime::kThrowNotConstructor); | 2079 __ TailCallRuntime(Runtime::kThrowNotConstructor); |
2082 } | 2080 } |
2083 | 2081 |
2084 // 4c. The new.target is not a constructor, throw an appropriate TypeError. | 2082 // 4c. The new.target is not a constructor, throw an appropriate TypeError. |
2085 __ Bind(&new_target_not_constructor); | 2083 __ Bind(&new_target_not_constructor); |
(...skipping 20 matching lines...) Expand all Loading... |
2106 // then drop the parameters and the receiver. | 2104 // then drop the parameters and the receiver. |
2107 __ Ldr(x10, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + | 2105 __ Ldr(x10, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + |
2108 kPointerSize))); | 2106 kPointerSize))); |
2109 __ Mov(jssp, fp); | 2107 __ Mov(jssp, fp); |
2110 __ Pop(fp, lr); | 2108 __ Pop(fp, lr); |
2111 __ DropBySMI(x10, kXRegSize); | 2109 __ DropBySMI(x10, kXRegSize); |
2112 __ Drop(1); | 2110 __ Drop(1); |
2113 } | 2111 } |
2114 | 2112 |
2115 // static | 2113 // static |
2116 void Builtins::Generate_Apply(MacroAssembler* masm) { | 2114 void Builtins::Generate_CallOrConstructVarargs(MacroAssembler* masm, |
| 2115 Handle<Code> code) { |
2117 // ----------- S t a t e ------------- | 2116 // ----------- S t a t e ------------- |
2118 // -- x0 : argumentsList | 2117 // -- x1 : target |
2119 // -- x1 : target | 2118 // -- x0 : number of parameters on the stack (not including the receiver) |
2120 // -- x3 : new.target (checked to be constructor or undefined) | 2119 // -- x2 : arguments list (a FixedArray) |
2121 // -- jssp[0] : thisArgument | 2120 // -- x4 : len (number of elements to push from args) |
| 2121 // -- x3 : new.target (for [[Construct]]) |
2122 // ----------------------------------- | 2122 // ----------------------------------- |
| 2123 __ AssertFixedArray(x2); |
2123 | 2124 |
2124 Register arguments_list = x0; | 2125 Register arguments_list = x2; |
2125 Register target = x1; | 2126 Register argc = x0; |
2126 Register new_target = x3; | 2127 Register len = x4; |
2127 | |
2128 Register args = x0; | |
2129 Register len = x2; | |
2130 | |
2131 // Create the list of arguments from the array-like argumentsList. | |
2132 { | |
2133 Label create_arguments, create_array, create_holey_array, create_runtime, | |
2134 done_create; | |
2135 __ JumpIfSmi(arguments_list, &create_runtime); | |
2136 | |
2137 // Load native context. | |
2138 Register native_context = x4; | |
2139 __ Ldr(native_context, NativeContextMemOperand()); | |
2140 | |
2141 // Load the map of argumentsList. | |
2142 Register arguments_list_map = x2; | |
2143 __ Ldr(arguments_list_map, | |
2144 FieldMemOperand(arguments_list, HeapObject::kMapOffset)); | |
2145 | |
2146 // Check if argumentsList is an (unmodified) arguments object. | |
2147 __ Ldr(x10, ContextMemOperand(native_context, | |
2148 Context::SLOPPY_ARGUMENTS_MAP_INDEX)); | |
2149 __ Ldr(x11, ContextMemOperand(native_context, | |
2150 Context::STRICT_ARGUMENTS_MAP_INDEX)); | |
2151 __ Cmp(arguments_list_map, x10); | |
2152 __ Ccmp(arguments_list_map, x11, ZFlag, ne); | |
2153 __ B(eq, &create_arguments); | |
2154 | |
2155 // Check if argumentsList is a fast JSArray. | |
2156 __ CompareInstanceType(arguments_list_map, x10, JS_ARRAY_TYPE); | |
2157 __ B(eq, &create_array); | |
2158 | |
2159 // Ask the runtime to create the list (actually a FixedArray). | |
2160 __ Bind(&create_runtime); | |
2161 { | |
2162 FrameScope scope(masm, StackFrame::INTERNAL); | |
2163 __ Push(target, new_target, arguments_list); | |
2164 __ CallRuntime(Runtime::kCreateListFromArrayLike); | |
2165 __ Pop(new_target, target); | |
2166 __ Ldrsw(len, UntagSmiFieldMemOperand(arguments_list, | |
2167 FixedArray::kLengthOffset)); | |
2168 } | |
2169 __ B(&done_create); | |
2170 | |
2171 // Try to create the list from an arguments object. | |
2172 __ Bind(&create_arguments); | |
2173 __ Ldrsw(len, UntagSmiFieldMemOperand(arguments_list, | |
2174 JSArgumentsObject::kLengthOffset)); | |
2175 __ Ldr(x10, FieldMemOperand(arguments_list, JSObject::kElementsOffset)); | |
2176 __ Ldrsw(x11, UntagSmiFieldMemOperand(x10, FixedArray::kLengthOffset)); | |
2177 __ CompareAndBranch(len, x11, ne, &create_runtime); | |
2178 __ Mov(args, x10); | |
2179 __ B(&done_create); | |
2180 | |
2181 // For holey JSArrays we need to check that the array prototype chain | |
2182 // protector is intact and our prototype is the Array.prototype actually. | |
2183 __ Bind(&create_holey_array); | |
2184 // -- x2 : arguments_list_map | |
2185 // -- x4 : native_context | |
2186 Register arguments_list_prototype = x2; | |
2187 __ Ldr(arguments_list_prototype, | |
2188 FieldMemOperand(arguments_list_map, Map::kPrototypeOffset)); | |
2189 __ Ldr(x10, ContextMemOperand(native_context, | |
2190 Context::INITIAL_ARRAY_PROTOTYPE_INDEX)); | |
2191 __ Cmp(arguments_list_prototype, x10); | |
2192 __ B(ne, &create_runtime); | |
2193 __ LoadRoot(x10, Heap::kArrayProtectorRootIndex); | |
2194 __ Ldrsw(x11, UntagSmiFieldMemOperand(x10, PropertyCell::kValueOffset)); | |
2195 __ Cmp(x11, Isolate::kProtectorValid); | |
2196 __ B(ne, &create_runtime); | |
2197 __ Ldrsw(len, | |
2198 UntagSmiFieldMemOperand(arguments_list, JSArray::kLengthOffset)); | |
2199 __ Ldr(args, FieldMemOperand(arguments_list, JSArray::kElementsOffset)); | |
2200 __ B(&done_create); | |
2201 | |
2202 // Try to create the list from a JSArray object. | |
2203 __ Bind(&create_array); | |
2204 __ Ldr(x10, FieldMemOperand(arguments_list_map, Map::kBitField2Offset)); | |
2205 __ DecodeField<Map::ElementsKindBits>(x10); | |
2206 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | |
2207 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | |
2208 STATIC_ASSERT(FAST_ELEMENTS == 2); | |
2209 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); | |
2210 // Check if it is a holey array, the order of the cmp is important as | |
2211 // anything higher than FAST_HOLEY_ELEMENTS will fall back to runtime. | |
2212 __ Cmp(x10, FAST_HOLEY_ELEMENTS); | |
2213 __ B(hi, &create_runtime); | |
2214 // Only FAST_XXX after this point, FAST_HOLEY_XXX are odd values. | |
2215 __ Tbnz(x10, 0, &create_holey_array); | |
2216 // FAST_SMI_ELEMENTS or FAST_ELEMENTS after this point. | |
2217 __ Ldrsw(len, | |
2218 UntagSmiFieldMemOperand(arguments_list, JSArray::kLengthOffset)); | |
2219 __ Ldr(args, FieldMemOperand(arguments_list, JSArray::kElementsOffset)); | |
2220 | |
2221 __ Bind(&done_create); | |
2222 } | |
2223 | 2128 |
2224 // Check for stack overflow. | 2129 // Check for stack overflow. |
2225 { | 2130 { |
2226 // Check the stack for overflow. We are not trying to catch interruptions | 2131 // Check the stack for overflow. We are not trying to catch interruptions |
2227 // (i.e. debug break and preemption) here, so check the "real stack limit". | 2132 // (i.e. debug break and preemption) here, so check the "real stack limit". |
2228 Label done; | 2133 Label done; |
2229 __ LoadRoot(x10, Heap::kRealStackLimitRootIndex); | 2134 __ LoadRoot(x10, Heap::kRealStackLimitRootIndex); |
2230 // Make x10 the space we have left. The stack might already be overflowed | 2135 // Make x10 the space we have left. The stack might already be overflowed |
2231 // here which will cause x10 to become negative. | 2136 // here which will cause x10 to become negative. |
2232 __ Sub(x10, masm->StackPointer(), x10); | 2137 __ Sub(x10, masm->StackPointer(), x10); |
2233 // Check if the arguments will overflow the stack. | 2138 // Check if the arguments will overflow the stack. |
2234 __ Cmp(x10, Operand(len, LSL, kPointerSizeLog2)); | 2139 __ Cmp(x10, Operand(len, LSL, kPointerSizeLog2)); |
2235 __ B(gt, &done); // Signed comparison. | 2140 __ B(gt, &done); // Signed comparison. |
2236 __ TailCallRuntime(Runtime::kThrowStackOverflow); | 2141 __ TailCallRuntime(Runtime::kThrowStackOverflow); |
2237 __ Bind(&done); | 2142 __ Bind(&done); |
2238 } | 2143 } |
2239 | 2144 |
2240 // ----------- S t a t e ------------- | |
2241 // -- x0 : args (a FixedArray built from argumentsList) | |
2242 // -- x1 : target | |
2243 // -- x2 : len (number of elements to push from args) | |
2244 // -- x3 : new.target (checked to be constructor or undefined) | |
2245 // -- jssp[0] : thisArgument | |
2246 // ----------------------------------- | |
2247 | |
2248 // Push arguments onto the stack (thisArgument is already on the stack). | 2145 // Push arguments onto the stack (thisArgument is already on the stack). |
2249 { | 2146 { |
2250 Label done, push, loop; | 2147 Label done, push, loop; |
2251 Register src = x4; | 2148 Register src = x5; |
2252 | 2149 |
2253 __ Add(src, args, FixedArray::kHeaderSize - kHeapObjectTag); | 2150 __ Add(src, arguments_list, FixedArray::kHeaderSize - kHeapObjectTag); |
2254 __ Mov(x0, len); // The 'len' argument for Call() or Construct(). | 2151 __ Add(argc, argc, len); // The 'len' argument for Call() or Construct(). |
2255 __ Cbz(len, &done); | 2152 __ Cbz(len, &done); |
2256 Register the_hole_value = x11; | 2153 Register the_hole_value = x11; |
2257 Register undefined_value = x12; | 2154 Register undefined_value = x12; |
2258 // We do not use the CompareRoot macro as it would do a LoadRoot behind the | 2155 // We do not use the CompareRoot macro as it would do a LoadRoot behind the |
2259 // scenes and we want to avoid that in a loop. | 2156 // scenes and we want to avoid that in a loop. |
2260 __ LoadRoot(the_hole_value, Heap::kTheHoleValueRootIndex); | 2157 __ LoadRoot(the_hole_value, Heap::kTheHoleValueRootIndex); |
2261 __ LoadRoot(undefined_value, Heap::kUndefinedValueRootIndex); | 2158 __ LoadRoot(undefined_value, Heap::kUndefinedValueRootIndex); |
2262 __ Claim(len); | 2159 __ Claim(len); |
2263 __ Bind(&loop); | 2160 __ Bind(&loop); |
2264 __ Sub(len, len, 1); | 2161 __ Sub(len, len, 1); |
2265 __ Ldr(x10, MemOperand(src, kPointerSize, PostIndex)); | 2162 __ Ldr(x10, MemOperand(src, kPointerSize, PostIndex)); |
2266 __ Cmp(x10, the_hole_value); | 2163 __ Cmp(x10, the_hole_value); |
2267 __ Csel(x10, x10, undefined_value, ne); | 2164 __ Csel(x10, x10, undefined_value, ne); |
2268 __ Poke(x10, Operand(len, LSL, kPointerSizeLog2)); | 2165 __ Poke(x10, Operand(len, LSL, kPointerSizeLog2)); |
2269 __ Cbnz(len, &loop); | 2166 __ Cbnz(len, &loop); |
2270 __ Bind(&done); | 2167 __ Bind(&done); |
2271 } | 2168 } |
2272 | 2169 |
2273 // ----------- S t a t e ------------- | 2170 // Tail-call to the actual Call or Construct builtin. |
2274 // -- x0 : argument count (len) | 2171 __ Jump(code, RelocInfo::CODE_TARGET); |
2275 // -- x1 : target | |
2276 // -- x3 : new.target (checked to be constructor or undefined) | |
2277 // -- jssp[0] : args[len-1] | |
2278 // -- jssp[8] : args[len-2] | |
2279 // ... : ... | |
2280 // -- jssp[8*(len-2)] : args[1] | |
2281 // -- jssp[8*(len-1)] : args[0] | |
2282 // ----------------------------------- | |
2283 | |
2284 // Dispatch to Call or Construct depending on whether new.target is undefined. | |
2285 { | |
2286 __ CompareRoot(new_target, Heap::kUndefinedValueRootIndex); | |
2287 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET, eq); | |
2288 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | |
2289 } | |
2290 } | 2172 } |
2291 | 2173 |
2292 // static | 2174 // static |
2293 void Builtins::Generate_ForwardVarargs(MacroAssembler* masm, | 2175 void Builtins::Generate_CallOrConstructForwardVarargs(MacroAssembler* masm, |
2294 Handle<Code> code) { | 2176 Handle<Code> code) { |
2295 // ----------- S t a t e ------------- | 2177 // ----------- S t a t e ------------- |
2296 // -- x0 : the number of arguments (not including the receiver) | 2178 // -- x0 : the number of arguments (not including the receiver) |
2297 // -- x3 : the new.target (for [[Construct]] calls) | 2179 // -- x3 : the new.target (for [[Construct]] calls) |
2298 // -- x1 : the target to call (can be any Object) | 2180 // -- x1 : the target to call (can be any Object) |
2299 // -- x2 : start index (to support rest parameters) | 2181 // -- x2 : start index (to support rest parameters) |
2300 // ----------------------------------- | 2182 // ----------------------------------- |
2301 | 2183 |
2302 // Check if we have an arguments adaptor frame below the function frame. | 2184 // Check if we have an arguments adaptor frame below the function frame. |
2303 Label arguments_adaptor, arguments_done; | 2185 Label arguments_adaptor, arguments_done; |
2304 __ Ldr(x5, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 2186 __ Ldr(x5, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3218 // Now jump to the instructions of the returned code object. | 3100 // Now jump to the instructions of the returned code object. |
3219 __ Jump(x8); | 3101 __ Jump(x8); |
3220 } | 3102 } |
3221 | 3103 |
3222 #undef __ | 3104 #undef __ |
3223 | 3105 |
3224 } // namespace internal | 3106 } // namespace internal |
3225 } // namespace v8 | 3107 } // namespace v8 |
3226 | 3108 |
3227 #endif // V8_TARGET_ARCH_ARM | 3109 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |