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/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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |