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

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: Add missing WB stub 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
« no previous file with comments | « src/ia32/codegen-ia32.cc ('k') | src/ic.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 2573 matching lines...) Expand 10 before | Expand all | Expand 10 after
2584 Handle<Map> receiver_map) { 2584 Handle<Map> receiver_map) {
2585 // ----------- S t a t e ------------- 2585 // ----------- S t a t e -------------
2586 // -- eax : value 2586 // -- eax : value
2587 // -- ecx : key 2587 // -- ecx : key
2588 // -- edx : receiver 2588 // -- edx : receiver
2589 // -- esp[0] : return address 2589 // -- esp[0] : return address
2590 // ----------------------------------- 2590 // -----------------------------------
2591 ElementsKind elements_kind = receiver_map->elements_kind(); 2591 ElementsKind elements_kind = receiver_map->elements_kind();
2592 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; 2592 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
2593 Handle<Code> stub = 2593 Handle<Code> stub =
2594 KeyedStoreElementStub(is_jsarray, elements_kind).GetCode(); 2594 KeyedStoreElementStub(is_jsarray, elements_kind, grow_mode_).GetCode();
2595 2595
2596 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); 2596 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
2597 2597
2598 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2598 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2599 __ jmp(ic, RelocInfo::CODE_TARGET); 2599 __ jmp(ic, RelocInfo::CODE_TARGET);
2600 2600
2601 // Return the generated code. 2601 // Return the generated code.
2602 return GetCode(NORMAL, factory()->empty_string()); 2602 return GetCode(NORMAL, factory()->empty_string());
2603 } 2603 }
2604 2604
(...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after
3711 __ bind(&miss_force_generic); 3711 __ bind(&miss_force_generic);
3712 Handle<Code> miss_ic = 3712 Handle<Code> miss_ic =
3713 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 3713 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3714 __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3714 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3715 } 3715 }
3716 3716
3717 3717
3718 void KeyedStoreStubCompiler::GenerateStoreFastElement( 3718 void KeyedStoreStubCompiler::GenerateStoreFastElement(
3719 MacroAssembler* masm, 3719 MacroAssembler* masm,
3720 bool is_js_array, 3720 bool is_js_array,
3721 ElementsKind elements_kind) { 3721 ElementsKind elements_kind,
3722 KeyedAccessGrowMode grow_mode) {
3722 // ----------- S t a t e ------------- 3723 // ----------- S t a t e -------------
3723 // -- eax : value 3724 // -- eax : value
3724 // -- ecx : key 3725 // -- ecx : key
3725 // -- edx : receiver 3726 // -- edx : receiver
3726 // -- esp[0] : return address 3727 // -- esp[0] : return address
3727 // ----------------------------------- 3728 // -----------------------------------
3728 Label miss_force_generic, transition_elements_kind; 3729 Label miss_force_generic, grow, slow, transition_elements_kind;
3730 Label check_capacity, prepare_slow, finish_store, commit_backing_store;
3729 3731
3730 // This stub is meant to be tail-jumped to, the receiver must already 3732 // This stub is meant to be tail-jumped to, the receiver must already
3731 // have been verified by the caller to not be a smi. 3733 // have been verified by the caller to not be a smi.
3732 3734
3733 // Check that the key is a smi. 3735 // Check that the key is a smi.
3734 __ JumpIfNotSmi(ecx, &miss_force_generic); 3736 __ JumpIfNotSmi(ecx, &miss_force_generic);
3735 3737
3738 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
3739 __ JumpIfNotSmi(eax, &transition_elements_kind);
3740 }
3741
3736 // Get the elements array and make sure it is a fast element array, not 'cow'. 3742 // Get the elements array and make sure it is a fast element array, not 'cow'.
3737 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 3743 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3738 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
3739 Immediate(masm->isolate()->factory()->fixed_array_map()));
3740 __ j(not_equal, &miss_force_generic);
3741
3742 if (is_js_array) { 3744 if (is_js_array) {
3743 // Check that the key is within bounds. 3745 // Check that the key is within bounds.
3744 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. 3746 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis.
3745 __ j(above_equal, &miss_force_generic); 3747 if (grow_mode == ALLOW_JSARRAY_GROWTH) {
3748 __ j(above_equal, &grow);
3749 } else {
3750 __ j(above_equal, &miss_force_generic);
3751 }
3746 } else { 3752 } else {
3747 // Check that the key is within bounds. 3753 // Check that the key is within bounds.
3748 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. 3754 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis.
3749 __ j(above_equal, &miss_force_generic); 3755 __ j(above_equal, &miss_force_generic);
3750 } 3756 }
3751 3757
3758 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
3759 Immediate(masm->isolate()->factory()->fixed_array_map()));
3760 __ j(not_equal, &miss_force_generic);
3761
3762 __ bind(&finish_store);
3752 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 3763 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
3753 __ JumpIfNotSmi(eax, &transition_elements_kind);
3754 // ecx is a smi, use times_half_pointer_size instead of 3764 // ecx is a smi, use times_half_pointer_size instead of
3755 // times_pointer_size 3765 // times_pointer_size
3756 __ mov(FieldOperand(edi, 3766 __ mov(FieldOperand(edi,
3757 ecx, 3767 ecx,
3758 times_half_pointer_size, 3768 times_half_pointer_size,
3759 FixedArray::kHeaderSize), eax); 3769 FixedArray::kHeaderSize), eax);
3760 } else { 3770 } else {
3761 ASSERT(elements_kind == FAST_ELEMENTS); 3771 ASSERT(elements_kind == FAST_ELEMENTS);
3762 // Do the store and update the write barrier. 3772 // Do the store and update the write barrier.
3763 // ecx is a smi, use times_half_pointer_size instead of 3773 // ecx is a smi, use times_half_pointer_size instead of
3764 // times_pointer_size 3774 // times_pointer_size
3765 __ lea(ecx, FieldOperand(edi, 3775 __ lea(ecx, FieldOperand(edi,
3766 ecx, 3776 ecx,
3767 times_half_pointer_size, 3777 times_half_pointer_size,
3768 FixedArray::kHeaderSize)); 3778 FixedArray::kHeaderSize));
3769 __ mov(Operand(ecx, 0), eax); 3779 __ mov(Operand(ecx, 0), eax);
3770 // Make sure to preserve the value in register eax. 3780 // Make sure to preserve the value in register eax.
3771 __ mov(edx, eax); 3781 __ mov(ebx, eax);
3772 __ RecordWrite(edi, ecx, edx, kDontSaveFPRegs); 3782 __ RecordWrite(edi, ecx, ebx, kDontSaveFPRegs);
3773 } 3783 }
3774 3784
3775 // Done. 3785 // Done.
3776 __ ret(0); 3786 __ ret(0);
3777 3787
3778 // Handle store cache miss, replacing the ic with the generic stub. 3788 // Handle store cache miss, replacing the ic with the generic stub.
3779 __ bind(&miss_force_generic); 3789 __ bind(&miss_force_generic);
3780 Handle<Code> ic_force_generic = 3790 Handle<Code> ic_force_generic =
3781 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3791 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3782 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 3792 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3783 3793
3784 // Handle transition to other elements kinds without using the generic stub. 3794 // Handle transition to other elements kinds without using the generic stub.
3785 __ bind(&transition_elements_kind); 3795 __ bind(&transition_elements_kind);
3786 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 3796 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
3787 __ jmp(ic_miss, RelocInfo::CODE_TARGET); 3797 __ jmp(ic_miss, RelocInfo::CODE_TARGET);
3798
3799 if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
3800 // Handle transition requiring the array to grow.
3801 __ bind(&grow);
3802
3803 // Make sure the array is only growing by a single element, anything else
3804 // must be handled by the runtime. Flags are already set by previous
3805 // compare.
3806 __ j(not_equal, &miss_force_generic);
3807
3808 // Check for the empty array, and preallocate a small backing store if
3809 // possible.
3810 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3811 __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array()));
3812 __ j(not_equal, &check_capacity);
3813
3814 int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
3815 __ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT);
3816 // Restore the key, which is known to be the array length.
3817
3818 // eax: value
3819 // ecx: key
3820 // edx: receiver
3821 // edi: elements
3822 // Make sure that the backing store can hold additional elements.
3823 __ mov(FieldOperand(edi, JSObject::kMapOffset),
3824 Immediate(masm->isolate()->factory()->fixed_array_map()));
3825 __ mov(FieldOperand(edi, FixedArray::kLengthOffset),
3826 Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
3827 __ mov(ebx, Immediate(masm->isolate()->factory()->the_hole_value()));
3828 for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) {
3829 __ mov(FieldOperand(edi, FixedArray::SizeFor(i)), ebx);
3830 }
3831
3832 // Store the element at index zero.
3833 __ mov(FieldOperand(edi, FixedArray::SizeFor(0)), eax);
3834
3835 // Install the new backing store in the JSArray.
3836 __ mov(FieldOperand(edx, JSObject::kElementsOffset), edi);
3837 __ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx,
3838 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
3839
3840 // Increment the length of the array.
3841 __ mov(FieldOperand(edx, JSArray::kLengthOffset),
3842 Immediate(Smi::FromInt(1)));
3843 __ ret(0);
3844
3845 __ bind(&check_capacity);
3846 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
3847 Immediate(masm->isolate()->factory()->fixed_cow_array_map()));
3848 __ j(equal, &miss_force_generic);
3849
3850 // eax: value
3851 // ecx: key
3852 // edx: receiver
3853 // edi: elements
3854 // Make sure that the backing store can hold additional elements.
3855 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
3856 __ j(above_equal, &slow);
3857
3858 // Grow the array and finish the store.
3859 __ add(FieldOperand(edx, JSArray::kLengthOffset),
3860 Immediate(Smi::FromInt(1)));
3861 __ jmp(&finish_store);
3862
3863 __ bind(&prepare_slow);
3864 // Restore the key, which is known to be the array length.
3865 __ mov(ecx, Immediate(0));
3866
3867 __ bind(&slow);
3868 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3869 __ jmp(ic_slow, RelocInfo::CODE_TARGET);
3870 }
3788 } 3871 }
3789 3872
3790 3873
3791 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( 3874 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
3792 MacroAssembler* masm, 3875 MacroAssembler* masm,
3793 bool is_js_array) { 3876 bool is_js_array,
3877 KeyedAccessGrowMode grow_mode) {
3794 // ----------- S t a t e ------------- 3878 // ----------- S t a t e -------------
3795 // -- eax : value 3879 // -- eax : value
3796 // -- ecx : key 3880 // -- ecx : key
3797 // -- edx : receiver 3881 // -- edx : receiver
3798 // -- esp[0] : return address 3882 // -- esp[0] : return address
3799 // ----------------------------------- 3883 // -----------------------------------
3800 Label miss_force_generic, transition_elements_kind; 3884 Label miss_force_generic, transition_elements_kind, grow, slow;
3885 Label check_capacity, prepare_slow, finish_store, commit_backing_store;
3801 3886
3802 // This stub is meant to be tail-jumped to, the receiver must already 3887 // This stub is meant to be tail-jumped to, the receiver must already
3803 // have been verified by the caller to not be a smi. 3888 // have been verified by the caller to not be a smi.
3804 3889
3805 // Check that the key is a smi. 3890 // Check that the key is a smi.
3806 __ JumpIfNotSmi(ecx, &miss_force_generic); 3891 __ JumpIfNotSmi(ecx, &miss_force_generic);
3807 3892
3808 // Get the elements array. 3893 // Get the elements array.
3809 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 3894 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3810 __ AssertFastElements(edi); 3895 __ AssertFastElements(edi);
3811 3896
3812 if (is_js_array) { 3897 if (is_js_array) {
3813 // Check that the key is within bounds. 3898 // Check that the key is within bounds.
3814 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. 3899 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis.
3900 if (grow_mode == ALLOW_JSARRAY_GROWTH) {
3901 __ j(above_equal, &grow);
3902 } else {
3903 __ j(above_equal, &miss_force_generic);
3904 }
3815 } else { 3905 } else {
3816 // Check that the key is within bounds. 3906 // Check that the key is within bounds.
3817 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. 3907 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis.
3818 } 3908 }
3819 __ j(above_equal, &miss_force_generic);
3820 3909
3821 __ StoreNumberToDoubleElements(eax, 3910 __ bind(&finish_store);
3822 edi, 3911 __ StoreNumberToDoubleElements(eax, edi, ecx, edx, xmm0,
3823 ecx, 3912 &transition_elements_kind, true);
3824 edx,
3825 xmm0,
3826 &transition_elements_kind,
3827 true);
3828 __ ret(0); 3913 __ ret(0);
3829 3914
3830 // Handle store cache miss, replacing the ic with the generic stub. 3915 // Handle store cache miss, replacing the ic with the generic stub.
3831 __ bind(&miss_force_generic); 3916 __ bind(&miss_force_generic);
3832 Handle<Code> ic_force_generic = 3917 Handle<Code> ic_force_generic =
3833 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3918 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3834 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 3919 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3835 3920
3836 // Handle transition to other elements kinds without using the generic stub. 3921 // Handle transition to other elements kinds without using the generic stub.
3837 __ bind(&transition_elements_kind); 3922 __ bind(&transition_elements_kind);
3838 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 3923 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
3839 __ jmp(ic_miss, RelocInfo::CODE_TARGET); 3924 __ jmp(ic_miss, RelocInfo::CODE_TARGET);
3925
3926 if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
3927 // Handle transition requiring the array to grow.
3928 __ bind(&grow);
3929
3930 // Make sure the array is only growing by a single element, anything else
3931 // must be handled by the runtime. Flags are already set by previous
3932 // compare.
3933 __ j(not_equal, &miss_force_generic);
3934
3935 // Transition on values that can't be stored in a FixedDoubleArray.
3936 Label value_is_smi;
3937 __ JumpIfSmi(eax, &value_is_smi);
3938 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3939 Immediate(Handle<Map>(masm->isolate()->heap()->heap_number_map())));
3940 __ j(not_equal, &transition_elements_kind);
3941 __ bind(&value_is_smi);
3942
3943 // Check for the empty array, and preallocate a small backing store if
3944 // possible.
3945 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3946 __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array()));
3947 __ j(not_equal, &check_capacity);
3948
3949 int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
3950 __ AllocateInNewSpace(size, edi, ebx, ecx, &prepare_slow, TAG_OBJECT);
3951 // Restore the key, which is known to be the array length.
3952 __ mov(ecx, Immediate(0));
3953
3954 // eax: value
3955 // ecx: key
3956 // edx: receiver
3957 // edi: elements
3958 // Initialize the new FixedDoubleArray. Leave elements unitialized for
3959 // efficiency, they are guaranteed to be initialized before use.
3960 __ mov(FieldOperand(edi, JSObject::kMapOffset),
3961 Immediate(masm->isolate()->factory()->fixed_double_array_map()));
3962 __ mov(FieldOperand(edi, FixedDoubleArray::kLengthOffset),
3963 Immediate(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
3964
3965 // Install the new backing store in the JSArray.
3966 __ mov(FieldOperand(edx, JSObject::kElementsOffset), edi);
3967 __ RecordWriteField(edx, JSObject::kElementsOffset, edi, ebx,
3968 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
3969
3970 // Increment the length of the array.
3971 __ add(FieldOperand(edx, JSArray::kLengthOffset),
3972 Immediate(Smi::FromInt(1)));
3973 __ jmp(&finish_store);
3974
3975 __ bind(&check_capacity);
3976 // eax: value
3977 // ecx: key
3978 // edx: receiver
3979 // edi: elements
3980 // Make sure that the backing store can hold additional elements.
3981 __ cmp(ecx, FieldOperand(edi, FixedDoubleArray::kLengthOffset));
3982 __ j(above_equal, &slow);
3983
3984 // Grow the array and finish the store.
3985 __ add(FieldOperand(edx, JSArray::kLengthOffset),
3986 Immediate(Smi::FromInt(1)));
3987 __ jmp(&finish_store);
3988
3989 __ bind(&prepare_slow);
3990 // Restore the key, which is known to be the array length.
3991 __ mov(ecx, Immediate(0));
3992
3993 __ bind(&slow);
3994 Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3995 __ jmp(ic_slow, RelocInfo::CODE_TARGET);
3996 }
3840 } 3997 }
3841 3998
3842 3999
3843 #undef __ 4000 #undef __
3844 4001
3845 } } // namespace v8::internal 4002 } } // namespace v8::internal
3846 4003
3847 #endif // V8_TARGET_ARCH_IA32 4004 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.cc ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698