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 2063 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2255 // No need for a write barrier here - cells are rescanned. | 2242 // No need for a write barrier here - cells are rescanned. |
2256 | 2243 |
2257 __ bind(&done); | 2244 __ bind(&done); |
2258 } | 2245 } |
2259 | 2246 |
2260 | 2247 |
2261 void CallFunctionStub::Generate(MacroAssembler* masm) { | 2248 void CallFunctionStub::Generate(MacroAssembler* masm) { |
2262 // rbx : cache cell for call target | 2249 // rbx : cache cell for call target |
2263 // rdi : the function to call | 2250 // rdi : the function to call |
2264 Isolate* isolate = masm->isolate(); | 2251 Isolate* isolate = masm->isolate(); |
2265 Label slow, non_function; | 2252 Label slow, non_function, wrap, cont; |
2266 StackArgumentsAccessor args(rsp, argc_); | 2253 StackArgumentsAccessor args(rsp, argc_); |
2267 | 2254 |
2268 // Check that the function really is a JavaScript function. | 2255 if (NeedsChecks()) { |
2269 __ JumpIfSmi(rdi, &non_function); | 2256 // Check that the function really is a JavaScript function. |
| 2257 __ JumpIfSmi(rdi, &non_function); |
2270 | 2258 |
2271 // Goto slow case if we do not have a function. | 2259 // Goto slow case if we do not have a function. |
2272 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 2260 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
2273 __ j(not_equal, &slow); | 2261 __ j(not_equal, &slow); |
2274 | 2262 |
2275 if (RecordCallTarget()) { | 2263 if (RecordCallTarget()) { |
2276 GenerateRecordCallTarget(masm); | 2264 GenerateRecordCallTarget(masm); |
| 2265 } |
2277 } | 2266 } |
2278 | 2267 |
2279 // Fast-case: Just invoke the function. | 2268 // Fast-case: Just invoke the function. |
2280 ParameterCount actual(argc_); | 2269 ParameterCount actual(argc_); |
2281 | 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 } |
2282 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); | 2300 __ InvokeFunction(rdi, actual, JUMP_FUNCTION, NullCallWrapper()); |
2283 | 2301 |
2284 // Slow-case: Non-function called. | 2302 if (NeedsChecks()) { |
2285 __ bind(&slow); | 2303 // Slow-case: Non-function called. |
2286 if (RecordCallTarget()) { | 2304 __ bind(&slow); |
2287 // If there is a call target cache, mark it megamorphic in the | 2305 if (RecordCallTarget()) { |
2288 // non-function case. MegamorphicSentinel is an immortal immovable | 2306 // If there is a call target cache, mark it megamorphic in the |
2289 // object (undefined) so no write barrier is needed. | 2307 // non-function case. MegamorphicSentinel is an immortal immovable |
2290 __ Move(FieldOperand(rbx, Cell::kValueOffset), | 2308 // object (undefined) so no write barrier is needed. |
2291 TypeFeedbackCells::MegamorphicSentinel(isolate)); | 2309 __ Move(FieldOperand(rbx, Cell::kValueOffset), |
2292 } | 2310 TypeFeedbackCells::MegamorphicSentinel(isolate)); |
2293 // Check for function proxy. | 2311 } |
2294 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); | 2312 // Check for function proxy. |
2295 __ j(not_equal, &non_function); | 2313 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); |
2296 __ PopReturnAddressTo(rcx); | 2314 __ j(not_equal, &non_function); |
2297 __ push(rdi); // put proxy as additional argument under return address | 2315 __ PopReturnAddressTo(rcx); |
2298 __ PushReturnAddressFrom(rcx); | 2316 __ push(rdi); // put proxy as additional argument under return address |
2299 __ Set(rax, argc_ + 1); | 2317 __ PushReturnAddressFrom(rcx); |
2300 __ Set(rbx, 0); | 2318 __ Set(rax, argc_ + 1); |
2301 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); | 2319 __ Set(rbx, 0); |
2302 { | 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); |
2303 Handle<Code> adaptor = | 2334 Handle<Code> adaptor = |
2304 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 2335 isolate->builtins()->ArgumentsAdaptorTrampoline(); |
2305 __ jmp(adaptor, RelocInfo::CODE_TARGET); | 2336 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
2306 } | 2337 } |
2307 | 2338 |
2308 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 2339 if (CallAsMethod()) { |
2309 // of the original receiver from the call site). | 2340 __ bind(&wrap); |
2310 __ bind(&non_function); | 2341 // Wrap the receiver and patch it back onto the stack. |
2311 __ movp(args.GetReceiverOperand(), rdi); | 2342 { FrameScope frame_scope(masm, StackFrame::INTERNAL); |
2312 __ Set(rax, argc_); | 2343 __ push(rdi); |
2313 __ Set(rbx, 0); | 2344 __ push(rax); |
2314 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); | 2345 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
2315 Handle<Code> adaptor = | 2346 __ pop(rdi); |
2316 isolate->builtins()->ArgumentsAdaptorTrampoline(); | 2347 } |
2317 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 2348 __ movp(Operand(rsp, (argc_ + 1) * kPointerSize), rax); |
| 2349 __ jmp(&cont); |
| 2350 } |
2318 } | 2351 } |
2319 | 2352 |
2320 | 2353 |
2321 void CallConstructStub::Generate(MacroAssembler* masm) { | 2354 void CallConstructStub::Generate(MacroAssembler* masm) { |
2322 // rax : number of arguments | 2355 // rax : number of arguments |
2323 // rbx : cache cell for call target | 2356 // rbx : cache cell for call target |
2324 // rdi : constructor function | 2357 // rdi : constructor function |
2325 Label slow, non_function_call; | 2358 Label slow, non_function_call; |
2326 | 2359 |
2327 // 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... |
4709 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 4742 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
4710 __ PopReturnAddressTo(rcx); | 4743 __ PopReturnAddressTo(rcx); |
4711 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE | 4744 int additional_offset = function_mode_ == JS_FUNCTION_STUB_MODE |
4712 ? kPointerSize | 4745 ? kPointerSize |
4713 : 0; | 4746 : 0; |
4714 __ lea(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset)); | 4747 __ lea(rsp, MemOperand(rsp, rbx, times_pointer_size, additional_offset)); |
4715 __ jmp(rcx); // Return to IC Miss stub, continuation still on stack. | 4748 __ jmp(rcx); // Return to IC Miss stub, continuation still on stack. |
4716 } | 4749 } |
4717 | 4750 |
4718 | 4751 |
4719 void StubFailureTailCallTrampolineStub::Generate(MacroAssembler* masm) { | |
4720 CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs); | |
4721 __ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET); | |
4722 __ movp(rdi, rax); | |
4723 int parameter_count_offset = | |
4724 StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset; | |
4725 __ movp(rax, MemOperand(rbp, parameter_count_offset)); | |
4726 // The parameter count above includes the receiver for the arguments passed to | |
4727 // the deoptimization handler. Subtract the receiver for the parameter count | |
4728 // for the call. | |
4729 __ subl(rax, Immediate(1)); | |
4730 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | |
4731 ParameterCount argument_count(rax); | |
4732 __ InvokeFunction(rdi, argument_count, JUMP_FUNCTION, NullCallWrapper()); | |
4733 } | |
4734 | |
4735 | |
4736 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 4752 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
4737 if (masm->isolate()->function_entry_hook() != NULL) { | 4753 if (masm->isolate()->function_entry_hook() != NULL) { |
4738 ProfileEntryHookStub stub; | 4754 ProfileEntryHookStub stub; |
4739 masm->CallStub(&stub); | 4755 masm->CallStub(&stub); |
4740 } | 4756 } |
4741 } | 4757 } |
4742 | 4758 |
4743 | 4759 |
4744 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { | 4760 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { |
4745 // 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 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5278 return_value_operand, | 5294 return_value_operand, |
5279 NULL); | 5295 NULL); |
5280 } | 5296 } |
5281 | 5297 |
5282 | 5298 |
5283 #undef __ | 5299 #undef __ |
5284 | 5300 |
5285 } } // namespace v8::internal | 5301 } } // namespace v8::internal |
5286 | 5302 |
5287 #endif // V8_TARGET_ARCH_X64 | 5303 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |