| 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 |