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