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

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

Issue 1609893003: [es6] Tail calls support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebasing Created 4 years, 11 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/arm/code-stubs-arm.cc ('k') | src/arm64/code-stubs-arm64.cc » ('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/codegen.h" 8 #include "src/codegen.h"
9 #include "src/debug/debug.h" 9 #include "src/debug/debug.h"
10 #include "src/deoptimizer.h" 10 #include "src/deoptimizer.h"
(...skipping 1970 matching lines...) Expand 10 before | Expand all | Expand 10 after
1981 // ----------------------------------- 1981 // -----------------------------------
1982 1982
1983 // Dispatch to Call or Construct depending on whether new.target is undefined. 1983 // Dispatch to Call or Construct depending on whether new.target is undefined.
1984 { 1984 {
1985 __ CompareRoot(new_target, Heap::kUndefinedValueRootIndex); 1985 __ CompareRoot(new_target, Heap::kUndefinedValueRootIndex);
1986 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET, eq); 1986 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET, eq);
1987 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 1987 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
1988 } 1988 }
1989 } 1989 }
1990 1990
1991 namespace {
1992
1993 // Drops top JavaScript frame and an arguments adaptor frame below it (if
1994 // present) preserving all the arguments prepared for current call.
1995 // Does nothing if debugger is currently active.
1996 // ES6 14.6.3. PrepareForTailCall
1997 //
1998 // Stack structure for the function g() tail calling f():
1999 //
2000 // ------- Caller frame: -------
2001 // | ...
2002 // | g()'s arg M
2003 // | ...
2004 // | g()'s arg 1
2005 // | g()'s receiver arg
2006 // | g()'s caller pc
2007 // ------- g()'s frame: -------
2008 // | g()'s caller fp <- fp
2009 // | g()'s context
2010 // | function pointer: g
2011 // | -------------------------
2012 // | ...
2013 // | ...
2014 // | f()'s arg N
2015 // | ...
2016 // | f()'s arg 1
2017 // | f()'s receiver arg <- sp (f()'s caller pc is not on the stack yet!)
2018 // ----------------------
2019 //
2020 void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
2021 Register scratch1, Register scratch2,
2022 Register scratch3) {
2023 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
2024 Comment cmnt(masm, "[ PrepareForTailCall");
2025
2026 // Prepare for tail call only if the debugger is not active.
2027 Label done;
2028 ExternalReference debug_is_active =
2029 ExternalReference::debug_is_active_address(masm->isolate());
2030 __ Mov(scratch1, Operand(debug_is_active));
2031 __ Ldrb(scratch1, MemOperand(scratch1));
2032 __ Cmp(scratch1, Operand(0));
2033 __ B(ne, &done);
2034
2035 // Check if next frame is an arguments adaptor frame.
2036 Label no_arguments_adaptor, formal_parameter_count_loaded;
2037 __ Ldr(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2038 __ Ldr(scratch3,
2039 MemOperand(scratch2, StandardFrameConstants::kContextOffset));
2040 __ Cmp(scratch3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2041 __ B(ne, &no_arguments_adaptor);
2042
2043 // Drop arguments adaptor frame and load arguments count.
2044 __ mov(fp, scratch2);
2045 __ Ldr(scratch1,
2046 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
2047 __ SmiUntag(scratch1);
2048 __ B(&formal_parameter_count_loaded);
2049
2050 __ bind(&no_arguments_adaptor);
2051 // Load caller's formal parameter count
2052 __ Ldr(scratch1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
2053 __ Ldr(scratch1,
2054 FieldMemOperand(scratch1, JSFunction::kSharedFunctionInfoOffset));
2055 __ Ldrsw(scratch1,
2056 FieldMemOperand(scratch1,
2057 SharedFunctionInfo::kFormalParameterCountOffset));
2058 __ bind(&formal_parameter_count_loaded);
2059
2060 // Calculate the end of destination area where we will put the arguments
2061 // after we drop current frame. We add kPointerSize to count the receiver
2062 // argument which is not included into formal parameters count.
2063 Register dst_reg = scratch2;
2064 __ add(dst_reg, fp, Operand(scratch1, LSL, kPointerSizeLog2));
2065 __ add(dst_reg, dst_reg,
2066 Operand(StandardFrameConstants::kCallerSPOffset + kPointerSize));
2067
2068 Register src_reg = scratch1;
2069 __ add(src_reg, jssp, Operand(args_reg, LSL, kPointerSizeLog2));
2070 // Count receiver argument as well (not included in args_reg).
2071 __ add(src_reg, src_reg, Operand(kPointerSize));
2072
2073 if (FLAG_debug_code) {
2074 __ Cmp(src_reg, dst_reg);
2075 __ Check(lo, kStackAccessBelowStackPointer);
2076 }
2077
2078 // Restore caller's frame pointer and return address now as they will be
2079 // overwritten by the copying loop.
2080 __ Ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
2081 __ Ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2082
2083 // Now copy callee arguments to the caller frame going backwards to avoid
2084 // callee arguments corruption (source and destination areas could overlap).
2085
2086 // Both src_reg and dst_reg are pointing to the word after the one to copy,
2087 // so they must be pre-decremented in the loop.
2088 Register tmp_reg = scratch3;
2089 Label loop, entry;
2090 __ B(&entry);
2091 __ bind(&loop);
2092 __ Ldr(tmp_reg, MemOperand(src_reg, -kPointerSize, PreIndex));
2093 __ Str(tmp_reg, MemOperand(dst_reg, -kPointerSize, PreIndex));
2094 __ bind(&entry);
2095 __ Cmp(jssp, src_reg);
2096 __ B(ne, &loop);
2097
2098 // Leave current frame.
2099 __ Mov(jssp, dst_reg);
2100 __ SetStackPointer(jssp);
2101 __ AssertStackConsistency();
2102
2103 __ bind(&done);
2104 }
2105 } // namespace
1991 2106
1992 // static 2107 // static
1993 void Builtins::Generate_CallFunction(MacroAssembler* masm, 2108 void Builtins::Generate_CallFunction(MacroAssembler* masm,
1994 ConvertReceiverMode mode) { 2109 ConvertReceiverMode mode,
2110 TailCallMode tail_call_mode) {
1995 ASM_LOCATION("Builtins::Generate_CallFunction"); 2111 ASM_LOCATION("Builtins::Generate_CallFunction");
1996 // ----------- S t a t e ------------- 2112 // ----------- S t a t e -------------
1997 // -- x0 : the number of arguments (not including the receiver) 2113 // -- x0 : the number of arguments (not including the receiver)
1998 // -- x1 : the function to call (checked to be a JSFunction) 2114 // -- x1 : the function to call (checked to be a JSFunction)
1999 // ----------------------------------- 2115 // -----------------------------------
2000 __ AssertFunction(x1); 2116 __ AssertFunction(x1);
2001 2117
2002 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) 2118 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
2003 // Check that function is not a "classConstructor". 2119 // Check that function is not a "classConstructor".
2004 Label class_constructor; 2120 Label class_constructor;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
2072 } 2188 }
2073 __ Bind(&done_convert); 2189 __ Bind(&done_convert);
2074 2190
2075 // ----------- S t a t e ------------- 2191 // ----------- S t a t e -------------
2076 // -- x0 : the number of arguments (not including the receiver) 2192 // -- x0 : the number of arguments (not including the receiver)
2077 // -- x1 : the function to call (checked to be a JSFunction) 2193 // -- x1 : the function to call (checked to be a JSFunction)
2078 // -- x2 : the shared function info. 2194 // -- x2 : the shared function info.
2079 // -- cp : the function context. 2195 // -- cp : the function context.
2080 // ----------------------------------- 2196 // -----------------------------------
2081 2197
2198 if (tail_call_mode == TailCallMode::kAllow) {
2199 PrepareForTailCall(masm, x0, x3, x4, x5);
2200 }
2201
2082 __ Ldrsw( 2202 __ Ldrsw(
2083 x2, FieldMemOperand(x2, SharedFunctionInfo::kFormalParameterCountOffset)); 2203 x2, FieldMemOperand(x2, SharedFunctionInfo::kFormalParameterCountOffset));
2084 ParameterCount actual(x0); 2204 ParameterCount actual(x0);
2085 ParameterCount expected(x2); 2205 ParameterCount expected(x2);
2086 __ InvokeFunctionCode(x1, no_reg, expected, actual, JUMP_FUNCTION, 2206 __ InvokeFunctionCode(x1, no_reg, expected, actual, JUMP_FUNCTION,
2087 CheckDebugStepCallWrapper()); 2207 CheckDebugStepCallWrapper());
2088 2208
2089 // The function is a "classConstructor", need to raise an exception. 2209 // The function is a "classConstructor", need to raise an exception.
2090 __ bind(&class_constructor); 2210 __ bind(&class_constructor);
2091 { 2211 {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2168 __ B(gt, &loop); 2288 __ B(gt, &loop);
2169 } 2289 }
2170 } 2290 }
2171 __ Bind(&no_bound_arguments); 2291 __ Bind(&no_bound_arguments);
2172 } 2292 }
2173 2293
2174 } // namespace 2294 } // namespace
2175 2295
2176 2296
2177 // static 2297 // static
2178 void Builtins::Generate_CallBoundFunction(MacroAssembler* masm) { 2298 void Builtins::Generate_CallBoundFunctionImpl(MacroAssembler* masm,
2299 TailCallMode tail_call_mode) {
2179 // ----------- S t a t e ------------- 2300 // ----------- S t a t e -------------
2180 // -- x0 : the number of arguments (not including the receiver) 2301 // -- x0 : the number of arguments (not including the receiver)
2181 // -- x1 : the function to call (checked to be a JSBoundFunction) 2302 // -- x1 : the function to call (checked to be a JSBoundFunction)
2182 // ----------------------------------- 2303 // -----------------------------------
2183 __ AssertBoundFunction(x1); 2304 __ AssertBoundFunction(x1);
2184 2305
2306 if (tail_call_mode == TailCallMode::kAllow) {
2307 PrepareForTailCall(masm, x0, x3, x4, x5);
2308 }
2309
2185 // Patch the receiver to [[BoundThis]]. 2310 // Patch the receiver to [[BoundThis]].
2186 __ Ldr(x10, FieldMemOperand(x1, JSBoundFunction::kBoundThisOffset)); 2311 __ Ldr(x10, FieldMemOperand(x1, JSBoundFunction::kBoundThisOffset));
2187 __ Poke(x10, Operand(x0, LSL, kPointerSizeLog2)); 2312 __ Poke(x10, Operand(x0, LSL, kPointerSizeLog2));
2188 2313
2189 // Push the [[BoundArguments]] onto the stack. 2314 // Push the [[BoundArguments]] onto the stack.
2190 Generate_PushBoundArguments(masm); 2315 Generate_PushBoundArguments(masm);
2191 2316
2192 // Call the [[BoundTargetFunction]] via the Call builtin. 2317 // Call the [[BoundTargetFunction]] via the Call builtin.
2193 __ Ldr(x1, FieldMemOperand(x1, JSBoundFunction::kBoundTargetFunctionOffset)); 2318 __ Ldr(x1, FieldMemOperand(x1, JSBoundFunction::kBoundTargetFunctionOffset));
2194 __ Mov(x10, 2319 __ Mov(x10,
2195 ExternalReference(Builtins::kCall_ReceiverIsAny, masm->isolate())); 2320 ExternalReference(Builtins::kCall_ReceiverIsAny, masm->isolate()));
2196 __ Ldr(x11, MemOperand(x10)); 2321 __ Ldr(x11, MemOperand(x10));
2197 __ Add(x12, x11, Code::kHeaderSize - kHeapObjectTag); 2322 __ Add(x12, x11, Code::kHeaderSize - kHeapObjectTag);
2198 __ Br(x12); 2323 __ Br(x12);
2199 } 2324 }
2200 2325
2201 2326
2202 // static 2327 // static
2203 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { 2328 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode,
2329 TailCallMode tail_call_mode) {
2204 // ----------- S t a t e ------------- 2330 // ----------- S t a t e -------------
2205 // -- x0 : the number of arguments (not including the receiver) 2331 // -- x0 : the number of arguments (not including the receiver)
2206 // -- x1 : the target to call (can be any Object). 2332 // -- x1 : the target to call (can be any Object).
2207 // ----------------------------------- 2333 // -----------------------------------
2208 2334
2209 Label non_callable, non_function, non_smi; 2335 Label non_callable, non_function, non_smi;
2210 __ JumpIfSmi(x1, &non_callable); 2336 __ JumpIfSmi(x1, &non_callable);
2211 __ Bind(&non_smi); 2337 __ Bind(&non_smi);
2212 __ CompareObjectType(x1, x4, x5, JS_FUNCTION_TYPE); 2338 __ CompareObjectType(x1, x4, x5, JS_FUNCTION_TYPE);
2213 __ Jump(masm->isolate()->builtins()->CallFunction(mode), 2339 __ Jump(masm->isolate()->builtins()->CallFunction(mode, tail_call_mode),
2214 RelocInfo::CODE_TARGET, eq); 2340 RelocInfo::CODE_TARGET, eq);
2215 __ Cmp(x5, JS_BOUND_FUNCTION_TYPE); 2341 __ Cmp(x5, JS_BOUND_FUNCTION_TYPE);
2216 __ Jump(masm->isolate()->builtins()->CallBoundFunction(), 2342 __ Jump(masm->isolate()->builtins()->CallBoundFunction(tail_call_mode),
2217 RelocInfo::CODE_TARGET, eq); 2343 RelocInfo::CODE_TARGET, eq);
2218 __ Cmp(x5, JS_PROXY_TYPE); 2344 __ Cmp(x5, JS_PROXY_TYPE);
2219 __ B(ne, &non_function); 2345 __ B(ne, &non_function);
2220 2346
2347 // 0. Prepare for tail call if necessary.
2348 if (tail_call_mode == TailCallMode::kAllow) {
2349 PrepareForTailCall(masm, x0, x3, x4, x5);
2350 }
2351
2221 // 1. Runtime fallback for Proxy [[Call]]. 2352 // 1. Runtime fallback for Proxy [[Call]].
2222 __ Push(x1); 2353 __ Push(x1);
2223 // Increase the arguments size to include the pushed function and the 2354 // Increase the arguments size to include the pushed function and the
2224 // existing receiver on the stack. 2355 // existing receiver on the stack.
2225 __ Add(x0, x0, Operand(2)); 2356 __ Add(x0, x0, Operand(2));
2226 // Tail-call to the runtime. 2357 // Tail-call to the runtime.
2227 __ JumpToExternalReference( 2358 __ JumpToExternalReference(
2228 ExternalReference(Runtime::kJSProxyCall, masm->isolate())); 2359 ExternalReference(Runtime::kJSProxyCall, masm->isolate()));
2229 2360
2230 // 2. Call to something else, which might have a [[Call]] internal method (if 2361 // 2. Call to something else, which might have a [[Call]] internal method (if
2231 // not we raise an exception). 2362 // not we raise an exception).
2232 __ Bind(&non_function); 2363 __ Bind(&non_function);
2233 // Check if target has a [[Call]] internal method. 2364 // Check if target has a [[Call]] internal method.
2234 __ Ldrb(x4, FieldMemOperand(x4, Map::kBitFieldOffset)); 2365 __ Ldrb(x4, FieldMemOperand(x4, Map::kBitFieldOffset));
2235 __ TestAndBranchIfAllClear(x4, 1 << Map::kIsCallable, &non_callable); 2366 __ TestAndBranchIfAllClear(x4, 1 << Map::kIsCallable, &non_callable);
2236 // Overwrite the original receiver with the (original) target. 2367 // Overwrite the original receiver with the (original) target.
2237 __ Poke(x1, Operand(x0, LSL, kXRegSizeLog2)); 2368 __ Poke(x1, Operand(x0, LSL, kXRegSizeLog2));
2238 // Let the "call_as_function_delegate" take care of the rest. 2369 // Let the "call_as_function_delegate" take care of the rest.
2239 __ LoadNativeContextSlot(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, x1); 2370 __ LoadNativeContextSlot(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, x1);
2240 __ Jump(masm->isolate()->builtins()->CallFunction( 2371 __ Jump(masm->isolate()->builtins()->CallFunction(
2241 ConvertReceiverMode::kNotNullOrUndefined), 2372 ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode),
2242 RelocInfo::CODE_TARGET); 2373 RelocInfo::CODE_TARGET);
2243 2374
2244 // 3. Call to something that is not callable. 2375 // 3. Call to something that is not callable.
2245 __ bind(&non_callable); 2376 __ bind(&non_callable);
2246 { 2377 {
2247 FrameScope scope(masm, StackFrame::INTERNAL); 2378 FrameScope scope(masm, StackFrame::INTERNAL);
2248 __ Push(x1); 2379 __ Push(x1);
2249 __ CallRuntime(Runtime::kThrowCalledNonCallable); 2380 __ CallRuntime(Runtime::kThrowCalledNonCallable);
2250 } 2381 }
2251 } 2382 }
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
2614 } 2745 }
2615 } 2746 }
2616 2747
2617 2748
2618 #undef __ 2749 #undef __
2619 2750
2620 } // namespace internal 2751 } // namespace internal
2621 } // namespace v8 2752 } // namespace v8
2622 2753
2623 #endif // V8_TARGET_ARCH_ARM 2754 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/code-stubs-arm.cc ('k') | src/arm64/code-stubs-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698