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 2741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2752 DO_SMI_CHECK); | 2752 DO_SMI_CHECK); |
2753 | 2753 |
2754 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2754 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
2755 __ jmp(ic, RelocInfo::CODE_TARGET); | 2755 __ jmp(ic, RelocInfo::CODE_TARGET); |
2756 | 2756 |
2757 // Return the generated code. | 2757 // Return the generated code. |
2758 return GetCode(NORMAL, NULL); | 2758 return GetCode(NORMAL, NULL); |
2759 } | 2759 } |
2760 | 2760 |
2761 | 2761 |
| 2762 MaybeObject* KeyedStoreStubCompiler::CompileStoreElementWithTransition( |
| 2763 Map* transitioned_map, |
| 2764 Map* untransitioned_map_1, |
| 2765 Map* untransitioned_map_2) { |
| 2766 // ----------- S t a t e ------------- |
| 2767 // -- eax : value |
| 2768 // -- ecx : key |
| 2769 // -- edx : receiver |
| 2770 // -- esp[0] : return address |
| 2771 // ----------------------------------- |
| 2772 |
| 2773 // The order of map occurrences in the generated code below is important. |
| 2774 // Both IC code and Crankshaft rely on |transitioned_map| being the first |
| 2775 // map in the stub. |
| 2776 |
| 2777 Code* notransition_stub; |
| 2778 ElementsKind elements_kind = transitioned_map->elements_kind(); |
| 2779 bool is_jsarray = transitioned_map->instance_type() == JS_ARRAY_TYPE; |
| 2780 MaybeObject* maybe_stub = |
| 2781 KeyedStoreElementStub(is_jsarray, elements_kind).TryGetCode(); |
| 2782 if (!maybe_stub->To(¬ransition_stub)) return maybe_stub; |
| 2783 |
| 2784 Label just_store, miss; |
| 2785 __ JumpIfSmi(edx, &miss, Label::kNear); |
| 2786 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 2787 // ebx: receiver->map(). |
| 2788 __ cmp(ebx, Handle<Map>(transitioned_map)); |
| 2789 __ j(equal, &just_store); |
| 2790 ASSERT_NE(untransitioned_map_1, NULL); |
| 2791 __ cmp(ebx, Handle<Map>(untransitioned_map_1)); |
| 2792 // TODO(jkummerow): When we have specialized code to do the transition, |
| 2793 // call that code here, then jump to just_store when the call returns. |
| 2794 // <temporary: just use the generic stub> |
| 2795 Code* generic_stub = (strict_mode_ == kStrictMode) |
| 2796 ? isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic_Strict) |
| 2797 : isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic); |
| 2798 __ j(equal, Handle<Code>(generic_stub)); |
| 2799 // </temporary> |
| 2800 if (untransitioned_map_2 != NULL) { |
| 2801 __ cmp(ebx, Handle<Map>(untransitioned_map_2)); |
| 2802 // <temporary: see above, same here> |
| 2803 __ j(equal, Handle<Code>(generic_stub)); |
| 2804 // </temporary> |
| 2805 } |
| 2806 __ bind(&miss); |
| 2807 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2808 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2809 |
| 2810 __ bind(&just_store); |
| 2811 __ jmp(Handle<Code>(notransition_stub), RelocInfo::CODE_TARGET); |
| 2812 |
| 2813 // Return the generated code. |
| 2814 return GetCode(NORMAL, NULL, MEGAMORPHIC); |
| 2815 } |
| 2816 |
| 2817 |
2762 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic( | 2818 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic( |
2763 MapList* receiver_maps, | 2819 MapList* receiver_maps, |
2764 CodeList* handler_ics) { | 2820 CodeList* handler_ics) { |
2765 // ----------- S t a t e ------------- | 2821 // ----------- S t a t e ------------- |
2766 // -- eax : value | 2822 // -- eax : value |
2767 // -- ecx : key | 2823 // -- ecx : key |
2768 // -- edx : receiver | 2824 // -- edx : receiver |
2769 // -- esp[0] : return address | 2825 // -- esp[0] : return address |
2770 // ----------------------------------- | 2826 // ----------------------------------- |
2771 Label miss; | 2827 Label miss; |
(...skipping 1131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3903 void KeyedStoreStubCompiler::GenerateStoreFastElement( | 3959 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
3904 MacroAssembler* masm, | 3960 MacroAssembler* masm, |
3905 bool is_js_array, | 3961 bool is_js_array, |
3906 ElementsKind elements_kind) { | 3962 ElementsKind elements_kind) { |
3907 // ----------- S t a t e ------------- | 3963 // ----------- S t a t e ------------- |
3908 // -- eax : value | 3964 // -- eax : value |
3909 // -- ecx : key | 3965 // -- ecx : key |
3910 // -- edx : receiver | 3966 // -- edx : receiver |
3911 // -- esp[0] : return address | 3967 // -- esp[0] : return address |
3912 // ----------------------------------- | 3968 // ----------------------------------- |
3913 Label miss_force_generic; | 3969 Label miss_force_generic, transition_elements_kind; |
3914 | 3970 |
3915 // This stub is meant to be tail-jumped to, the receiver must already | 3971 // This stub is meant to be tail-jumped to, the receiver must already |
3916 // have been verified by the caller to not be a smi. | 3972 // have been verified by the caller to not be a smi. |
3917 | 3973 |
3918 // Check that the key is a smi. | 3974 // Check that the key is a smi. |
3919 __ JumpIfNotSmi(ecx, &miss_force_generic); | 3975 __ JumpIfNotSmi(ecx, &miss_force_generic); |
3920 | 3976 |
3921 // Get the elements array and make sure it is a fast element array, not 'cow'. | 3977 // Get the elements array and make sure it is a fast element array, not 'cow'. |
3922 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 3978 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
3923 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), | 3979 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), |
3924 Immediate(masm->isolate()->factory()->fixed_array_map())); | 3980 Immediate(masm->isolate()->factory()->fixed_array_map())); |
3925 __ j(not_equal, &miss_force_generic); | 3981 __ j(not_equal, &miss_force_generic); |
3926 | 3982 |
3927 if (is_js_array) { | 3983 if (is_js_array) { |
3928 // Check that the key is within bounds. | 3984 // Check that the key is within bounds. |
3929 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. | 3985 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. |
3930 __ j(above_equal, &miss_force_generic); | 3986 __ j(above_equal, &miss_force_generic); |
3931 } else { | 3987 } else { |
3932 // Check that the key is within bounds. | 3988 // Check that the key is within bounds. |
3933 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. | 3989 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. |
3934 __ j(above_equal, &miss_force_generic); | 3990 __ j(above_equal, &miss_force_generic); |
3935 } | 3991 } |
3936 | 3992 |
3937 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { | 3993 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
3938 __ JumpIfNotSmi(eax, &miss_force_generic); | 3994 __ JumpIfNotSmi(eax, &transition_elements_kind); |
3939 // ecx is a smi, use times_half_pointer_size instead of | 3995 // ecx is a smi, use times_half_pointer_size instead of |
3940 // times_pointer_size | 3996 // times_pointer_size |
3941 __ mov(FieldOperand(edi, | 3997 __ mov(FieldOperand(edi, |
3942 ecx, | 3998 ecx, |
3943 times_half_pointer_size, | 3999 times_half_pointer_size, |
3944 FixedArray::kHeaderSize), eax); | 4000 FixedArray::kHeaderSize), eax); |
3945 } else { | 4001 } else { |
3946 ASSERT(elements_kind == FAST_ELEMENTS); | 4002 ASSERT(elements_kind == FAST_ELEMENTS); |
3947 // Do the store and update the write barrier. | 4003 // Do the store and update the write barrier. |
3948 // ecx is a smi, use times_half_pointer_size instead of | 4004 // ecx is a smi, use times_half_pointer_size instead of |
3949 // times_pointer_size | 4005 // times_pointer_size |
3950 __ lea(ecx, FieldOperand(edi, | 4006 __ lea(ecx, FieldOperand(edi, |
3951 ecx, | 4007 ecx, |
3952 times_half_pointer_size, | 4008 times_half_pointer_size, |
3953 FixedArray::kHeaderSize)); | 4009 FixedArray::kHeaderSize)); |
3954 __ mov(Operand(ecx, 0), eax); | 4010 __ mov(Operand(ecx, 0), eax); |
3955 // Make sure to preserve the value in register eax. | 4011 // Make sure to preserve the value in register eax. |
3956 __ mov(edx, eax); | 4012 __ mov(edx, eax); |
3957 __ RecordWrite(edi, ecx, edx, kDontSaveFPRegs); | 4013 __ RecordWrite(edi, ecx, edx, kDontSaveFPRegs); |
3958 } | 4014 } |
3959 | 4015 |
3960 // Done. | 4016 // Done. |
3961 __ ret(0); | 4017 __ ret(0); |
3962 | 4018 |
3963 // Handle store cache miss, replacing the ic with the generic stub. | 4019 // Handle store cache miss, replacing the ic with the generic stub. |
3964 __ bind(&miss_force_generic); | 4020 __ bind(&miss_force_generic); |
3965 Handle<Code> ic_force_generic = | 4021 Handle<Code> ic_force_generic = |
3966 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 4022 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3967 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | 4023 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
| 4024 |
| 4025 // Handle transition to other elements kinds without using the generic stub. |
| 4026 __ bind(&transition_elements_kind); |
| 4027 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 4028 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
3968 } | 4029 } |
3969 | 4030 |
3970 | 4031 |
3971 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( | 4032 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( |
3972 MacroAssembler* masm, | 4033 MacroAssembler* masm, |
3973 bool is_js_array) { | 4034 bool is_js_array) { |
3974 // ----------- S t a t e ------------- | 4035 // ----------- S t a t e ------------- |
3975 // -- eax : value | 4036 // -- eax : value |
3976 // -- ecx : key | 4037 // -- ecx : key |
3977 // -- edx : receiver | 4038 // -- edx : receiver |
3978 // -- esp[0] : return address | 4039 // -- esp[0] : return address |
3979 // ----------------------------------- | 4040 // ----------------------------------- |
3980 Label miss_force_generic; | 4041 Label miss_force_generic, transition_elements_kind; |
3981 | 4042 |
3982 // This stub is meant to be tail-jumped to, the receiver must already | 4043 // This stub is meant to be tail-jumped to, the receiver must already |
3983 // have been verified by the caller to not be a smi. | 4044 // have been verified by the caller to not be a smi. |
3984 | 4045 |
3985 // Check that the key is a smi. | 4046 // Check that the key is a smi. |
3986 __ JumpIfNotSmi(ecx, &miss_force_generic); | 4047 __ JumpIfNotSmi(ecx, &miss_force_generic); |
3987 | 4048 |
3988 // Get the elements array. | 4049 // Get the elements array. |
3989 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 4050 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
3990 __ AssertFastElements(edi); | 4051 __ AssertFastElements(edi); |
3991 | 4052 |
3992 if (is_js_array) { | 4053 if (is_js_array) { |
3993 // Check that the key is within bounds. | 4054 // Check that the key is within bounds. |
3994 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. | 4055 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. |
3995 } else { | 4056 } else { |
3996 // Check that the key is within bounds. | 4057 // Check that the key is within bounds. |
3997 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. | 4058 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis. |
3998 } | 4059 } |
3999 __ j(above_equal, &miss_force_generic); | 4060 __ j(above_equal, &miss_force_generic); |
4000 | 4061 |
4001 __ StoreNumberToDoubleElements(eax, | 4062 __ StoreNumberToDoubleElements(eax, |
4002 edi, | 4063 edi, |
4003 ecx, | 4064 ecx, |
4004 edx, | 4065 edx, |
4005 xmm0, | 4066 xmm0, |
4006 &miss_force_generic, | 4067 &transition_elements_kind, |
4007 true); | 4068 true); |
4008 __ ret(0); | 4069 __ ret(0); |
4009 | 4070 |
4010 // Handle store cache miss, replacing the ic with the generic stub. | 4071 // Handle store cache miss, replacing the ic with the generic stub. |
4011 __ bind(&miss_force_generic); | 4072 __ bind(&miss_force_generic); |
4012 Handle<Code> ic_force_generic = | 4073 Handle<Code> ic_force_generic = |
4013 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 4074 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
4014 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | 4075 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
| 4076 |
| 4077 // Handle transition to other elements kinds without using the generic stub. |
| 4078 __ bind(&transition_elements_kind); |
| 4079 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 4080 __ jmp(ic_miss, RelocInfo::CODE_TARGET); |
4015 } | 4081 } |
4016 | 4082 |
4017 | 4083 |
4018 #undef __ | 4084 #undef __ |
4019 | 4085 |
4020 } } // namespace v8::internal | 4086 } } // namespace v8::internal |
4021 | 4087 |
4022 #endif // V8_TARGET_ARCH_IA32 | 4088 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |