Chromium Code Reviews| 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_X64 | 5 #if V8_TARGET_ARCH_X64 |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/codegen.h" | 8 #include "src/codegen.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 1179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1190 __ JumpIfRoot(rax, Heap::kNullValueRootIndex, &no_arguments, Label::kNear); | 1190 __ JumpIfRoot(rax, Heap::kNullValueRootIndex, &no_arguments, Label::kNear); |
| 1191 __ JumpIfRoot(rax, Heap::kUndefinedValueRootIndex, &no_arguments, | 1191 __ JumpIfRoot(rax, Heap::kUndefinedValueRootIndex, &no_arguments, |
| 1192 Label::kNear); | 1192 Label::kNear); |
| 1193 | 1193 |
| 1194 // 4a. Apply the receiver to the given argArray (passing undefined for | 1194 // 4a. Apply the receiver to the given argArray (passing undefined for |
| 1195 // new.target). | 1195 // new.target). |
| 1196 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); | 1196 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); |
| 1197 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); | 1197 __ Jump(masm->isolate()->builtins()->Apply(), RelocInfo::CODE_TARGET); |
| 1198 | 1198 |
| 1199 // 4b. The argArray is either null or undefined, so we tail call without any | 1199 // 4b. The argArray is either null or undefined, so we tail call without any |
| 1200 // arguments to the receiver. | 1200 // arguments to the receiver. Since we did not create a frame for |
| 1201 // Function.prototype.apply() yet, we use a normal Call builtin here. | |
| 1201 __ bind(&no_arguments); | 1202 __ bind(&no_arguments); |
| 1202 { | 1203 { |
| 1203 __ Set(rax, 0); | 1204 __ Set(rax, 0); |
| 1204 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1205 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1205 } | 1206 } |
| 1206 | 1207 |
| 1207 // 4c. The receiver is not callable, throw an appropriate TypeError. | 1208 // 4c. The receiver is not callable, throw an appropriate TypeError. |
| 1208 __ bind(&receiver_not_callable); | 1209 __ bind(&receiver_not_callable); |
| 1209 { | 1210 { |
| 1210 StackArgumentsAccessor args(rsp, 0); | 1211 StackArgumentsAccessor args(rsp, 0); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1254 __ bind(&loop); | 1255 __ bind(&loop); |
| 1255 __ movp(rbx, args.GetArgumentOperand(1)); | 1256 __ movp(rbx, args.GetArgumentOperand(1)); |
| 1256 __ movp(args.GetArgumentOperand(0), rbx); | 1257 __ movp(args.GetArgumentOperand(0), rbx); |
| 1257 __ decp(rcx); | 1258 __ decp(rcx); |
| 1258 __ j(not_zero, &loop); // While non-zero. | 1259 __ j(not_zero, &loop); // While non-zero. |
| 1259 __ DropUnderReturnAddress(1, rbx); // Drop one slot under return address. | 1260 __ DropUnderReturnAddress(1, rbx); // Drop one slot under return address. |
| 1260 __ decp(rax); // One fewer argument (first argument is new receiver). | 1261 __ decp(rax); // One fewer argument (first argument is new receiver). |
| 1261 } | 1262 } |
| 1262 | 1263 |
| 1263 // 4. Call the callable. | 1264 // 4. Call the callable. |
| 1265 // Since we did not create a frame for Function.prototype.call() yet, | |
| 1266 // we use a normal Call builtin here. | |
| 1264 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1267 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1265 } | 1268 } |
| 1266 | 1269 |
| 1267 | 1270 |
| 1268 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { | 1271 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { |
| 1269 // ----------- S t a t e ------------- | 1272 // ----------- S t a t e ------------- |
| 1270 // -- rax : argc | 1273 // -- rax : argc |
| 1271 // -- rsp[0] : return address | 1274 // -- rsp[0] : return address |
| 1272 // -- rsp[8] : argumentsList | 1275 // -- rsp[8] : argumentsList |
| 1273 // -- rsp[16] : thisArgument | 1276 // -- rsp[16] : thisArgument |
| (...skipping 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2035 | 2038 |
| 2036 // Dispatch to Call or Construct depending on whether new.target is undefined. | 2039 // Dispatch to Call or Construct depending on whether new.target is undefined. |
| 2037 { | 2040 { |
| 2038 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); | 2041 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); |
| 2039 __ j(equal, masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 2042 __ j(equal, masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 2040 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 2043 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 2041 } | 2044 } |
| 2042 } | 2045 } |
| 2043 | 2046 |
| 2044 | 2047 |
| 2048 namespace { | |
| 2049 | |
| 2050 // Drops top JavaScript frame and an arguments adaptor frame below it (if | |
| 2051 // present) preserving all the arguments prepared for current call. | |
| 2052 // Does nothing if debugger is currently active. | |
| 2053 // ES6 14.6.3. PrepareForTailCall | |
| 2054 // | |
| 2055 // Stack structure for the function g() tail calling f(): | |
| 2056 // | |
| 2057 // ------- Caller frame: ------- | |
| 2058 // | ... | |
| 2059 // | g()'s arg M | |
| 2060 // | ... | |
| 2061 // | g()'s arg 1 | |
| 2062 // | g()'s receiver arg | |
| 2063 // | g()'s caller pc | |
| 2064 // ------- g()'s frame: ------- | |
| 2065 // | g()'s caller fp <- fp | |
| 2066 // | g()'s context | |
| 2067 // | function pointer: g | |
| 2068 // | ------------------------- | |
| 2069 // | ... | |
| 2070 // | ... | |
| 2071 // | f()'s arg N | |
| 2072 // | ... | |
| 2073 // | f()'s arg 1 | |
| 2074 // | f()'s receiver arg | |
| 2075 // | f()'s caller pc <- sp | |
| 2076 // ---------------------- | |
| 2077 // | |
| 2078 void PrepareForTailCall(MacroAssembler* masm, Register args_reg, | |
| 2079 Register scratch1, Register scratch2, | |
| 2080 Register scratch3) { | |
| 2081 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); | |
| 2082 Comment cmnt(masm, "[ PrepareForTailCall"); | |
| 2083 | |
| 2084 // Prepare for tail call only if the debugger is not active. | |
| 2085 Label done; | |
| 2086 ExternalReference debug_is_active = | |
| 2087 ExternalReference::debug_is_active_address(masm->isolate()); | |
| 2088 __ Move(kScratchRegister, debug_is_active); | |
| 2089 __ cmpb(Operand(kScratchRegister, 0), Immediate(0)); | |
| 2090 __ j(not_equal, &done, Label::kNear); | |
| 2091 | |
| 2092 // Check if next frame is an arguments adaptor frame. | |
| 2093 Label no_arguments_adaptor, formal_parameter_count_loaded; | |
| 2094 __ movp(scratch2, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | |
| 2095 __ Cmp(Operand(scratch2, StandardFrameConstants::kContextOffset), | |
| 2096 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | |
| 2097 __ j(not_equal, &no_arguments_adaptor, Label::kNear); | |
| 2098 | |
| 2099 // Drop arguments adaptor frame and load arguments count. | |
| 2100 __ movp(rbp, scratch2); | |
| 2101 __ SmiToInteger32( | |
| 2102 scratch1, Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
| 2103 __ jmp(&formal_parameter_count_loaded, Label::kNear); | |
| 2104 | |
| 2105 __ bind(&no_arguments_adaptor); | |
| 2106 // Load caller's formal parameter count | |
| 2107 __ movp(scratch1, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | |
| 2108 __ movp(scratch1, | |
| 2109 FieldOperand(scratch1, JSFunction::kSharedFunctionInfoOffset)); | |
| 2110 __ LoadSharedFunctionInfoSpecialField( | |
| 2111 scratch1, scratch1, SharedFunctionInfo::kFormalParameterCountOffset); | |
| 2112 | |
| 2113 __ bind(&formal_parameter_count_loaded); | |
| 2114 | |
| 2115 // Calculate the destination address where we will put the return address | |
| 2116 // after we drop current frame. | |
| 2117 Register new_sp_reg = scratch2; | |
| 2118 __ subp(scratch1, args_reg); | |
| 2119 __ leap(new_sp_reg, Operand(rbp, scratch1, times_pointer_size, | |
| 2120 StandardFrameConstants::kCallerPCOffset)); | |
| 2121 | |
| 2122 if (FLAG_debug_code) { | |
| 2123 __ cmpp(rsp, new_sp_reg); | |
| 2124 __ Check(below, kStackAccessBelowStackPointer); | |
| 2125 } | |
| 2126 | |
| 2127 // Copy receiver and return address as well. | |
| 2128 Register count_reg = scratch1; | |
| 2129 __ leap(count_reg, Operand(args_reg, 2)); | |
| 2130 | |
| 2131 // Copy return address from caller's frame to current frame's return address | |
| 2132 // to avoid its trashing and let the following loop copy it to the right | |
| 2133 // place. | |
| 2134 Register tmp_reg = scratch3; | |
| 2135 __ movp(tmp_reg, Operand(rbp, StandardFrameConstants::kCallerPCOffset)); | |
| 2136 __ movp(Operand(rsp, 0), tmp_reg); | |
| 2137 | |
| 2138 // Restore caller's frame pointer now as it could be overwritten by | |
| 2139 // the copying loop. | |
| 2140 __ movp(rbp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | |
| 2141 | |
| 2142 Operand src(rsp, count_reg, times_pointer_size, 0); | |
| 2143 Operand dst(new_sp_reg, count_reg, times_pointer_size, 0); | |
| 2144 | |
| 2145 // Now copy callee arguments to the caller frame going backwards to avoid | |
| 2146 // callee arguments corruption (source and destination areas could overlap). | |
| 2147 Label loop, entry; | |
| 2148 __ jmp(&entry, Label::kNear); | |
| 2149 __ bind(&loop); | |
| 2150 __ decp(count_reg); | |
| 2151 __ movp(tmp_reg, src); | |
| 2152 __ movp(dst, tmp_reg); | |
| 2153 __ bind(&entry); | |
| 2154 __ cmpp(count_reg, Immediate(0)); | |
| 2155 __ j(not_equal, &loop, Label::kNear); | |
| 2156 | |
| 2157 // Leave current frame. | |
| 2158 __ movp(rsp, new_sp_reg); | |
| 2159 | |
| 2160 __ bind(&done); | |
| 2161 } | |
| 2162 } // namespace | |
| 2163 | |
| 2164 | |
| 2045 // static | 2165 // static |
| 2046 void Builtins::Generate_CallFunction(MacroAssembler* masm, | 2166 void Builtins::Generate_CallFunction(MacroAssembler* masm, |
| 2047 ConvertReceiverMode mode) { | 2167 ConvertReceiverMode mode, |
| 2168 TailCallMode tail_call_mode) { | |
| 2048 // ----------- S t a t e ------------- | 2169 // ----------- S t a t e ------------- |
| 2049 // -- rax : the number of arguments (not including the receiver) | 2170 // -- rax : the number of arguments (not including the receiver) |
| 2050 // -- rdi : the function to call (checked to be a JSFunction) | 2171 // -- rdi : the function to call (checked to be a JSFunction) |
| 2051 // ----------------------------------- | 2172 // ----------------------------------- |
| 2052 StackArgumentsAccessor args(rsp, rax); | 2173 StackArgumentsAccessor args(rsp, rax); |
| 2053 __ AssertFunction(rdi); | 2174 __ AssertFunction(rdi); |
| 2054 | 2175 |
| 2055 // ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) | 2176 // ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) |
| 2056 // Check that the function is not a "classConstructor". | 2177 // Check that the function is not a "classConstructor". |
| 2057 Label class_constructor; | 2178 Label class_constructor; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2133 } | 2254 } |
| 2134 __ bind(&done_convert); | 2255 __ bind(&done_convert); |
| 2135 | 2256 |
| 2136 // ----------- S t a t e ------------- | 2257 // ----------- S t a t e ------------- |
| 2137 // -- rax : the number of arguments (not including the receiver) | 2258 // -- rax : the number of arguments (not including the receiver) |
| 2138 // -- rdx : the shared function info. | 2259 // -- rdx : the shared function info. |
| 2139 // -- rdi : the function to call (checked to be a JSFunction) | 2260 // -- rdi : the function to call (checked to be a JSFunction) |
| 2140 // -- rsi : the function context. | 2261 // -- rsi : the function context. |
| 2141 // ----------------------------------- | 2262 // ----------------------------------- |
| 2142 | 2263 |
| 2264 if (tail_call_mode == TailCallMode::kAllow) { | |
| 2265 PrepareForTailCall(masm, rax, rbx, rcx, r8); | |
| 2266 } | |
| 2267 | |
| 2143 __ LoadSharedFunctionInfoSpecialField( | 2268 __ LoadSharedFunctionInfoSpecialField( |
| 2144 rbx, rdx, SharedFunctionInfo::kFormalParameterCountOffset); | 2269 rbx, rdx, SharedFunctionInfo::kFormalParameterCountOffset); |
| 2145 ParameterCount actual(rax); | 2270 ParameterCount actual(rax); |
| 2146 ParameterCount expected(rbx); | 2271 ParameterCount expected(rbx); |
| 2147 | 2272 |
| 2148 __ InvokeFunctionCode(rdi, no_reg, expected, actual, JUMP_FUNCTION, | 2273 __ InvokeFunctionCode(rdi, no_reg, expected, actual, JUMP_FUNCTION, |
| 2149 CheckDebugStepCallWrapper()); | 2274 CheckDebugStepCallWrapper()); |
| 2150 | 2275 |
| 2151 // The function is a "classConstructor", need to raise an exception. | 2276 // The function is a "classConstructor", need to raise an exception. |
| 2152 __ bind(&class_constructor); | 2277 __ bind(&class_constructor); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2237 // [[BoundArguments]]), so we need to subtract one for the return address. | 2362 // [[BoundArguments]]), so we need to subtract one for the return address. |
| 2238 __ decl(rax); | 2363 __ decl(rax); |
| 2239 } | 2364 } |
| 2240 __ bind(&no_bound_arguments); | 2365 __ bind(&no_bound_arguments); |
| 2241 } | 2366 } |
| 2242 | 2367 |
| 2243 } // namespace | 2368 } // namespace |
| 2244 | 2369 |
| 2245 | 2370 |
| 2246 // static | 2371 // static |
| 2247 void Builtins::Generate_CallBoundFunction(MacroAssembler* masm) { | 2372 void Builtins::Generate_CallBoundFunctionImpl(MacroAssembler* masm, |
|
Benedikt Meurer
2016/01/22 05:23:12
Nit: No need to add Impl suffix here.
Igor Sheludko
2016/01/22 09:48:51
We have to use a different name here otherwise the
| |
| 2373 TailCallMode tail_call_mode) { | |
| 2248 // ----------- S t a t e ------------- | 2374 // ----------- S t a t e ------------- |
| 2249 // -- rax : the number of arguments (not including the receiver) | 2375 // -- rax : the number of arguments (not including the receiver) |
| 2250 // -- rdi : the function to call (checked to be a JSBoundFunction) | 2376 // -- rdi : the function to call (checked to be a JSBoundFunction) |
| 2251 // ----------------------------------- | 2377 // ----------------------------------- |
| 2252 __ AssertBoundFunction(rdi); | 2378 __ AssertBoundFunction(rdi); |
| 2253 | 2379 |
| 2380 if (tail_call_mode == TailCallMode::kAllow) { | |
|
Benedikt Meurer
2016/01/22 05:23:12
You don't need to do this here. Just pick the righ
Igor Sheludko
2016/01/22 09:48:51
If we do like you suggested that would mean that w
| |
| 2381 PrepareForTailCall(masm, rax, rbx, rcx, r8); | |
| 2382 } | |
| 2383 | |
| 2254 // Patch the receiver to [[BoundThis]]. | 2384 // Patch the receiver to [[BoundThis]]. |
| 2255 StackArgumentsAccessor args(rsp, rax); | 2385 StackArgumentsAccessor args(rsp, rax); |
| 2256 __ movp(rbx, FieldOperand(rdi, JSBoundFunction::kBoundThisOffset)); | 2386 __ movp(rbx, FieldOperand(rdi, JSBoundFunction::kBoundThisOffset)); |
| 2257 __ movp(args.GetReceiverOperand(), rbx); | 2387 __ movp(args.GetReceiverOperand(), rbx); |
| 2258 | 2388 |
| 2259 // Push the [[BoundArguments]] onto the stack. | 2389 // Push the [[BoundArguments]] onto the stack. |
| 2260 Generate_PushBoundArguments(masm); | 2390 Generate_PushBoundArguments(masm); |
| 2261 | 2391 |
| 2262 // Call the [[BoundTargetFunction]] via the Call builtin. | 2392 // Call the [[BoundTargetFunction]] via the Call builtin. |
| 2263 __ movp(rdi, FieldOperand(rdi, JSBoundFunction::kBoundTargetFunctionOffset)); | 2393 __ movp(rdi, FieldOperand(rdi, JSBoundFunction::kBoundTargetFunctionOffset)); |
| 2264 __ Load(rcx, | 2394 __ Load(rcx, |
| 2265 ExternalReference(Builtins::kCall_ReceiverIsAny, masm->isolate())); | 2395 ExternalReference(Builtins::kCall_ReceiverIsAny, masm->isolate())); |
| 2266 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); | 2396 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); |
| 2267 __ jmp(rcx); | 2397 __ jmp(rcx); |
| 2268 } | 2398 } |
| 2269 | 2399 |
| 2270 | 2400 |
| 2271 // static | 2401 // static |
| 2272 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { | 2402 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode, |
| 2403 TailCallMode tail_call_mode) { | |
| 2273 // ----------- S t a t e ------------- | 2404 // ----------- S t a t e ------------- |
| 2274 // -- rax : the number of arguments (not including the receiver) | 2405 // -- rax : the number of arguments (not including the receiver) |
| 2275 // -- rdi : the target to call (can be any Object) | 2406 // -- rdi : the target to call (can be any Object) |
| 2276 // ----------------------------------- | 2407 // ----------------------------------- |
| 2277 StackArgumentsAccessor args(rsp, rax); | 2408 StackArgumentsAccessor args(rsp, rax); |
| 2278 | 2409 |
| 2279 Label non_callable, non_function, non_smi; | 2410 Label non_callable, non_function, non_smi; |
| 2280 __ JumpIfSmi(rdi, &non_callable); | 2411 __ JumpIfSmi(rdi, &non_callable); |
| 2281 __ bind(&non_smi); | 2412 __ bind(&non_smi); |
| 2282 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 2413 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
| 2283 __ j(equal, masm->isolate()->builtins()->CallFunction(mode), | 2414 __ j(equal, masm->isolate()->builtins()->CallFunction(mode, tail_call_mode), |
| 2284 RelocInfo::CODE_TARGET); | 2415 RelocInfo::CODE_TARGET); |
| 2285 __ CmpInstanceType(rcx, JS_BOUND_FUNCTION_TYPE); | 2416 __ CmpInstanceType(rcx, JS_BOUND_FUNCTION_TYPE); |
| 2286 __ j(equal, masm->isolate()->builtins()->CallBoundFunction(), | 2417 __ j(equal, masm->isolate()->builtins()->CallBoundFunction(tail_call_mode), |
| 2287 RelocInfo::CODE_TARGET); | 2418 RelocInfo::CODE_TARGET); |
| 2288 __ CmpInstanceType(rcx, JS_PROXY_TYPE); | 2419 __ CmpInstanceType(rcx, JS_PROXY_TYPE); |
| 2289 __ j(not_equal, &non_function); | 2420 __ j(not_equal, &non_function); |
| 2290 | 2421 |
| 2422 // 0. Prepare for tail call if necessary. | |
| 2423 if (tail_call_mode == TailCallMode::kAllow) { | |
| 2424 PrepareForTailCall(masm, rax, rbx, rcx, r8); | |
| 2425 } | |
| 2426 | |
| 2291 // 1. Runtime fallback for Proxy [[Call]]. | 2427 // 1. Runtime fallback for Proxy [[Call]]. |
| 2292 __ PopReturnAddressTo(kScratchRegister); | 2428 __ PopReturnAddressTo(kScratchRegister); |
| 2293 __ Push(rdi); | 2429 __ Push(rdi); |
| 2294 __ PushReturnAddressFrom(kScratchRegister); | 2430 __ PushReturnAddressFrom(kScratchRegister); |
| 2295 // Increase the arguments size to include the pushed function and the | 2431 // Increase the arguments size to include the pushed function and the |
| 2296 // existing receiver on the stack. | 2432 // existing receiver on the stack. |
| 2297 __ addp(rax, Immediate(2)); | 2433 __ addp(rax, Immediate(2)); |
| 2298 // Tail-call to the runtime. | 2434 // Tail-call to the runtime. |
| 2299 __ JumpToExternalReference( | 2435 __ JumpToExternalReference( |
| 2300 ExternalReference(Runtime::kJSProxyCall, masm->isolate())); | 2436 ExternalReference(Runtime::kJSProxyCall, masm->isolate())); |
| 2301 | 2437 |
| 2302 // 2. Call to something else, which might have a [[Call]] internal method (if | 2438 // 2. Call to something else, which might have a [[Call]] internal method (if |
| 2303 // not we raise an exception). | 2439 // not we raise an exception). |
| 2304 __ bind(&non_function); | 2440 __ bind(&non_function); |
| 2305 // Check if target has a [[Call]] internal method. | 2441 // Check if target has a [[Call]] internal method. |
| 2306 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), | 2442 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), |
| 2307 Immediate(1 << Map::kIsCallable)); | 2443 Immediate(1 << Map::kIsCallable)); |
| 2308 __ j(zero, &non_callable, Label::kNear); | 2444 __ j(zero, &non_callable, Label::kNear); |
| 2309 // Overwrite the original receiver with the (original) target. | 2445 // Overwrite the original receiver with the (original) target. |
| 2310 __ movp(args.GetReceiverOperand(), rdi); | 2446 __ movp(args.GetReceiverOperand(), rdi); |
| 2311 // Let the "call_as_function_delegate" take care of the rest. | 2447 // Let the "call_as_function_delegate" take care of the rest. |
| 2312 __ LoadNativeContextSlot(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, rdi); | 2448 __ LoadNativeContextSlot(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, rdi); |
| 2313 __ Jump(masm->isolate()->builtins()->CallFunction( | 2449 __ Jump(masm->isolate()->builtins()->CallFunction( |
| 2314 ConvertReceiverMode::kNotNullOrUndefined), | 2450 ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode), |
| 2315 RelocInfo::CODE_TARGET); | 2451 RelocInfo::CODE_TARGET); |
| 2316 | 2452 |
| 2317 // 3. Call to something that is not callable. | 2453 // 3. Call to something that is not callable. |
| 2318 __ bind(&non_callable); | 2454 __ bind(&non_callable); |
| 2319 { | 2455 { |
| 2320 FrameScope scope(masm, StackFrame::INTERNAL); | 2456 FrameScope scope(masm, StackFrame::INTERNAL); |
| 2321 __ Push(rdi); | 2457 __ Push(rdi); |
| 2322 __ CallRuntime(Runtime::kThrowCalledNonCallable); | 2458 __ CallRuntime(Runtime::kThrowCalledNonCallable); |
| 2323 } | 2459 } |
| 2324 } | 2460 } |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2615 __ ret(0); | 2751 __ ret(0); |
| 2616 } | 2752 } |
| 2617 | 2753 |
| 2618 | 2754 |
| 2619 #undef __ | 2755 #undef __ |
| 2620 | 2756 |
| 2621 } // namespace internal | 2757 } // namespace internal |
| 2622 } // namespace v8 | 2758 } // namespace v8 |
| 2623 | 2759 |
| 2624 #endif // V8_TARGET_ARCH_X64 | 2760 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |