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 2589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2600 DO_SMI_CHECK); | 2600 DO_SMI_CHECK); |
2601 | 2601 |
2602 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2602 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
2603 __ jmp(ic, RelocInfo::CODE_TARGET); | 2603 __ jmp(ic, RelocInfo::CODE_TARGET); |
2604 | 2604 |
2605 // Return the generated code. | 2605 // Return the generated code. |
2606 return GetCode(NORMAL, NULL); | 2606 return GetCode(NORMAL, NULL); |
2607 } | 2607 } |
2608 | 2608 |
2609 | 2609 |
| 2610 MaybeObject* KeyedStoreStubCompiler::CompileStoreElementWithTransition( |
| 2611 Map* transitioned_map, |
| 2612 Map* untransitioned_map_1, |
| 2613 Map* untransitioned_map_2) { |
| 2614 // ----------- S t a t e ------------- |
| 2615 // -- rax : value |
| 2616 // -- rcx : key |
| 2617 // -- rdx : receiver |
| 2618 // -- rsp[0] : return address |
| 2619 // ----------------------------------- |
| 2620 |
| 2621 // The order of map occurrences in the generated code below is important. |
| 2622 // Both IC code and Crankshaft rely on |transitioned_map| being the first |
| 2623 // map in the stub. |
| 2624 |
| 2625 Code* notransition_stub; |
| 2626 ElementsKind elements_kind = transitioned_map->elements_kind(); |
| 2627 bool is_js_array = transitioned_map->instance_type() == JS_ARRAY_TYPE; |
| 2628 MaybeObject* maybe_stub = |
| 2629 KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode(); |
| 2630 if (!maybe_stub->To(¬ransition_stub)) return maybe_stub; |
| 2631 |
| 2632 Label just_store, miss; |
| 2633 __ JumpIfSmi(rdx, &miss, Label::kNear); |
| 2634 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); |
| 2635 // rbx: receiver->map(). |
| 2636 __ Cmp(rbx, Handle<Map>(transitioned_map)); |
| 2637 __ j(equal, &just_store); |
| 2638 ASSERT_NE(untransitioned_map_1, NULL); |
| 2639 __ Cmp(rbx, Handle<Map>(untransitioned_map_1)); |
| 2640 Code* generic_stub = (strict_mode_ == kStrictMode) |
| 2641 ? isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic_Strict) |
| 2642 : isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic); |
| 2643 __ j(equal, Handle<Code>(generic_stub), RelocInfo::CODE_TARGET); |
| 2644 if (untransitioned_map_2 != NULL) { |
| 2645 __ Cmp(rbx, Handle<Map>(untransitioned_map_2)); |
| 2646 __ j(equal, Handle<Code>(generic_stub), RelocInfo::CODE_TARGET); |
| 2647 } |
| 2648 __ bind(&miss); |
| 2649 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2650 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2651 |
| 2652 __ bind(&just_store); |
| 2653 __ jmp(Handle<Code>(notransition_stub), RelocInfo::CODE_TARGET); |
| 2654 |
| 2655 // Return the generated code. |
| 2656 return GetCode(NORMAL, NULL, MEGAMORPHIC); |
| 2657 } |
| 2658 |
| 2659 |
2610 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic( | 2660 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic( |
2611 MapList* receiver_maps, | 2661 MapList* receiver_maps, |
2612 CodeList* handler_ics) { | 2662 CodeList* handler_ics) { |
2613 // ----------- S t a t e ------------- | 2663 // ----------- S t a t e ------------- |
2614 // -- rax : value | 2664 // -- rax : value |
2615 // -- rcx : key | 2665 // -- rcx : key |
2616 // -- rdx : receiver | 2666 // -- rdx : receiver |
2617 // -- rsp[0] : return address | 2667 // -- rsp[0] : return address |
2618 // ----------------------------------- | 2668 // ----------------------------------- |
2619 Label miss; | 2669 Label miss; |
(...skipping 1071 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3691 void KeyedStoreStubCompiler::GenerateStoreFastElement( | 3741 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
3692 MacroAssembler* masm, | 3742 MacroAssembler* masm, |
3693 bool is_js_array, | 3743 bool is_js_array, |
3694 ElementsKind elements_kind) { | 3744 ElementsKind elements_kind) { |
3695 // ----------- S t a t e ------------- | 3745 // ----------- S t a t e ------------- |
3696 // -- rax : value | 3746 // -- rax : value |
3697 // -- rcx : key | 3747 // -- rcx : key |
3698 // -- rdx : receiver | 3748 // -- rdx : receiver |
3699 // -- rsp[0] : return address | 3749 // -- rsp[0] : return address |
3700 // ----------------------------------- | 3750 // ----------------------------------- |
3701 Label miss_force_generic; | 3751 Label miss_force_generic, transition_elements_kind; |
3702 | 3752 |
3703 // This stub is meant to be tail-jumped to, the receiver must already | 3753 // This stub is meant to be tail-jumped to, the receiver must already |
3704 // have been verified by the caller to not be a smi. | 3754 // have been verified by the caller to not be a smi. |
3705 | 3755 |
3706 // Check that the key is a smi. | 3756 // Check that the key is a smi. |
3707 __ JumpIfNotSmi(rcx, &miss_force_generic); | 3757 __ JumpIfNotSmi(rcx, &miss_force_generic); |
3708 | 3758 |
3709 // Get the elements array and make sure it is a fast element array, not 'cow'. | 3759 // Get the elements array and make sure it is a fast element array, not 'cow'. |
3710 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); | 3760 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); |
3711 __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset), | 3761 __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset), |
3712 Heap::kFixedArrayMapRootIndex); | 3762 Heap::kFixedArrayMapRootIndex); |
3713 __ j(not_equal, &miss_force_generic); | 3763 __ j(not_equal, &miss_force_generic); |
3714 | 3764 |
3715 // Check that the key is within bounds. | 3765 // Check that the key is within bounds. |
3716 if (is_js_array) { | 3766 if (is_js_array) { |
3717 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); | 3767 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); |
3718 __ j(above_equal, &miss_force_generic); | 3768 __ j(above_equal, &miss_force_generic); |
3719 } else { | 3769 } else { |
3720 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); | 3770 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); |
3721 __ j(above_equal, &miss_force_generic); | 3771 __ j(above_equal, &miss_force_generic); |
3722 } | 3772 } |
3723 | 3773 |
3724 // Do the store and update the write barrier. | |
3725 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { | 3774 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
3726 __ JumpIfNotSmi(rax, &miss_force_generic); | 3775 __ JumpIfNotSmi(rax, &transition_elements_kind); |
3727 __ SmiToInteger32(rcx, rcx); | 3776 __ SmiToInteger32(rcx, rcx); |
3728 __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize), | 3777 __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize), |
3729 rax); | 3778 rax); |
3730 } else { | 3779 } else { |
| 3780 // Do the store and update the write barrier. |
3731 ASSERT(elements_kind == FAST_ELEMENTS); | 3781 ASSERT(elements_kind == FAST_ELEMENTS); |
3732 __ SmiToInteger32(rcx, rcx); | 3782 __ SmiToInteger32(rcx, rcx); |
3733 __ lea(rcx, | 3783 __ lea(rcx, |
3734 FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize)); | 3784 FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize)); |
3735 __ movq(Operand(rcx, 0), rax); | 3785 __ movq(Operand(rcx, 0), rax); |
3736 // Make sure to preserve the value in register rax. | 3786 // Make sure to preserve the value in register rax. |
3737 __ movq(rdx, rax); | 3787 __ movq(rdx, rax); |
3738 __ RecordWrite(rdi, rcx, rdx, kDontSaveFPRegs); | 3788 __ RecordWrite(rdi, rcx, rdx, kDontSaveFPRegs); |
3739 } | 3789 } |
3740 | 3790 |
3741 // Done. | 3791 // Done. |
3742 __ ret(0); | 3792 __ ret(0); |
3743 | 3793 |
3744 // Handle store cache miss. | 3794 // Handle store cache miss. |
3745 __ bind(&miss_force_generic); | 3795 __ bind(&miss_force_generic); |
3746 Handle<Code> ic_force_generic = | 3796 Handle<Code> ic_force_generic = |
3747 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3797 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3748 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | 3798 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
| 3799 |
| 3800 __ bind(&transition_elements_kind); |
| 3801 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3802 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
3749 } | 3803 } |
3750 | 3804 |
3751 | 3805 |
3752 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( | 3806 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( |
3753 MacroAssembler* masm, | 3807 MacroAssembler* masm, |
3754 bool is_js_array) { | 3808 bool is_js_array) { |
3755 // ----------- S t a t e ------------- | 3809 // ----------- S t a t e ------------- |
3756 // -- rax : value | 3810 // -- rax : value |
3757 // -- rcx : key | 3811 // -- rcx : key |
3758 // -- rdx : receiver | 3812 // -- rdx : receiver |
3759 // -- rsp[0] : return address | 3813 // -- rsp[0] : return address |
3760 // ----------------------------------- | 3814 // ----------------------------------- |
3761 Label miss_force_generic; | 3815 Label miss_force_generic, transition_elements_kind; |
3762 | 3816 |
3763 // This stub is meant to be tail-jumped to, the receiver must already | 3817 // This stub is meant to be tail-jumped to, the receiver must already |
3764 // have been verified by the caller to not be a smi. | 3818 // have been verified by the caller to not be a smi. |
3765 | 3819 |
3766 // Check that the key is a smi. | 3820 // Check that the key is a smi. |
3767 __ JumpIfNotSmi(rcx, &miss_force_generic); | 3821 __ JumpIfNotSmi(rcx, &miss_force_generic); |
3768 | 3822 |
3769 // Get the elements array. | 3823 // Get the elements array. |
3770 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); | 3824 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); |
3771 __ AssertFastElements(rdi); | 3825 __ AssertFastElements(rdi); |
3772 | 3826 |
3773 // Check that the key is within bounds. | 3827 // Check that the key is within bounds. |
3774 if (is_js_array) { | 3828 if (is_js_array) { |
3775 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); | 3829 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); |
3776 } else { | 3830 } else { |
3777 __ SmiCompare(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset)); | 3831 __ SmiCompare(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset)); |
3778 } | 3832 } |
3779 __ j(above_equal, &miss_force_generic); | 3833 __ j(above_equal, &miss_force_generic); |
3780 | 3834 |
3781 // Handle smi values specially | 3835 // Handle smi values specially |
3782 __ SmiToInteger32(rcx, rcx); | 3836 __ SmiToInteger32(rcx, rcx); |
3783 __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0, &miss_force_generic); | 3837 __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0, |
| 3838 &transition_elements_kind); |
3784 __ ret(0); | 3839 __ ret(0); |
3785 | 3840 |
3786 // Handle store cache miss, replacing the ic with the generic stub. | 3841 // Handle store cache miss, replacing the ic with the generic stub. |
3787 __ bind(&miss_force_generic); | 3842 __ bind(&miss_force_generic); |
3788 Handle<Code> ic_force_generic = | 3843 Handle<Code> ic_force_generic = |
3789 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3844 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3790 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | 3845 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
| 3846 |
| 3847 __ bind(&transition_elements_kind); |
| 3848 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3849 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
3791 } | 3850 } |
3792 | 3851 |
3793 | 3852 |
3794 #undef __ | 3853 #undef __ |
3795 | 3854 |
3796 } } // namespace v8::internal | 3855 } } // namespace v8::internal |
3797 | 3856 |
3798 #endif // V8_TARGET_ARCH_X64 | 3857 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |