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