OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 void KeyedLoadFieldStub::InitializeInterfaceDescriptor( | 159 void KeyedLoadFieldStub::InitializeInterfaceDescriptor( |
160 Isolate* isolate, | 160 Isolate* isolate, |
161 CodeStubInterfaceDescriptor* descriptor) { | 161 CodeStubInterfaceDescriptor* descriptor) { |
162 static Register registers[] = { rdx }; | 162 static Register registers[] = { rdx }; |
163 descriptor->register_param_count_ = 1; | 163 descriptor->register_param_count_ = 1; |
164 descriptor->register_params_ = registers; | 164 descriptor->register_params_ = registers; |
165 descriptor->deoptimization_handler_ = NULL; | 165 descriptor->deoptimization_handler_ = NULL; |
166 } | 166 } |
167 | 167 |
168 | 168 |
169 void KeyedArrayCallStub::InitializeInterfaceDescriptor( | |
170 Isolate* isolate, | |
171 CodeStubInterfaceDescriptor* descriptor) { | |
172 static Register registers[] = { rcx }; | |
173 descriptor->register_param_count_ = 1; | |
174 descriptor->register_params_ = registers; | |
175 descriptor->continuation_type_ = TAIL_CALL_CONTINUATION; | |
176 descriptor->handler_arguments_mode_ = PASS_ARGUMENTS; | |
177 descriptor->deoptimization_handler_ = | |
178 FUNCTION_ADDR(KeyedCallIC_MissFromStubFailure); | |
179 } | |
180 | |
181 | |
182 void KeyedStoreFastElementStub::InitializeInterfaceDescriptor( | 169 void KeyedStoreFastElementStub::InitializeInterfaceDescriptor( |
183 Isolate* isolate, | 170 Isolate* isolate, |
184 CodeStubInterfaceDescriptor* descriptor) { | 171 CodeStubInterfaceDescriptor* descriptor) { |
185 static Register registers[] = { rdx, rcx, rax }; | 172 static Register registers[] = { rdx, rcx, rax }; |
186 descriptor->register_param_count_ = 3; | 173 descriptor->register_param_count_ = 3; |
187 descriptor->register_params_ = registers; | 174 descriptor->register_params_ = registers; |
188 descriptor->deoptimization_handler_ = | 175 descriptor->deoptimization_handler_ = |
189 FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure); | 176 FUNCTION_ADDR(KeyedStoreIC_MissFromStubFailure); |
190 } | 177 } |
191 | 178 |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 rdx, // receiver | 423 rdx, // receiver |
437 }; | 424 }; |
438 static Representation representations[] = { | 425 static Representation representations[] = { |
439 Representation::Tagged(), // context | 426 Representation::Tagged(), // context |
440 Representation::Tagged(), // receiver | 427 Representation::Tagged(), // receiver |
441 }; | 428 }; |
442 descriptor->register_param_count_ = 2; | 429 descriptor->register_param_count_ = 2; |
443 descriptor->register_params_ = registers; | 430 descriptor->register_params_ = registers; |
444 descriptor->param_representations_ = representations; | 431 descriptor->param_representations_ = representations; |
445 } | 432 } |
| 433 { |
| 434 CallInterfaceDescriptor* descriptor = |
| 435 isolate->call_descriptor(Isolate::ApiFunctionCall); |
| 436 static Register registers[] = { rax, // callee |
| 437 rbx, // call_data |
| 438 rcx, // holder |
| 439 rdx, // api_function_address |
| 440 rsi, // context |
| 441 }; |
| 442 static Representation representations[] = { |
| 443 Representation::Tagged(), // callee |
| 444 Representation::Tagged(), // call_data |
| 445 Representation::Tagged(), // holder |
| 446 Representation::External(), // api_function_address |
| 447 Representation::Tagged(), // context |
| 448 }; |
| 449 descriptor->register_param_count_ = 5; |
| 450 descriptor->register_params_ = registers; |
| 451 descriptor->param_representations_ = representations; |
| 452 } |
446 } | 453 } |
447 | 454 |
448 | 455 |
449 #define __ ACCESS_MASM(masm) | 456 #define __ ACCESS_MASM(masm) |
450 | 457 |
451 | 458 |
452 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { | 459 void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) { |
453 // Update the static counter each time a new code stub is generated. | 460 // Update the static counter each time a new code stub is generated. |
454 Isolate* isolate = masm->isolate(); | 461 Isolate* isolate = masm->isolate(); |
455 isolate->counters()->code_stubs()->Increment(); | 462 isolate->counters()->code_stubs()->Increment(); |
(...skipping 1779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2235 // No need for a write barrier here - cells are rescanned. | 2242 // No need for a write barrier here - cells are rescanned. |
2236 | 2243 |
2237 __ bind(&done); | 2244 __ bind(&done); |
2238 } | 2245 } |
2239 | 2246 |
2240 | 2247 |
2241 void CallFunctionStub::Generate(MacroAssembler* masm) { | 2248 void CallFunctionStub::Generate(MacroAssembler* masm) { |
2242 // rbx : cache cell for call target | 2249 // rbx : cache cell for call target |
2243 // rdi : the function to call | 2250 // rdi : the function to call |
2244 Isolate* isolate = masm->isolate(); | 2251 Isolate* isolate = masm->isolate(); |
2245 Label slow, non_function; | 2252 Label slow, non_function, wrap, cont; |
2246 StackArgumentsAccessor args(rsp, argc_); | 2253 StackArgumentsAccessor args(rsp, argc_); |
2247 | 2254 |
2248 // Check that the function really is a JavaScript function. | 2255 if (NeedsChecks()) { |
2249 __ JumpIfSmi(rdi, &non_function); | 2256 // Check that the function really is a JavaScript function. |
| 2257 __ JumpIfSmi(rdi, &non_function); |
2250 | 2258 |
2251 // Goto slow case if we do not have a function. | 2259 // Goto slow case if we do not have a function. |
2252 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 2260 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
2253 __ j(not_equal, &slow); | 2261 __ j(not_equal, &slow); |
2254 | 2262 |
2255 if (RecordCallTarget()) { | 2263 if (RecordCallTarget()) { |
2256 GenerateRecordCallTarget(masm); | 2264 GenerateRecordCallTarget(masm); |
| 2265 } |
2257 } | 2266 } |
2258 | 2267 |
2259 // Fast-case: Just invoke the function. | 2268 // Fast-case: Just invoke the function. |
2260 ParameterCount actual(argc_); | 2269 ParameterCount actual(argc_); |
2261 | 2270 |
| 2271 if (CallAsMethod()) { |
| 2272 if (NeedsChecks()) { |
| 2273 // Do not transform the receiver for strict mode functions. |
| 2274 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
| 2275 __ testb(FieldOperand(rcx, SharedFunctionInfo::kStrictModeByteOffset), |
| 2276 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte)); |
| 2277 __ j(not_equal, &cont); |
| 2278 |
| 2279 // Do not transform the receiver for natives. |
| 2280 // SharedFunctionInfo is already loaded into rcx. |
| 2281 __ testb(FieldOperand(rcx, SharedFunctionInfo::kNativeByteOffset), |
| 2282 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); |
| 2283 __ j(not_equal, &cont); |
| 2284 } |
| 2285 |
| 2286 // Load the receiver from the stack. |
| 2287 __ movp(rax, Operand(rsp, (argc_ + 1) * kPointerSize)); |
| 2288 |
| 2289 if (NeedsChecks()) { |
| 2290 __ JumpIfSmi(rax, &wrap); |
| 2291 |
| 2292 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); |
| 2293 __ j(below, &wrap); |
| 2294 } else { |
| 2295 __ jmp(&wrap); |
| 2296 } |
| 2297 |
| 2298 __ bind(&cont); |
| 2299 } |
2262 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); | 2300 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); |
2263 | 2301 |
2264 // Slow-case: Non-function called. | 2302 if (NeedsChecks()) { |
2265 __ bind(&slow); | 2303 // Slow-case: Non-function called. |
2266 if (RecordCallTarget()) { | 2304 __ bind(&slow); |
2267 // If there is a call target cache, mark it megamorphic in the | 2305 if (RecordCallTarget()) { |
2268 // non-function case. MegamorphicSentinel is an immortal immovable | 2306 // If there is a call target cache, mark it megamorphic in the |
2269 // object (undefined) so no write barrier is needed. | 2307 // non-function case. MegamorphicSentinel is an immortal immovable |
2270 __ Move(FieldOperand(rbx, Cell::kValueOffset), | 2308 // object (undefined) so no write barrier is needed. |
2271 TypeFeedbackCells::MegamorphicSentinel(isolate)); | 2309 __ Move(FieldOperand(rbx, Cell::kValueOffset), |
2272 } | 2310 TypeFeedbackCells::MegamorphicSentinel(isolate)); |
2273 // Check for function proxy. | 2311 } |
2274 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); | 2312 // Check for function proxy. |
2275 __ j(not_equal, &non_function); | 2313 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); |
2276 __ PopReturnAddressTo(rcx); | 2314 __ j(not_equal, &non_function); |
2277 __ push(rdi); // put proxy as additional argument under return address | 2315 __ PopReturnAddressTo(rcx); |
2278 __ PushReturnAddressFrom(rcx); | 2316 __ push(rdi); // put proxy as additional argument under return address |
2279 __ Set(rax, argc_ + 1); | 2317 __ PushReturnAddressFrom(rcx); |
2280 __ Set(rbx, 0); | 2318 __ Set(rax, argc_ + 1); |
2281 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); | 2319 __ Set(rbx, 0); |
2282 { | 2320 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); |
| 2321 { |
| 2322 Handle<Code> adaptor = |
| 2323 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
| 2324 __ jmp(adaptor, RelocInfo::CODE_TARGET); |
| 2325 } |
| 2326 |
| 2327 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
| 2328 // of the original receiver from the call site). |
| 2329 __ bind(&non_function); |
| 2330 __ movp(args.GetReceiverOperand(), rdi); |
| 2331 __ Set(rax, argc_); |
| 2332 __ Set(rbx, 0); |
| 2333 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); |
2283 Handle<Code> adaptor = | 2334 Handle<Code> adaptor = |
2284 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 2335 isolate->builtins()->ArgumentsAdaptorTrampoline(); |
2285 __ jmp(adaptor, RelocInfo::CODE_TARGET); | 2336 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
2286 } | 2337 } |
2287 | 2338 |
2288 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 2339 if (CallAsMethod()) { |
2289 // of the original receiver from the call site). | 2340 __ bind(&wrap); |
2290 __ bind(&non_function); | 2341 // Wrap the receiver and patch it back onto the stack. |
2291 __ movp(args.GetReceiverOperand(), rdi); | 2342 { FrameScope frame_scope(masm, StackFrame::INTERNAL); |
2292 __ Set(rax, argc_); | 2343 __ push(rdi); |
2293 __ Set(rbx, 0); | 2344 __ push(rax); |
2294 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); | 2345 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
2295 Handle<Code> adaptor = | 2346 __ pop(rdi); |
2296 isolate->builtins()->ArgumentsAdaptorTrampoline(); | 2347 } |
2297 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 2348 __ movp(Operand(rsp, (argc_ + 1) * kPointerSize), rax); |
| 2349 __ jmp(&cont); |
| 2350 } |
2298 } | 2351 } |
2299 | 2352 |
2300 | 2353 |
2301 void CallConstructStub::Generate(MacroAssembler* masm) { | 2354 void CallConstructStub::Generate(MacroAssembler* masm) { |
2302 // rax : number of arguments | 2355 // rax : number of arguments |
2303 // rbx : cache cell for call target | 2356 // rbx : cache cell for call target |
2304 // rdi : constructor function | 2357 // rdi : constructor function |
2305 Label slow, non_function_call; | 2358 Label slow, non_function_call; |
2306 | 2359 |
2307 // Check that function is not a smi. | 2360 // Check that function is not a smi. |
(...skipping 2381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4689 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 4742 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
4690 __ PopReturnAddressTo(rcx); | 4743 __ PopReturnAddressTo(rcx); |
4691 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE | 4744 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE |
4692 ? kPointerSize | 4745 ? kPointerSize |
4693 : 0; | 4746 : 0; |
4694 __ lea(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset)); | 4747 __ lea(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset)); |
4695 __ jmp(rcx); // Return to IC Miss stub, continuation still on stack. | 4748 __ jmp(rcx); // Return to IC Miss stub, continuation still on stack. |
4696 } | 4749 } |
4697 | 4750 |
4698 | 4751 |
4699 void StubFailureTailCallTrampolineStub::Generate(MacroAssembler* masm) { | |
4700 CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs); | |
4701 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
4702 __ movp(rdi, rax); | |
4703 int parameter_count_offset = | |
4704 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; | |
4705 __ movp(rax, MemOperand(rbp, parameter_count_offset)); | |
4706 // The parameter count above includes the receiver for the arguments passed to | |
4707 // the deoptimization handler. Subtract the receiver for the parameter count | |
4708 // for the call. | |
4709 __ subl(rax, Immediate(1)); | |
4710 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | |
4711 ParameterCount argument_count(rax); | |
4712 __ InvokeFunction(rdi, argument_count, JUMP_FUNCTION, NullCallWrapper()); | |
4713 } | |
4714 | |
4715 | |
4716 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 4752 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
4717 if (masm->isolate()->function_entry_hook() != NULL) { | 4753 if (masm->isolate()->function_entry_hook() != NULL) { |
4718 ProfileEntryHookStub stub; | 4754 ProfileEntryHookStub stub; |
4719 masm->CallStub(&stub); | 4755 masm->CallStub(&stub); |
4720 } | 4756 } |
4721 } | 4757 } |
4722 | 4758 |
4723 | 4759 |
4724 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { | 4760 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { |
4725 // This stub can be called from essentially anywhere, so it needs to save | 4761 // This stub can be called from essentially anywhere, so it needs to save |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5193 __ CallApiFunctionAndReturn( | 5229 __ CallApiFunctionAndReturn( |
5194 api_function_address, | 5230 api_function_address, |
5195 thunk_address, | 5231 thunk_address, |
5196 callback_arg, | 5232 callback_arg, |
5197 argc + FCA::kArgsLength + 1, | 5233 argc + FCA::kArgsLength + 1, |
5198 return_value_operand, | 5234 return_value_operand, |
5199 restore_context ? &context_restore_operand : NULL); | 5235 restore_context ? &context_restore_operand : NULL); |
5200 } | 5236 } |
5201 | 5237 |
5202 | 5238 |
| 5239 void CallApiGetterStub::Generate(MacroAssembler* masm) { |
| 5240 // ----------- S t a t e ------------- |
| 5241 // -- rsp[0] : return address |
| 5242 // -- rsp[8] : name |
| 5243 // -- rsp[16 - kArgsLength*8] : PropertyCallbackArguments object |
| 5244 // -- ... |
| 5245 // -- r8 : api_function_address |
| 5246 // ----------------------------------- |
| 5247 |
| 5248 #if defined(__MINGW64__) || defined(_WIN64) |
| 5249 Register getter_arg = r8; |
| 5250 Register accessor_info_arg = rdx; |
| 5251 Register name_arg = rcx; |
| 5252 #else |
| 5253 Register getter_arg = rdx; |
| 5254 Register accessor_info_arg = rsi; |
| 5255 Register name_arg = rdi; |
| 5256 #endif |
| 5257 Register api_function_address = r8; |
| 5258 Register scratch = rax; |
| 5259 |
| 5260 // v8::Arguments::values_ and handler for name. |
| 5261 const int kStackSpace = PropertyCallbackArguments::kArgsLength + 1; |
| 5262 |
| 5263 // Allocate v8::AccessorInfo in non-GCed stack space. |
| 5264 const int kArgStackSpace = 1; |
| 5265 |
| 5266 __ lea(name_arg, Operand(rsp, 1 * kPointerSize)); |
| 5267 |
| 5268 __ PrepareCallApiFunction(kArgStackSpace); |
| 5269 __ lea(scratch, Operand(name_arg, 1 * kPointerSize)); |
| 5270 |
| 5271 // v8::PropertyAccessorInfo::args_. |
| 5272 __ movp(StackSpaceOperand(0), scratch); |
| 5273 |
| 5274 // The context register (rsi) has been saved in PrepareCallApiFunction and |
| 5275 // could be used to pass arguments. |
| 5276 __ lea(accessor_info_arg, StackSpaceOperand(0)); |
| 5277 |
| 5278 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); |
| 5279 |
| 5280 // It's okay if api_function_address == getter_arg |
| 5281 // but not accessor_info_arg or name_arg |
| 5282 ASSERT(!api_function_address.is(accessor_info_arg) && |
| 5283 !api_function_address.is(name_arg)); |
| 5284 |
| 5285 // The name handler is counted as an argument. |
| 5286 StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength); |
| 5287 Operand return_value_operand = args.GetArgumentOperand( |
| 5288 PropertyCallbackArguments::kArgsLength - 1 - |
| 5289 PropertyCallbackArguments::kReturnValueOffset); |
| 5290 __ CallApiFunctionAndReturn(api_function_address, |
| 5291 thunk_address, |
| 5292 getter_arg, |
| 5293 kStackSpace, |
| 5294 return_value_operand, |
| 5295 NULL); |
| 5296 } |
| 5297 |
| 5298 |
5203 #undef __ | 5299 #undef __ |
5204 | 5300 |
5205 } } // namespace v8::internal | 5301 } } // namespace v8::internal |
5206 | 5302 |
5207 #endif // V8_TARGET_ARCH_X64 | 5303 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |