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

Side by Side Diff: src/mips/builtins-mips.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/ic/ic-state.h ('k') | src/mips/code-stubs-mips.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_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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ic/ic-state.h ('k') | src/mips/code-stubs-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698