Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/builtins/arm64/builtins-arm64.cc

Issue 2930623002: [builtins] Start refactoring the Apply builtin. (Closed)
Patch Set: Address feedback. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/builtins/arm/builtins-arm.cc ('k') | src/builtins/builtins.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/builtins/arm/builtins-arm.cc ('k') | src/builtins/builtins.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698