Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Side by Side Diff: src/ia32/stub-cache-ia32.cc

Issue 9310117: Implement KeyedStoreICs to grow arrays on out-of-bound stores. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: nits Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 2550 matching lines...) Expand 10 before | Expand all | Expand 10 after
2561 Handle<Map> receiver_map) { 2561 Handle<Map> receiver_map) {
2562 // ----------- S t a t e ------------- 2562 // ----------- S t a t e -------------
2563 // -- eax : value 2563 // -- eax : value
2564 // -- ecx : key 2564 // -- ecx : key
2565 // -- edx : receiver 2565 // -- edx : receiver
2566 // -- esp[0] : return address 2566 // -- esp[0] : return address
2567 // ----------------------------------- 2567 // -----------------------------------
2568 ElementsKind elements_kind = receiver_map->elements_kind(); 2568 ElementsKind elements_kind = receiver_map->elements_kind();
2569 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; 2569 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
2570 Handle<Code> stub = 2570 Handle<Code> stub =
2571 KeyedStoreElementStub(is_jsarray, elements_kind).GetCode(); 2571 KeyedStoreElementStub(is_jsarray, elements_kind, grow_mode_).GetCode();
2572 2572
2573 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); 2573 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
2574 2574
2575 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2575 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2576 __ jmp(ic, RelocInfo::CODE_TARGET); 2576 __ jmp(ic, RelocInfo::CODE_TARGET);
2577 2577
2578 // Return the generated code. 2578 // Return the generated code.
2579 return GetCode(NORMAL, factory()->empty_string()); 2579 return GetCode(NORMAL, factory()->empty_string());
2580 } 2580 }
2581 2581
(...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after
3688 __ bind(&miss_force_generic); 3688 __ bind(&miss_force_generic);
3689 Handle<Code> miss_ic = 3689 Handle<Code> miss_ic =
3690 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 3690 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3691 __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3691 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3692 } 3692 }
3693 3693
3694 3694
3695 void KeyedStoreStubCompiler::GenerateStoreFastElement( 3695 void KeyedStoreStubCompiler::GenerateStoreFastElement(
3696 MacroAssembler* masm, 3696 MacroAssembler* masm,
3697 bool is_js_array, 3697 bool is_js_array,
3698 ElementsKind elements_kind) { 3698 ElementsKind elements_kind,
3699 KeyedAccessGrowMode grow_mode) {
3699 // ----------- S t a t e ------------- 3700 // ----------- S t a t e -------------
3700 // -- eax : value 3701 // -- eax : value
3701 // -- ecx : key 3702 // -- ecx : key
3702 // -- edx : receiver 3703 // -- edx : receiver
3703 // -- esp[0] : return address 3704 // -- esp[0] : return address
3704 // ----------------------------------- 3705 // -----------------------------------
3705 Label miss_force_generic, transition_elements_kind; 3706 Label miss_force_generic, grow, slow, transition_elements_kind;
3707 Label check_capacity, prepare_slow, finish_store, commit_backing_store;
3706 3708
3707 // This stub is meant to be tail-jumped to, the receiver must already 3709 // This stub is meant to be tail-jumped to, the receiver must already
3708 // have been verified by the caller to not be a smi. 3710 // have been verified by the caller to not be a smi.
3709 3711
3710 // Check that the key is a smi. 3712 // Check that the key is a smi.
3711 __ JumpIfNotSmi(ecx, &miss_force_generic); 3713 __ JumpIfNotSmi(ecx, &miss_force_generic);
3712 3714
3715 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
3716 __ JumpIfNotSmi(eax, &transition_elements_kind);
3717 }
3718
3713 // Get the elements array and make sure it is a fast element array, not 'cow'. 3719 // Get the elements array and make sure it is a fast element array, not 'cow'.
3714 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 3720 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3715 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
3716 Immediate(masm->isolate()->factory()->fixed_array_map()));
3717 __ j(not_equal, &miss_force_generic);
3718
3719 if (is_js_array) { 3721 if (is_js_array) {
3720 // Check that the key is within bounds. 3722 // Check that the key is within bounds.
3721 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. 3723 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis.
3722 __ j(above_equal, &miss_force_generic); 3724 if (grow_mode == ALLOW_JSARRAY_GROWTH) {
3725 __ j(above_equal, &grow);
3726 } else {
3727 __ j(above_equal, &miss_force_generic);
3728 }
3723 } else { 3729 } else {
3724 // Check that the key is within bounds. 3730 // Check that the key is within bounds.
3725 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. 3731 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis.
3726 __ j(above_equal, &miss_force_generic); 3732 __ j(above_equal, &miss_force_generic);
3727 } 3733 }
3728 3734
3735 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
3736 Immediate(masm->isolate()->factory()->fixed_array_map()));
3737 __ j(not_equal, &miss_force_generic);
3738
3739 __ bind(&finish_store);
3729 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 3740 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
3730 __ JumpIfNotSmi(eax, &transition_elements_kind);
3731 // ecx is a smi, use times_half_pointer_size instead of 3741 // ecx is a smi, use times_half_pointer_size instead of
3732 // times_pointer_size 3742 // times_pointer_size
3733 __ mov(FieldOperand(edi, 3743 __ mov(FieldOperand(edi,
3734 ecx, 3744 ecx,
3735 times_half_pointer_size, 3745 times_half_pointer_size,
3736 FixedArray::kHeaderSize), eax); 3746 FixedArray::kHeaderSize), eax);
3737 } else { 3747 } else {
3738 ASSERT(elements_kind == FAST_ELEMENTS); 3748 ASSERT(elements_kind == FAST_ELEMENTS);
3739 // Do the store and update the write barrier. 3749 // Do the store and update the write barrier.
3740 // ecx is a smi, use times_half_pointer_size instead of 3750 // ecx is a smi, use times_half_pointer_size instead of
3741 // times_pointer_size 3751 // times_pointer_size
3742 __ lea(ecx, FieldOperand(edi, 3752 __ lea(ecx, FieldOperand(edi,
3743 ecx, 3753 ecx,
3744 times_half_pointer_size, 3754 times_half_pointer_size,
3745 FixedArray::kHeaderSize)); 3755 FixedArray::kHeaderSize));
3746 __ mov(Operand(ecx, 0), eax); 3756 __ mov(Operand(ecx, 0), eax);
3747 // Make sure to preserve the value in register eax. 3757 // Make sure to preserve the value in register eax.
3748 __ mov(edx, eax); 3758 __ mov(ebx, eax);
3749 __ RecordWrite(edi, ecx, edx, kDontSaveFPRegs); 3759 __ RecordWrite(edi, ecx, ebx, kDontSaveFPRegs);
3750 } 3760 }
3751 3761
3752 // Done. 3762 // Done.
3753 __ ret(0); 3763 __ ret(0);
3754 3764
3755 // Handle store cache miss, replacing the ic with the generic stub. 3765 // Handle store cache miss, replacing the ic with the generic stub.
3756 __ bind(&miss_force_generic); 3766 __ bind(&miss_force_generic);
3757 Handle<Code> ic_force_generic = 3767 Handle<Code> ic_force_generic =
3758 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3768 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3759 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 3769 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3760 3770
3761 // Handle transition to other elements kinds without using the generic stub. 3771 // Handle transition to other elements kinds without using the generic stub.
3762 __ bind(&transition_elements_kind); 3772 __ bind(&transition_elements_kind);
3763 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 3773 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
3764 __ jmp(ic_miss, RelocInfo::CODE_TARGET); 3774 __ jmp(ic_miss, RelocInfo::CODE_TARGET);
3775
3776 if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
Vyacheslav Egorov (Chromium) 2012/02/09 16:29:19 We might have setters on the prototype: function
danno 2012/02/10 12:25:34 It turns out the existing elements ICs are very br
3777 // Handle transition requiring the array to grow.
3778 __ bind(&grow);
3779
3780 // Make sure the array is only growing by a single element, anything else
3781 // must be handled by the runtime. Flags are already set by previous
3782 // compare.
3783 __ j(not_equal, &miss_force_generic);
3784
3785 // Check for the empty array, and preallocate a small backing store if
3786 // possible.
3787 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3788 __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array()));
3789 __ j(not_equal, &check_capacity);
3790
3791 int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
3792 __ AllocateInNewSpace(size,
3793 edi,
3794 ebx,
3795 ecx,
3796 &prepare_slow,
3797 TAG_OBJECT);
3798 // Restore the key, which is known to be the array length.
3799
3800 // eax: value
3801 // ecx: key
3802 // edx: receiver
3803 // edi: elements
3804 // Make sure that the backing store can hold additional elements.
3805 __ mov(FieldOperand(edi, JSObject::kMapOffset),
3806 Immediate(masm->isolate()->factory()->fixed_array_map()));
3807 __ mov(FieldOperand(edi, FixedArray::kLengthOffset),
3808 Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
3809 __ mov(ebx, Immediate(masm->isolate()->factory()->the_hole_value()));
3810 for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) {
3811 __ mov(FieldOperand(edi, FixedArray::SizeFor(i)), ebx);
3812 }
3813
3814 // Store the element at index zero.
3815 __ mov(FieldOperand(edi, FixedArray::SizeFor(0)), eax);
3816
3817 // Install the new backing store in the JSArray.
3818 __ mov(FieldOperand(edx, JSObject::kElementsOffset), edi);
3819 __ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx,
3820 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
3821
3822 // Increment the length of the array.
3823 __ add(FieldOperand(edx, JSArray::kLengthOffset),
Vyacheslav Egorov (Chromium) 2012/02/09 16:29:19 can be actually move of smi 1 instead of addition
danno 2012/02/10 12:25:34 Done.
3824 Immediate(Smi::FromInt(1)));
3825 __ ret(0);
3826
3827 __ bind(&check_capacity);
3828 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
3829 Immediate(masm->isolate()->factory()->fixed_cow_array_map()));
3830 __ j(equal, &miss_force_generic);
3831
3832 // eax: value
3833 // ecx: key
3834 // edx: receiver
3835 // edi: elements
3836 // Make sure that the backing store can hold additional elements.
3837 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
3838 __ j(above_equal, &slow);
3839
3840 // Grow the array and finish the store.
3841 __ add(FieldOperand(edx, JSArray::kLengthOffset),
3842 Immediate(Smi::FromInt(1)));
3843 __ jmp(&finish_store);
3844
3845 __ bind(&prepare_slow);
3846 // Restore the key, which is known to be the array length.
3847 __ mov(ecx, Immediate(0));
3848
3849 __ bind(&slow);
3850 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3851 __ jmp(ic_slow, RelocInfo::CODE_TARGET);
3852 }
3765 } 3853 }
3766 3854
3767 3855
3768 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( 3856 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
3769 MacroAssembler* masm, 3857 MacroAssembler* masm,
3770 bool is_js_array) { 3858 bool is_js_array,
3859 KeyedAccessGrowMode grow_mode) {
3771 // ----------- S t a t e ------------- 3860 // ----------- S t a t e -------------
3772 // -- eax : value 3861 // -- eax : value
3773 // -- ecx : key 3862 // -- ecx : key
3774 // -- edx : receiver 3863 // -- edx : receiver
3775 // -- esp[0] : return address 3864 // -- esp[0] : return address
3776 // ----------------------------------- 3865 // -----------------------------------
3777 Label miss_force_generic, transition_elements_kind; 3866 Label miss_force_generic, transition_elements_kind, grow, slow;
3867 Label check_capacity, prepare_slow, finish_store, commit_backing_store;
3778 3868
3779 // This stub is meant to be tail-jumped to, the receiver must already 3869 // This stub is meant to be tail-jumped to, the receiver must already
3780 // have been verified by the caller to not be a smi. 3870 // have been verified by the caller to not be a smi.
3781 3871
3782 // Check that the key is a smi. 3872 // Check that the key is a smi.
3783 __ JumpIfNotSmi(ecx, &miss_force_generic); 3873 __ JumpIfNotSmi(ecx, &miss_force_generic);
3784 3874
3785 // Get the elements array. 3875 // Get the elements array.
3786 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 3876 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3787 __ AssertFastElements(edi); 3877 __ AssertFastElements(edi);
3788 3878
3789 if (is_js_array) { 3879 if (is_js_array) {
3790 // Check that the key is within bounds. 3880 // Check that the key is within bounds.
3791 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. 3881 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis.
3882 if (grow_mode == ALLOW_JSARRAY_GROWTH) {
3883 __ j(above_equal, &grow);
3884 } else {
3885 __ j(above_equal, &miss_force_generic);
3886 }
3792 } else { 3887 } else {
3793 // Check that the key is within bounds. 3888 // Check that the key is within bounds.
3794 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. 3889 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis.
3795 } 3890 }
3796 __ j(above_equal, &miss_force_generic);
3797 3891
3892 __ bind(&finish_store);
3798 __ StoreNumberToDoubleElements(eax, 3893 __ StoreNumberToDoubleElements(eax,
3799 edi, 3894 edi,
3800 ecx, 3895 ecx,
3801 edx, 3896 edx,
3802 xmm0, 3897 xmm0,
3803 &transition_elements_kind, 3898 &transition_elements_kind,
3804 true); 3899 true);
3805 __ ret(0); 3900 __ ret(0);
3806 3901
3807 // Handle store cache miss, replacing the ic with the generic stub. 3902 // Handle store cache miss, replacing the ic with the generic stub.
3808 __ bind(&miss_force_generic); 3903 __ bind(&miss_force_generic);
3809 Handle<Code> ic_force_generic = 3904 Handle<Code> ic_force_generic =
3810 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3905 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3811 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 3906 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3812 3907
3813 // Handle transition to other elements kinds without using the generic stub. 3908 // Handle transition to other elements kinds without using the generic stub.
3814 __ bind(&transition_elements_kind); 3909 __ bind(&transition_elements_kind);
3815 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 3910 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
3816 __ jmp(ic_miss, RelocInfo::CODE_TARGET); 3911 __ jmp(ic_miss, RelocInfo::CODE_TARGET);
3912
3913 if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
3914 // Handle transition requiring the array to grow.
3915 __ bind(&grow);
3916
3917 // Make sure the array is only growing by a single element, anything else
3918 // must be handled by the runtime. Flags are already set by previous
3919 // compare.
3920 __ j(not_equal, &miss_force_generic);
3921
3922 // Transition on values that can't be stored in a FixedDoubleArray.
3923 Label value_is_smi;
3924 __ JumpIfSmi(eax, &value_is_smi);
3925 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3926 Immediate(Handle<Map>(masm->isolate()->heap()->heap_number_map())));
3927 __ j(not_equal, &transition_elements_kind);
3928 __ bind(&value_is_smi);
3929
3930 // Check for the empty array, and preallocate a small backing store if
3931 // possible.
3932 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3933 __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array()));
3934 __ j(not_equal, &check_capacity);
3935
3936 int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
3937 __ AllocateInNewSpace(size,
3938 edi,
3939 ebx,
3940 ecx,
3941 &prepare_slow,
3942 TAG_OBJECT);
3943 // Restore the key, which is known to be the array length.
3944 __ mov(ecx, Immediate(0));
3945
3946 // eax: value
3947 // ecx: key
3948 // edx: receiver
3949 // edi: elements
3950 // Make sure that the backing store can hold additional elements.
3951 __ mov(FieldOperand(edi, JSObject::kMapOffset),
3952 Immediate(masm->isolate()->factory()->fixed_double_array_map()));
3953 __ mov(FieldOperand(edi, FixedDoubleArray::kLengthOffset),
3954 Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
3955
3956 // Install the new backing store in the JSArray.
3957 __ mov(FieldOperand(edx, JSObject::kElementsOffset), edi);
Vyacheslav Egorov (Chromium) 2012/02/10 00:19:18 elements of the backing store are completely unini
danno 2012/02/10 12:25:34 Done.
3958 __ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx,
3959 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
3960
3961 // Increment the length of the array.
3962 __ add(FieldOperand(edx, JSArray::kLengthOffset),
3963 Immediate(Smi::FromInt(1)));
3964 __ jmp(&finish_store);
3965
3966 __ bind(&check_capacity);
3967 // eax: value
3968 // ecx: key
3969 // edx: receiver
3970 // edi: elements
3971 // Make sure that the backing store can hold additional elements.
3972 __ cmp(ecx, FieldOperand(edi, FixedDoubleArray::kLengthOffset));
3973 __ j(above_equal, &slow);
3974
3975 // Grow the array and finish the store.
3976 __ add(FieldOperand(edx, JSArray::kLengthOffset),
3977 Immediate(Smi::FromInt(1)));
3978 __ jmp(&finish_store);
3979
3980 __ bind(&prepare_slow);
3981 // Restore the key, which is known to be the array length.
3982 __ mov(ecx, Immediate(0));
3983
3984 __ bind(&slow);
3985 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3986 __ jmp(ic_slow, RelocInfo::CODE_TARGET);
3987 }
3817 } 3988 }
3818 3989
3819 3990
3820 #undef __ 3991 #undef __
3821 3992
3822 } } // namespace v8::internal 3993 } } // namespace v8::internal
3823 3994
3824 #endif // V8_TARGET_ARCH_IA32 3995 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698