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

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

Issue 1635823003: PPC: [es6] Tail calls support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 10 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/full-codegen/ppc/full-codegen-ppc.cc ('k') | src/ppc/code-stubs-ppc.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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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_PPC 5 #if V8_TARGET_ARCH_PPC
6 6
7 #include "src/codegen.h" 7 #include "src/codegen.h"
8 #include "src/debug/debug.h" 8 #include "src/debug/debug.h"
9 #include "src/deoptimizer.h" 9 #include "src/deoptimizer.h"
10 #include "src/full-codegen/full-codegen.h" 10 #include "src/full-codegen/full-codegen.h"
(...skipping 1964 matching lines...) Expand 10 before | Expand all | Expand 10 after
1975 } 1975 }
1976 1976
1977 // Dispatch to Call or Construct depending on whether new.target is undefined. 1977 // Dispatch to Call or Construct depending on whether new.target is undefined.
1978 { 1978 {
1979 __ CompareRoot(r6, Heap::kUndefinedValueRootIndex); 1979 __ CompareRoot(r6, Heap::kUndefinedValueRootIndex);
1980 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET, eq); 1980 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET, eq);
1981 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 1981 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
1982 } 1982 }
1983 } 1983 }
1984 1984
1985 namespace {
1986
1987 // Drops top JavaScript frame and an arguments adaptor frame below it (if
1988 // present) preserving all the arguments prepared for current call.
1989 // Does nothing if debugger is currently active.
1990 // ES6 14.6.3. PrepareForTailCall
1991 //
1992 // Stack structure for the function g() tail calling f():
1993 //
1994 // ------- Caller frame: -------
1995 // | ...
1996 // | g()'s arg M
1997 // | ...
1998 // | g()'s arg 1
1999 // | g()'s receiver arg
2000 // | g()'s caller pc
2001 // ------- g()'s frame: -------
2002 // | g()'s caller fp <- fp
2003 // | g()'s context
2004 // | function pointer: g
2005 // | -------------------------
2006 // | ...
2007 // | ...
2008 // | f()'s arg N
2009 // | ...
2010 // | f()'s arg 1
2011 // | f()'s receiver arg <- sp (f()'s caller pc is not on the stack yet!)
2012 // ----------------------
2013 //
2014 void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
2015 Register scratch1, Register scratch2,
2016 Register scratch3) {
2017 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
2018 Comment cmnt(masm, "[ PrepareForTailCall");
2019
2020 // Prepare for tail call only if the debugger is not active.
2021 Label done;
2022 ExternalReference debug_is_active =
2023 ExternalReference::debug_is_active_address(masm->isolate());
2024 __ mov(scratch1, Operand(debug_is_active));
2025 __ lbz(scratch1, MemOperand(scratch1));
2026 __ cmpi(scratch1, Operand::Zero());
2027 __ bne(&done);
2028
2029 // Check if next frame is an arguments adaptor frame.
2030 Label no_arguments_adaptor, formal_parameter_count_loaded;
2031 __ LoadP(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2032 __ LoadP(scratch3,
2033 MemOperand(scratch2, StandardFrameConstants::kContextOffset));
2034 __ CmpSmiLiteral(scratch3, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
2035 __ bne(&no_arguments_adaptor);
2036
2037 // Drop arguments adaptor frame and load arguments count.
2038 __ mr(fp, scratch2);
2039 __ LoadP(scratch1,
2040 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
2041 __ SmiUntag(scratch1);
2042 __ b(&formal_parameter_count_loaded);
2043
2044 __ bind(&no_arguments_adaptor);
2045 // Load caller's formal parameter count
2046 __ LoadP(scratch1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
2047 __ LoadP(scratch1,
2048 FieldMemOperand(scratch1, JSFunction::kSharedFunctionInfoOffset));
2049 __ LoadWordArith(
2050 scratch1, FieldMemOperand(
2051 scratch1, SharedFunctionInfo::kFormalParameterCountOffset));
2052 #if !V8_TARGET_ARCH_PPC64
2053 __ SmiUntag(scratch1);
2054 #endif
2055
2056 __ bind(&formal_parameter_count_loaded);
2057
2058 // Calculate the end of destination area where we will put the arguments
2059 // after we drop current frame. We add kPointerSize to count the receiver
2060 // argument which is not included into formal parameters count.
2061 Register dst_reg = scratch2;
2062 __ ShiftLeftImm(dst_reg, scratch1, Operand(kPointerSizeLog2));
2063 __ add(dst_reg, fp, dst_reg);
2064 __ addi(dst_reg, dst_reg,
2065 Operand(StandardFrameConstants::kCallerSPOffset + kPointerSize));
2066
2067 Register src_reg = scratch1;
2068 __ ShiftLeftImm(src_reg, args_reg, Operand(kPointerSizeLog2));
2069 __ add(src_reg, sp, src_reg);
2070 // Count receiver argument as well (not included in args_reg).
2071 __ addi(src_reg, src_reg, Operand(kPointerSize));
2072
2073 if (FLAG_debug_code) {
2074 __ cmpl(src_reg, dst_reg);
2075 __ Check(lt, kStackAccessBelowStackPointer);
2076 }
2077
2078 // Restore caller's frame pointer and return address now as they will be
2079 // overwritten by the copying loop.
2080 if (FLAG_enable_embedded_constant_pool) {
2081 __ LoadP(kConstantPoolRegister,
2082 MemOperand(fp, StandardFrameConstants::kConstantPoolOffset));
2083 }
2084 __ LoadP(r0, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
2085 __ LoadP(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2086 __ mtlr(r0);
2087
2088 // Now copy callee arguments to the caller frame going backwards to avoid
2089 // callee arguments corruption (source and destination areas could overlap).
2090
2091 // Both src_reg and dst_reg are pointing to the word after the one to copy,
2092 // so they must be pre-decremented in the loop.
2093 Register tmp_reg = scratch3;
2094 Label loop;
2095 __ addi(tmp_reg, args_reg, Operand(1)); // +1 for receiver
2096 __ mtctr(tmp_reg);
2097 __ bind(&loop);
2098 __ LoadPU(tmp_reg, MemOperand(src_reg, -kPointerSize));
2099 __ StorePU(tmp_reg, MemOperand(dst_reg, -kPointerSize));
2100 __ bdnz(&loop);
2101
2102 // Leave current frame.
2103 __ mr(sp, dst_reg);
2104
2105 __ bind(&done);
2106 }
2107 } // namespace
1985 2108
1986 // static 2109 // static
1987 void Builtins::Generate_CallFunction(MacroAssembler* masm, 2110 void Builtins::Generate_CallFunction(MacroAssembler* masm,
1988 ConvertReceiverMode mode) { 2111 ConvertReceiverMode mode,
2112 TailCallMode tail_call_mode) {
1989 // ----------- S t a t e ------------- 2113 // ----------- S t a t e -------------
1990 // -- r3 : the number of arguments (not including the receiver) 2114 // -- r3 : the number of arguments (not including the receiver)
1991 // -- r4 : the function to call (checked to be a JSFunction) 2115 // -- r4 : the function to call (checked to be a JSFunction)
1992 // ----------------------------------- 2116 // -----------------------------------
1993 __ AssertFunction(r4); 2117 __ AssertFunction(r4);
1994 2118
1995 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) 2119 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
1996 // Check that the function is not a "classConstructor". 2120 // Check that the function is not a "classConstructor".
1997 Label class_constructor; 2121 Label class_constructor;
1998 __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); 2122 __ LoadP(r5, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2063 } 2187 }
2064 __ bind(&done_convert); 2188 __ bind(&done_convert);
2065 2189
2066 // ----------- S t a t e ------------- 2190 // ----------- S t a t e -------------
2067 // -- r3 : the number of arguments (not including the receiver) 2191 // -- r3 : the number of arguments (not including the receiver)
2068 // -- r4 : the function to call (checked to be a JSFunction) 2192 // -- r4 : the function to call (checked to be a JSFunction)
2069 // -- r5 : the shared function info. 2193 // -- r5 : the shared function info.
2070 // -- cp : the function context. 2194 // -- cp : the function context.
2071 // ----------------------------------- 2195 // -----------------------------------
2072 2196
2197 if (tail_call_mode == TailCallMode::kAllow) {
2198 PrepareForTailCall(masm, r3, r6, r7, r8);
2199 }
2200
2073 __ LoadWordArith( 2201 __ LoadWordArith(
2074 r5, FieldMemOperand(r5, SharedFunctionInfo::kFormalParameterCountOffset)); 2202 r5, FieldMemOperand(r5, SharedFunctionInfo::kFormalParameterCountOffset));
2075 #if !V8_TARGET_ARCH_PPC64 2203 #if !V8_TARGET_ARCH_PPC64
2076 __ SmiUntag(r5); 2204 __ SmiUntag(r5);
2077 #endif 2205 #endif
2078 ParameterCount actual(r3); 2206 ParameterCount actual(r3);
2079 ParameterCount expected(r5); 2207 ParameterCount expected(r5);
2080 __ InvokeFunctionCode(r4, no_reg, expected, actual, JUMP_FUNCTION, 2208 __ InvokeFunctionCode(r4, no_reg, expected, actual, JUMP_FUNCTION,
2081 CheckDebugStepCallWrapper()); 2209 CheckDebugStepCallWrapper());
2082 2210
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
2167 __ add(r3, r3, r7); 2295 __ add(r3, r3, r7);
2168 } 2296 }
2169 } 2297 }
2170 __ bind(&no_bound_arguments); 2298 __ bind(&no_bound_arguments);
2171 } 2299 }
2172 2300
2173 } // namespace 2301 } // namespace
2174 2302
2175 2303
2176 // static 2304 // static
2177 void Builtins::Generate_CallBoundFunction(MacroAssembler* masm) { 2305 void Builtins::Generate_CallBoundFunctionImpl(MacroAssembler* masm,
2306 TailCallMode tail_call_mode) {
2178 // ----------- S t a t e ------------- 2307 // ----------- S t a t e -------------
2179 // -- r3 : the number of arguments (not including the receiver) 2308 // -- r3 : the number of arguments (not including the receiver)
2180 // -- r4 : the function to call (checked to be a JSBoundFunction) 2309 // -- r4 : the function to call (checked to be a JSBoundFunction)
2181 // ----------------------------------- 2310 // -----------------------------------
2182 __ AssertBoundFunction(r4); 2311 __ AssertBoundFunction(r4);
2183 2312
2313 if (tail_call_mode == TailCallMode::kAllow) {
2314 PrepareForTailCall(masm, r3, r6, r7, r8);
2315 }
2316
2184 // Patch the receiver to [[BoundThis]]. 2317 // Patch the receiver to [[BoundThis]].
2185 __ LoadP(ip, FieldMemOperand(r4, JSBoundFunction::kBoundThisOffset)); 2318 __ LoadP(ip, FieldMemOperand(r4, JSBoundFunction::kBoundThisOffset));
2186 __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2)); 2319 __ ShiftLeftImm(r0, r3, Operand(kPointerSizeLog2));
2187 __ StorePX(ip, MemOperand(sp, r0)); 2320 __ StorePX(ip, MemOperand(sp, r0));
2188 2321
2189 // Push the [[BoundArguments]] onto the stack. 2322 // Push the [[BoundArguments]] onto the stack.
2190 Generate_PushBoundArguments(masm); 2323 Generate_PushBoundArguments(masm);
2191 2324
2192 // Call the [[BoundTargetFunction]] via the Call builtin. 2325 // Call the [[BoundTargetFunction]] via the Call builtin.
2193 __ LoadP(r4, 2326 __ LoadP(r4,
2194 FieldMemOperand(r4, JSBoundFunction::kBoundTargetFunctionOffset)); 2327 FieldMemOperand(r4, JSBoundFunction::kBoundTargetFunctionOffset));
2195 __ mov(ip, Operand(ExternalReference(Builtins::kCall_ReceiverIsAny, 2328 __ mov(ip, Operand(ExternalReference(Builtins::kCall_ReceiverIsAny,
2196 masm->isolate()))); 2329 masm->isolate())));
2197 __ LoadP(ip, MemOperand(ip)); 2330 __ LoadP(ip, MemOperand(ip));
2198 __ addi(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); 2331 __ addi(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
2199 __ JumpToJSEntry(ip); 2332 __ JumpToJSEntry(ip);
2200 } 2333 }
2201 2334
2202 2335
2203 // static 2336 // static
2204 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { 2337 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode,
2338 TailCallMode tail_call_mode) {
2205 // ----------- S t a t e ------------- 2339 // ----------- S t a t e -------------
2206 // -- r3 : the number of arguments (not including the receiver) 2340 // -- r3 : the number of arguments (not including the receiver)
2207 // -- r4 : the target to call (can be any Object). 2341 // -- r4 : the target to call (can be any Object).
2208 // ----------------------------------- 2342 // -----------------------------------
2209 2343
2210 Label non_callable, non_function, non_smi; 2344 Label non_callable, non_function, non_smi;
2211 __ JumpIfSmi(r4, &non_callable); 2345 __ JumpIfSmi(r4, &non_callable);
2212 __ bind(&non_smi); 2346 __ bind(&non_smi);
2213 __ CompareObjectType(r4, r7, r8, JS_FUNCTION_TYPE); 2347 __ CompareObjectType(r4, r7, r8, JS_FUNCTION_TYPE);
2214 __ Jump(masm->isolate()->builtins()->CallFunction(mode), 2348 __ Jump(masm->isolate()->builtins()->CallFunction(mode, tail_call_mode),
2215 RelocInfo::CODE_TARGET, eq); 2349 RelocInfo::CODE_TARGET, eq);
2216 __ cmpi(r8, Operand(JS_BOUND_FUNCTION_TYPE)); 2350 __ cmpi(r8, Operand(JS_BOUND_FUNCTION_TYPE));
2217 __ Jump(masm->isolate()->builtins()->CallBoundFunction(), 2351 __ Jump(masm->isolate()->builtins()->CallBoundFunction(tail_call_mode),
2218 RelocInfo::CODE_TARGET, eq); 2352 RelocInfo::CODE_TARGET, eq);
2219 __ cmpi(r8, Operand(JS_PROXY_TYPE)); 2353 __ cmpi(r8, Operand(JS_PROXY_TYPE));
2220 __ bne(&non_function); 2354 __ bne(&non_function);
2221 2355
2356 // 0. Prepare for tail call if necessary.
2357 if (tail_call_mode == TailCallMode::kAllow) {
2358 PrepareForTailCall(masm, r3, r6, r7, r8);
2359 }
2360
2222 // 1. Runtime fallback for Proxy [[Call]]. 2361 // 1. Runtime fallback for Proxy [[Call]].
2223 __ Push(r4); 2362 __ Push(r4);
2224 // Increase the arguments size to include the pushed function and the 2363 // Increase the arguments size to include the pushed function and the
2225 // existing receiver on the stack. 2364 // existing receiver on the stack.
2226 __ addi(r3, r3, Operand(2)); 2365 __ addi(r3, r3, Operand(2));
2227 // Tail-call to the runtime. 2366 // Tail-call to the runtime.
2228 __ JumpToExternalReference( 2367 __ JumpToExternalReference(
2229 ExternalReference(Runtime::kJSProxyCall, masm->isolate())); 2368 ExternalReference(Runtime::kJSProxyCall, masm->isolate()));
2230 2369
2231 // 2. Call to something else, which might have a [[Call]] internal method (if 2370 // 2. Call to something else, which might have a [[Call]] internal method (if
2232 // not we raise an exception). 2371 // not we raise an exception).
2233 __ bind(&non_function); 2372 __ bind(&non_function);
2234 // Check if target has a [[Call]] internal method. 2373 // Check if target has a [[Call]] internal method.
2235 __ lbz(r7, FieldMemOperand(r7, Map::kBitFieldOffset)); 2374 __ lbz(r7, FieldMemOperand(r7, Map::kBitFieldOffset));
2236 __ TestBit(r7, Map::kIsCallable, r0); 2375 __ TestBit(r7, Map::kIsCallable, r0);
2237 __ beq(&non_callable, cr0); 2376 __ beq(&non_callable, cr0);
2238 // Overwrite the original receiver the (original) target. 2377 // Overwrite the original receiver the (original) target.
2239 __ ShiftLeftImm(r8, r3, Operand(kPointerSizeLog2)); 2378 __ ShiftLeftImm(r8, r3, Operand(kPointerSizeLog2));
2240 __ StorePX(r4, MemOperand(sp, r8)); 2379 __ StorePX(r4, MemOperand(sp, r8));
2241 // Let the "call_as_function_delegate" take care of the rest. 2380 // Let the "call_as_function_delegate" take care of the rest.
2242 __ LoadNativeContextSlot(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, r4); 2381 __ LoadNativeContextSlot(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, r4);
2243 __ Jump(masm->isolate()->builtins()->CallFunction( 2382 __ Jump(masm->isolate()->builtins()->CallFunction(
2244 ConvertReceiverMode::kNotNullOrUndefined), 2383 ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode),
2245 RelocInfo::CODE_TARGET); 2384 RelocInfo::CODE_TARGET);
2246 2385
2247 // 3. Call to something that is not callable. 2386 // 3. Call to something that is not callable.
2248 __ bind(&non_callable); 2387 __ bind(&non_callable);
2249 { 2388 {
2250 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); 2389 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
2251 __ Push(r4); 2390 __ Push(r4);
2252 __ CallRuntime(Runtime::kThrowCalledNonCallable); 2391 __ CallRuntime(Runtime::kThrowCalledNonCallable);
2253 } 2392 }
2254 } 2393 }
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
2535 __ bkpt(0); 2674 __ bkpt(0);
2536 } 2675 }
2537 } 2676 }
2538 2677
2539 2678
2540 #undef __ 2679 #undef __
2541 } // namespace internal 2680 } // namespace internal
2542 } // namespace v8 2681 } // namespace v8
2543 2682
2544 #endif // V8_TARGET_ARCH_PPC 2683 #endif // V8_TARGET_ARCH_PPC
OLDNEW
« no previous file with comments | « src/full-codegen/ppc/full-codegen-ppc.cc ('k') | src/ppc/code-stubs-ppc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698