OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_MIPS64 | 5 #if V8_TARGET_ARCH_MIPS64 |
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 1934 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1945 { | 1945 { |
1946 Label construct; | 1946 Label construct; |
1947 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 1947 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
1948 __ Branch(&construct, ne, a3, Operand(at)); | 1948 __ Branch(&construct, ne, a3, Operand(at)); |
1949 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1949 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
1950 __ bind(&construct); | 1950 __ bind(&construct); |
1951 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 1951 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
1952 } | 1952 } |
1953 } | 1953 } |
1954 | 1954 |
| 1955 namespace { |
| 1956 |
| 1957 // Drops top JavaScript frame and an arguments adaptor frame below it (if |
| 1958 // present) preserving all the arguments prepared for current call. |
| 1959 // Does nothing if debugger is currently active. |
| 1960 // ES6 14.6.3. PrepareForTailCall |
| 1961 // |
| 1962 // Stack structure for the function g() tail calling f(): |
| 1963 // |
| 1964 // ------- Caller frame: ------- |
| 1965 // | ... |
| 1966 // | g()'s arg M |
| 1967 // | ... |
| 1968 // | g()'s arg 1 |
| 1969 // | g()'s receiver arg |
| 1970 // | g()'s caller pc |
| 1971 // ------- g()'s frame: ------- |
| 1972 // | g()'s caller fp <- fp |
| 1973 // | g()'s context |
| 1974 // | function pointer: g |
| 1975 // | ------------------------- |
| 1976 // | ... |
| 1977 // | ... |
| 1978 // | f()'s arg N |
| 1979 // | ... |
| 1980 // | f()'s arg 1 |
| 1981 // | f()'s receiver arg <- sp (f()'s caller pc is not on the stack yet!) |
| 1982 // ---------------------- |
| 1983 // |
| 1984 void PrepareForTailCall(MacroAssembler* masm, Register args_reg, |
| 1985 Register scratch1, Register scratch2, |
| 1986 Register scratch3) { |
| 1987 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); |
| 1988 Comment cmnt(masm, "[ PrepareForTailCall"); |
| 1989 |
| 1990 // Prepare for tail call only if the debugger is not active. |
| 1991 Label done; |
| 1992 ExternalReference debug_is_active = |
| 1993 ExternalReference::debug_is_active_address(masm->isolate()); |
| 1994 __ li(at, Operand(debug_is_active)); |
| 1995 __ lb(scratch1, MemOperand(at)); |
| 1996 __ Branch(&done, ne, scratch1, Operand(zero_reg)); |
| 1997 |
| 1998 // Check if next frame is an arguments adaptor frame. |
| 1999 Label no_arguments_adaptor, formal_parameter_count_loaded; |
| 2000 __ ld(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 2001 __ ld(scratch3, MemOperand(scratch2, StandardFrameConstants::kContextOffset)); |
| 2002 __ Branch(&no_arguments_adaptor, ne, scratch3, |
| 2003 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 2004 |
| 2005 // Drop arguments adaptor frame and load arguments count. |
| 2006 __ mov(fp, scratch2); |
| 2007 __ ld(scratch1, |
| 2008 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 2009 __ SmiUntag(scratch1); |
| 2010 __ Branch(&formal_parameter_count_loaded); |
| 2011 |
| 2012 __ bind(&no_arguments_adaptor); |
| 2013 // Load caller's formal parameter count |
| 2014 __ ld(scratch1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 2015 __ ld(scratch1, |
| 2016 FieldMemOperand(scratch1, JSFunction::kSharedFunctionInfoOffset)); |
| 2017 __ lw(scratch1, |
| 2018 FieldMemOperand(scratch1, |
| 2019 SharedFunctionInfo::kFormalParameterCountOffset)); |
| 2020 |
| 2021 __ bind(&formal_parameter_count_loaded); |
| 2022 |
| 2023 // Calculate the end of destination area where we will put the arguments |
| 2024 // after we drop current frame. We add kPointerSize to count the receiver |
| 2025 // argument which is not included into formal parameters count. |
| 2026 Register dst_reg = scratch2; |
| 2027 __ Dlsa(dst_reg, fp, scratch1, kPointerSizeLog2); |
| 2028 __ Daddu(dst_reg, dst_reg, |
| 2029 Operand(StandardFrameConstants::kCallerSPOffset + kPointerSize)); |
| 2030 |
| 2031 Register src_reg = scratch1; |
| 2032 __ Dlsa(src_reg, sp, args_reg, kPointerSizeLog2); |
| 2033 // Count receiver argument as well (not included in args_reg). |
| 2034 __ Daddu(src_reg, src_reg, Operand(kPointerSize)); |
| 2035 |
| 2036 if (FLAG_debug_code) { |
| 2037 __ Check(lo, kStackAccessBelowStackPointer, src_reg, Operand(dst_reg)); |
| 2038 } |
| 2039 |
| 2040 // Restore caller's frame pointer and return address now as they will be |
| 2041 // overwritten by the copying loop. |
| 2042 __ ld(ra, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); |
| 2043 __ ld(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 2044 |
| 2045 // Now copy callee arguments to the caller frame going backwards to avoid |
| 2046 // callee arguments corruption (source and destination areas could overlap). |
| 2047 |
| 2048 // Both src_reg and dst_reg are pointing to the word after the one to copy, |
| 2049 // so they must be pre-decremented in the loop. |
| 2050 Register tmp_reg = scratch3; |
| 2051 Label loop, entry; |
| 2052 __ Branch(&entry); |
| 2053 __ bind(&loop); |
| 2054 __ Dsubu(src_reg, src_reg, Operand(kPointerSize)); |
| 2055 __ Dsubu(dst_reg, dst_reg, Operand(kPointerSize)); |
| 2056 __ ld(tmp_reg, MemOperand(src_reg)); |
| 2057 __ sd(tmp_reg, MemOperand(dst_reg)); |
| 2058 __ bind(&entry); |
| 2059 __ Branch(&loop, ne, sp, Operand(src_reg)); |
| 2060 |
| 2061 // Leave current frame. |
| 2062 __ mov(sp, dst_reg); |
| 2063 |
| 2064 __ bind(&done); |
| 2065 } |
| 2066 } // namespace |
1955 | 2067 |
1956 // static | 2068 // static |
1957 void Builtins::Generate_CallFunction(MacroAssembler* masm, | 2069 void Builtins::Generate_CallFunction(MacroAssembler* masm, |
1958 ConvertReceiverMode mode) { | 2070 ConvertReceiverMode mode, |
| 2071 TailCallMode tail_call_mode) { |
1959 // ----------- S t a t e ------------- | 2072 // ----------- S t a t e ------------- |
1960 // -- a0 : the number of arguments (not including the receiver) | 2073 // -- a0 : the number of arguments (not including the receiver) |
1961 // -- a1 : the function to call (checked to be a JSFunction) | 2074 // -- a1 : the function to call (checked to be a JSFunction) |
1962 // ----------------------------------- | 2075 // ----------------------------------- |
1963 __ AssertFunction(a1); | 2076 __ AssertFunction(a1); |
1964 | 2077 |
1965 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) | 2078 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) |
1966 // Check that function is not a "classConstructor". | 2079 // Check that function is not a "classConstructor". |
1967 Label class_constructor; | 2080 Label class_constructor; |
1968 __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 2081 __ ld(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2036 } | 2149 } |
2037 __ bind(&done_convert); | 2150 __ bind(&done_convert); |
2038 | 2151 |
2039 // ----------- S t a t e ------------- | 2152 // ----------- S t a t e ------------- |
2040 // -- a0 : the number of arguments (not including the receiver) | 2153 // -- a0 : the number of arguments (not including the receiver) |
2041 // -- a1 : the function to call (checked to be a JSFunction) | 2154 // -- a1 : the function to call (checked to be a JSFunction) |
2042 // -- a2 : the shared function info. | 2155 // -- a2 : the shared function info. |
2043 // -- cp : the function context. | 2156 // -- cp : the function context. |
2044 // ----------------------------------- | 2157 // ----------------------------------- |
2045 | 2158 |
| 2159 if (tail_call_mode == TailCallMode::kAllow) { |
| 2160 PrepareForTailCall(masm, a0, t0, t1, t2); |
| 2161 } |
| 2162 |
2046 __ lw(a2, | 2163 __ lw(a2, |
2047 FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset)); | 2164 FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset)); |
2048 ParameterCount actual(a0); | 2165 ParameterCount actual(a0); |
2049 ParameterCount expected(a2); | 2166 ParameterCount expected(a2); |
2050 __ InvokeFunctionCode(a1, no_reg, expected, actual, JUMP_FUNCTION, | 2167 __ InvokeFunctionCode(a1, no_reg, expected, actual, JUMP_FUNCTION, |
2051 CheckDebugStepCallWrapper()); | 2168 CheckDebugStepCallWrapper()); |
2052 | 2169 |
2053 // The function is a "classConstructor", need to raise an exception. | 2170 // The function is a "classConstructor", need to raise an exception. |
2054 __ bind(&class_constructor); | 2171 __ bind(&class_constructor); |
2055 { | 2172 { |
2056 FrameScope frame(masm, StackFrame::INTERNAL); | 2173 FrameScope frame(masm, StackFrame::INTERNAL); |
2057 __ Push(a1); | 2174 __ Push(a1); |
2058 __ CallRuntime(Runtime::kThrowConstructorNonCallableError); | 2175 __ CallRuntime(Runtime::kThrowConstructorNonCallableError); |
2059 } | 2176 } |
2060 } | 2177 } |
2061 | 2178 |
2062 | 2179 |
2063 // static | 2180 // static |
2064 void Builtins::Generate_CallBoundFunction(MacroAssembler* masm) { | 2181 void Builtins::Generate_CallBoundFunctionImpl(MacroAssembler* masm, |
| 2182 TailCallMode tail_call_mode) { |
2065 // ----------- S t a t e ------------- | 2183 // ----------- S t a t e ------------- |
2066 // -- a0 : the number of arguments (not including the receiver) | 2184 // -- a0 : the number of arguments (not including the receiver) |
2067 // -- a1 : the function to call (checked to be a JSBoundFunction) | 2185 // -- a1 : the function to call (checked to be a JSBoundFunction) |
2068 // ----------------------------------- | 2186 // ----------------------------------- |
2069 __ AssertBoundFunction(a1); | 2187 __ AssertBoundFunction(a1); |
2070 | 2188 |
| 2189 if (tail_call_mode == TailCallMode::kAllow) { |
| 2190 PrepareForTailCall(masm, a0, t0, t1, t2); |
| 2191 } |
| 2192 |
2071 // Patch the receiver to [[BoundThis]]. | 2193 // Patch the receiver to [[BoundThis]]. |
2072 { | 2194 { |
2073 __ ld(at, FieldMemOperand(a1, JSBoundFunction::kBoundThisOffset)); | 2195 __ ld(at, FieldMemOperand(a1, JSBoundFunction::kBoundThisOffset)); |
2074 __ Dlsa(a4, sp, a0, kPointerSizeLog2); | 2196 __ Dlsa(a4, sp, a0, kPointerSizeLog2); |
2075 __ sd(at, MemOperand(a4)); | 2197 __ sd(at, MemOperand(a4)); |
2076 } | 2198 } |
2077 | 2199 |
2078 // Load [[BoundArguments]] into a2 and length of that into a4. | 2200 // Load [[BoundArguments]] into a2 and length of that into a4. |
2079 __ ld(a2, FieldMemOperand(a1, JSBoundFunction::kBoundArgumentsOffset)); | 2201 __ ld(a2, FieldMemOperand(a1, JSBoundFunction::kBoundArgumentsOffset)); |
2080 __ ld(a4, FieldMemOperand(a2, FixedArray::kLengthOffset)); | 2202 __ ld(a4, FieldMemOperand(a2, FixedArray::kLengthOffset)); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2144 __ ld(a1, FieldMemOperand(a1, JSBoundFunction::kBoundTargetFunctionOffset)); | 2266 __ ld(a1, FieldMemOperand(a1, JSBoundFunction::kBoundTargetFunctionOffset)); |
2145 __ li(at, Operand(ExternalReference(Builtins::kCall_ReceiverIsAny, | 2267 __ li(at, Operand(ExternalReference(Builtins::kCall_ReceiverIsAny, |
2146 masm->isolate()))); | 2268 masm->isolate()))); |
2147 __ ld(at, MemOperand(at)); | 2269 __ ld(at, MemOperand(at)); |
2148 __ Daddu(at, at, Operand(Code::kHeaderSize - kHeapObjectTag)); | 2270 __ Daddu(at, at, Operand(Code::kHeaderSize - kHeapObjectTag)); |
2149 __ Jump(at); | 2271 __ Jump(at); |
2150 } | 2272 } |
2151 | 2273 |
2152 | 2274 |
2153 // static | 2275 // static |
2154 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { | 2276 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode, |
| 2277 TailCallMode tail_call_mode) { |
2155 // ----------- S t a t e ------------- | 2278 // ----------- S t a t e ------------- |
2156 // -- a0 : the number of arguments (not including the receiver) | 2279 // -- a0 : the number of arguments (not including the receiver) |
2157 // -- a1 : the target to call (can be any Object). | 2280 // -- a1 : the target to call (can be any Object). |
2158 // ----------------------------------- | 2281 // ----------------------------------- |
2159 | 2282 |
2160 Label non_callable, non_function, non_smi; | 2283 Label non_callable, non_function, non_smi; |
2161 __ JumpIfSmi(a1, &non_callable); | 2284 __ JumpIfSmi(a1, &non_callable); |
2162 __ bind(&non_smi); | 2285 __ bind(&non_smi); |
2163 __ GetObjectType(a1, t1, t2); | 2286 __ GetObjectType(a1, t1, t2); |
2164 __ Jump(masm->isolate()->builtins()->CallFunction(mode), | 2287 __ Jump(masm->isolate()->builtins()->CallFunction(mode, tail_call_mode), |
2165 RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE)); | 2288 RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE)); |
2166 __ Jump(masm->isolate()->builtins()->CallBoundFunction(), | 2289 __ Jump(masm->isolate()->builtins()->CallBoundFunction(tail_call_mode), |
2167 RelocInfo::CODE_TARGET, eq, t2, Operand(JS_BOUND_FUNCTION_TYPE)); | 2290 RelocInfo::CODE_TARGET, eq, t2, Operand(JS_BOUND_FUNCTION_TYPE)); |
2168 __ Branch(&non_function, ne, t2, Operand(JS_PROXY_TYPE)); | 2291 __ Branch(&non_function, ne, t2, Operand(JS_PROXY_TYPE)); |
2169 | 2292 |
| 2293 // 0. Prepare for tail call if necessary. |
| 2294 if (tail_call_mode == TailCallMode::kAllow) { |
| 2295 PrepareForTailCall(masm, a0, t0, t1, t2); |
| 2296 } |
| 2297 |
2170 // 1. Runtime fallback for Proxy [[Call]]. | 2298 // 1. Runtime fallback for Proxy [[Call]]. |
2171 __ Push(a1); | 2299 __ Push(a1); |
2172 // Increase the arguments size to include the pushed function and the | 2300 // Increase the arguments size to include the pushed function and the |
2173 // existing receiver on the stack. | 2301 // existing receiver on the stack. |
2174 __ Daddu(a0, a0, 2); | 2302 __ Daddu(a0, a0, 2); |
2175 // Tail-call to the runtime. | 2303 // Tail-call to the runtime. |
2176 __ JumpToExternalReference( | 2304 __ JumpToExternalReference( |
2177 ExternalReference(Runtime::kJSProxyCall, masm->isolate())); | 2305 ExternalReference(Runtime::kJSProxyCall, masm->isolate())); |
2178 | 2306 |
2179 // 2. Call to something else, which might have a [[Call]] internal method (if | 2307 // 2. Call to something else, which might have a [[Call]] internal method (if |
2180 // not we raise an exception). | 2308 // not we raise an exception). |
2181 __ bind(&non_function); | 2309 __ bind(&non_function); |
2182 // Check if target has a [[Call]] internal method. | 2310 // Check if target has a [[Call]] internal method. |
2183 __ lbu(t1, FieldMemOperand(t1, Map::kBitFieldOffset)); | 2311 __ lbu(t1, FieldMemOperand(t1, Map::kBitFieldOffset)); |
2184 __ And(t1, t1, Operand(1 << Map::kIsCallable)); | 2312 __ And(t1, t1, Operand(1 << Map::kIsCallable)); |
2185 __ Branch(&non_callable, eq, t1, Operand(zero_reg)); | 2313 __ Branch(&non_callable, eq, t1, Operand(zero_reg)); |
2186 // Overwrite the original receiver with the (original) target. | 2314 // Overwrite the original receiver with the (original) target. |
2187 __ Dlsa(at, sp, a0, kPointerSizeLog2); | 2315 __ Dlsa(at, sp, a0, kPointerSizeLog2); |
2188 __ sd(a1, MemOperand(at)); | 2316 __ sd(a1, MemOperand(at)); |
2189 // Let the "call_as_function_delegate" take care of the rest. | 2317 // Let the "call_as_function_delegate" take care of the rest. |
2190 __ LoadNativeContextSlot(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, a1); | 2318 __ LoadNativeContextSlot(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, a1); |
2191 __ Jump(masm->isolate()->builtins()->CallFunction( | 2319 __ Jump(masm->isolate()->builtins()->CallFunction( |
2192 ConvertReceiverMode::kNotNullOrUndefined), | 2320 ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode), |
2193 RelocInfo::CODE_TARGET); | 2321 RelocInfo::CODE_TARGET); |
2194 | 2322 |
2195 // 3. Call to something that is not callable. | 2323 // 3. Call to something that is not callable. |
2196 __ bind(&non_callable); | 2324 __ bind(&non_callable); |
2197 { | 2325 { |
2198 FrameScope scope(masm, StackFrame::INTERNAL); | 2326 FrameScope scope(masm, StackFrame::INTERNAL); |
2199 __ Push(a1); | 2327 __ Push(a1); |
2200 __ CallRuntime(Runtime::kThrowCalledNonCallable); | 2328 __ CallRuntime(Runtime::kThrowCalledNonCallable); |
2201 } | 2329 } |
2202 } | 2330 } |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2540 } | 2668 } |
2541 } | 2669 } |
2542 | 2670 |
2543 | 2671 |
2544 #undef __ | 2672 #undef __ |
2545 | 2673 |
2546 } // namespace internal | 2674 } // namespace internal |
2547 } // namespace v8 | 2675 } // namespace v8 |
2548 | 2676 |
2549 #endif // V8_TARGET_ARCH_MIPS64 | 2677 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |