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

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

Issue 1609893003: [es6] Tail calls support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebasing Created 4 years, 11 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/mips/code-stubs-mips.cc ('k') | src/mips64/code-stubs-mips64.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 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
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
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
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
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
OLDNEW
« no previous file with comments | « src/mips/code-stubs-mips.cc ('k') | src/mips64/code-stubs-mips64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698