OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 3564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3575 __ testb(scratch, Immediate(kIsSymbolMask)); | 3575 __ testb(scratch, Immediate(kIsSymbolMask)); |
3576 __ j(zero, label); | 3576 __ j(zero, label); |
3577 } | 3577 } |
3578 | 3578 |
3579 | 3579 |
3580 void StackCheckStub::Generate(MacroAssembler* masm) { | 3580 void StackCheckStub::Generate(MacroAssembler* masm) { |
3581 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); | 3581 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); |
3582 } | 3582 } |
3583 | 3583 |
3584 | 3584 |
3585 void CallFunctionStub::FinishCode(Handle<Code> code) { | 3585 static void GenerateRecordCallTarget(MacroAssembler* masm) { |
3586 code->set_has_function_cache(false); | 3586 // Cache the called function in a global property cell. Cache states |
3587 } | 3587 // are uninitialized, monomorphic (indicated by a JSFunction), and |
| 3588 // megamorphic. |
| 3589 // rbx : cache cell for call target |
| 3590 // rdi : the function to call |
| 3591 Isolate* isolate = masm->isolate(); |
| 3592 Label initialize, done; |
3588 | 3593 |
| 3594 // Load the cache state into rcx. |
| 3595 __ movq(rcx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); |
3589 | 3596 |
3590 void CallFunctionStub::Clear(Heap* heap, Address address) { | 3597 // A monomorphic cache hit or an already megamorphic state: invoke the |
3591 UNREACHABLE(); | 3598 // function without changing the state. |
3592 } | 3599 __ cmpq(rcx, rdi); |
| 3600 __ j(equal, &done, Label::kNear); |
| 3601 __ Cmp(rcx, TypeFeedbackCells::MegamorphicSentinel(isolate)); |
| 3602 __ j(equal, &done, Label::kNear); |
3593 | 3603 |
| 3604 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
| 3605 // megamorphic. |
| 3606 __ Cmp(rcx, TypeFeedbackCells::UninitializedSentinel(isolate)); |
| 3607 __ j(equal, &initialize, Label::kNear); |
| 3608 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
| 3609 // write-barrier is needed. |
| 3610 __ Move(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), |
| 3611 TypeFeedbackCells::MegamorphicSentinel(isolate)); |
| 3612 __ jmp(&done, Label::kNear); |
3594 | 3613 |
3595 Object* CallFunctionStub::GetCachedValue(Address address) { | 3614 // An uninitialized cache is patched with the function. |
3596 UNREACHABLE(); | 3615 __ bind(&initialize); |
3597 return NULL; | 3616 __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rdi); |
| 3617 // No need for a write barrier here - cells are rescanned. |
| 3618 |
| 3619 __ bind(&done); |
3598 } | 3620 } |
3599 | 3621 |
3600 | 3622 |
3601 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3623 void CallFunctionStub::Generate(MacroAssembler* masm) { |
3602 // rdi : the function to call | 3624 // rdi : the function to call |
| 3625 // rbx : cache cell for call target |
3603 Label slow, non_function; | 3626 Label slow, non_function; |
3604 | 3627 |
3605 // The receiver might implicitly be the global object. This is | 3628 // The receiver might implicitly be the global object. This is |
3606 // indicated by passing the hole as the receiver to the call | 3629 // indicated by passing the hole as the receiver to the call |
3607 // function stub. | 3630 // function stub. |
3608 if (ReceiverMightBeImplicit()) { | 3631 if (ReceiverMightBeImplicit()) { |
3609 Label call; | 3632 Label call; |
3610 // Get the receiver from the stack. | 3633 // Get the receiver from the stack. |
3611 // +1 ~ return address | 3634 // +1 ~ return address |
3612 __ movq(rax, Operand(rsp, (argc_ + 1) * kPointerSize)); | 3635 __ movq(rax, Operand(rsp, (argc_ + 1) * kPointerSize)); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3671 __ Set(rax, argc_); | 3694 __ Set(rax, argc_); |
3672 __ Set(rbx, 0); | 3695 __ Set(rbx, 0); |
3673 __ SetCallKind(rcx, CALL_AS_METHOD); | 3696 __ SetCallKind(rcx, CALL_AS_METHOD); |
3674 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); | 3697 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); |
3675 Handle<Code> adaptor = | 3698 Handle<Code> adaptor = |
3676 Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline(); | 3699 Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline(); |
3677 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 3700 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
3678 } | 3701 } |
3679 | 3702 |
3680 | 3703 |
| 3704 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 3705 // rax : number of arguments |
| 3706 // rbx : cache cell for call target |
| 3707 // rdi : constructor function |
| 3708 Label slow, non_function_call; |
| 3709 |
| 3710 // Check that function is not a smi. |
| 3711 __ JumpIfSmi(rdi, &non_function_call); |
| 3712 // Check that function is a JSFunction. |
| 3713 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
| 3714 __ j(not_equal, &slow); |
| 3715 |
| 3716 if (RecordCallTarget()) { |
| 3717 GenerateRecordCallTarget(masm); |
| 3718 } |
| 3719 |
| 3720 // Jump to the function-specific construct stub. |
| 3721 __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
| 3722 __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kConstructStubOffset)); |
| 3723 __ lea(rbx, FieldOperand(rbx, Code::kHeaderSize)); |
| 3724 __ jmp(rbx); |
| 3725 |
| 3726 // rdi: called object |
| 3727 // rax: number of arguments |
| 3728 // rcx: object map |
| 3729 Label do_call; |
| 3730 __ bind(&slow); |
| 3731 __ CmpInstanceType(rcx, JS_FUNCTION_PROXY_TYPE); |
| 3732 __ j(not_equal, &non_function_call); |
| 3733 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); |
| 3734 __ jmp(&do_call); |
| 3735 |
| 3736 __ bind(&non_function_call); |
| 3737 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); |
| 3738 __ bind(&do_call); |
| 3739 // Set expected number of arguments to zero (not changing rax). |
| 3740 __ Set(rbx, 0); |
| 3741 __ SetCallKind(rcx, CALL_AS_METHOD); |
| 3742 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 3743 RelocInfo::CODE_TARGET); |
| 3744 } |
| 3745 |
| 3746 |
3681 bool CEntryStub::NeedsImmovableCode() { | 3747 bool CEntryStub::NeedsImmovableCode() { |
3682 return false; | 3748 return false; |
3683 } | 3749 } |
3684 | 3750 |
3685 | 3751 |
3686 bool CEntryStub::IsPregenerated() { | 3752 bool CEntryStub::IsPregenerated() { |
3687 #ifdef _WIN64 | 3753 #ifdef _WIN64 |
3688 return result_size_ == 1; | 3754 return result_size_ == 1; |
3689 #else | 3755 #else |
3690 return true; | 3756 return true; |
(...skipping 2544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6235 xmm0, | 6301 xmm0, |
6236 &slow_elements); | 6302 &slow_elements); |
6237 __ ret(0); | 6303 __ ret(0); |
6238 } | 6304 } |
6239 | 6305 |
6240 #undef __ | 6306 #undef __ |
6241 | 6307 |
6242 } } // namespace v8::internal | 6308 } } // namespace v8::internal |
6243 | 6309 |
6244 #endif // V8_TARGET_ARCH_X64 | 6310 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |