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

Side by Side Diff: src/arm/ic-arm.cc

Issue 2804029: Implement IC for storing to dictionary case objects.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 5 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/arm/codegen-arm.cc ('k') | src/arm/macro-assembler-arm.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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 __ b(eq, global_object); 57 __ b(eq, global_object);
58 __ cmp(type, Operand(JS_BUILTINS_OBJECT_TYPE)); 58 __ cmp(type, Operand(JS_BUILTINS_OBJECT_TYPE));
59 __ b(eq, global_object); 59 __ b(eq, global_object);
60 __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE)); 60 __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE));
61 __ b(eq, global_object); 61 __ b(eq, global_object);
62 } 62 }
63 63
64 64
65 // Generated code falls through if the receiver is a regular non-global 65 // Generated code falls through if the receiver is a regular non-global
66 // JS object with slow properties and no interceptors. 66 // JS object with slow properties and no interceptors.
67 static void GenerateDictionaryLoadReceiverCheck(MacroAssembler* masm, 67 static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
68 Register receiver, 68 Register receiver,
69 Register elements, 69 Register elements,
70 Register t0, 70 Register t0,
71 Register t1, 71 Register t1,
72 Label* miss) { 72 Label* miss) {
73 // Register usage: 73 // Register usage:
74 // receiver: holds the receiver on entry and is unchanged. 74 // receiver: holds the receiver on entry and is unchanged.
75 // elements: holds the property dictionary on fall through. 75 // elements: holds the property dictionary on fall through.
76 // Scratch registers: 76 // Scratch registers:
77 // t0: used to holds the receiver map. 77 // t0: used to holds the receiver map.
78 // t1: used to holds the receiver instance type, receiver bit mask and 78 // t1: used to holds the receiver instance type, receiver bit mask and
79 // elements map. 79 // elements map.
80 80
81 // Check that the receiver isn't a smi. 81 // Check that the receiver isn't a smi.
82 __ tst(receiver, Operand(kSmiTagMask)); 82 __ tst(receiver, Operand(kSmiTagMask));
(...skipping 15 matching lines...) Expand all
98 __ b(nz, miss); 98 __ b(nz, miss);
99 99
100 __ ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 100 __ ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
101 __ ldr(t1, FieldMemOperand(elements, HeapObject::kMapOffset)); 101 __ ldr(t1, FieldMemOperand(elements, HeapObject::kMapOffset));
102 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 102 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
103 __ cmp(t1, ip); 103 __ cmp(t1, ip);
104 __ b(nz, miss); 104 __ b(nz, miss);
105 } 105 }
106 106
107 107
108 // Helper function used from LoadIC/CallIC GenerateNormal. 108 // Probe the string dictionary in the |elements| register. Jump to the
109 // 109 // |done| label if a property with the given name is found. Jump to
110 // elements: Property dictionary. It is not clobbered if a jump to the miss 110 // the |miss| label otherwise.
111 // label is done. 111 static void GenerateStringDictionaryProbes(MacroAssembler* masm,
112 // name: Property name. It is not clobbered if a jump to the miss label is 112 Label* miss,
113 // done 113 Label* done,
114 // result: Register for the result. It is only updated if a jump to the miss 114 Register elements,
115 // label is not done. Can be the same as elements or name clobbering 115 Register name,
116 // one of these in the case of not jumping to the miss label. 116 Register scratch1,
117 // The two scratch registers need to be different from elements, name and 117 Register scratch2) {
118 // result.
119 // The generated code assumes that the receiver has slow properties,
120 // is not a global object and does not have interceptors.
121 static void GenerateDictionaryLoad(MacroAssembler* masm,
122 Label* miss,
123 Register elements,
124 Register name,
125 Register result,
126 Register scratch1,
127 Register scratch2) {
128 // Main use of the scratch registers.
129 // scratch1: Used as temporary and to hold the capacity of the property
130 // dictionary.
131 // scratch2: Used as temporary.
132
133 Label done;
134
135 // Compute the capacity mask. 118 // Compute the capacity mask.
136 const int kCapacityOffset = StringDictionary::kHeaderSize + 119 const int kCapacityOffset = StringDictionary::kHeaderSize +
137 StringDictionary::kCapacityIndex * kPointerSize; 120 StringDictionary::kCapacityIndex * kPointerSize;
138 __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset)); 121 __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset));
139 __ mov(scratch1, Operand(scratch1, ASR, kSmiTagSize)); // convert smi to int 122 __ mov(scratch1, Operand(scratch1, ASR, kSmiTagSize)); // convert smi to int
140 __ sub(scratch1, scratch1, Operand(1)); 123 __ sub(scratch1, scratch1, Operand(1));
141 124
142 const int kElementsStartOffset = StringDictionary::kHeaderSize + 125 const int kElementsStartOffset = StringDictionary::kHeaderSize +
143 StringDictionary::kElementsStartIndex * kPointerSize; 126 StringDictionary::kElementsStartIndex * kPointerSize;
144 127
(...skipping 18 matching lines...) Expand all
163 // Scale the index by multiplying by the element size. 146 // Scale the index by multiplying by the element size.
164 ASSERT(StringDictionary::kEntrySize == 3); 147 ASSERT(StringDictionary::kEntrySize == 3);
165 // scratch2 = scratch2 * 3. 148 // scratch2 = scratch2 * 3.
166 __ add(scratch2, scratch2, Operand(scratch2, LSL, 1)); 149 __ add(scratch2, scratch2, Operand(scratch2, LSL, 1));
167 150
168 // Check if the key is identical to the name. 151 // Check if the key is identical to the name.
169 __ add(scratch2, elements, Operand(scratch2, LSL, 2)); 152 __ add(scratch2, elements, Operand(scratch2, LSL, 2));
170 __ ldr(ip, FieldMemOperand(scratch2, kElementsStartOffset)); 153 __ ldr(ip, FieldMemOperand(scratch2, kElementsStartOffset));
171 __ cmp(name, Operand(ip)); 154 __ cmp(name, Operand(ip));
172 if (i != kProbes - 1) { 155 if (i != kProbes - 1) {
173 __ b(eq, &done); 156 __ b(eq, done);
174 } else { 157 } else {
175 __ b(ne, miss); 158 __ b(ne, miss);
176 } 159 }
177 } 160 }
161 }
178 162
179 // Check that the value is a normal property. 163
164 // Helper function used from LoadIC/CallIC GenerateNormal.
165 //
166 // elements: Property dictionary. It is not clobbered if a jump to the miss
167 // label is done.
168 // name: Property name. It is not clobbered if a jump to the miss label is
169 // done
170 // result: Register for the result. It is only updated if a jump to the miss
171 // label is not done. Can be the same as elements or name clobbering
172 // one of these in the case of not jumping to the miss label.
173 // The two scratch registers need to be different from elements, name and
174 // result.
175 // The generated code assumes that the receiver has slow properties,
176 // is not a global object and does not have interceptors.
177 static void GenerateDictionaryLoad(MacroAssembler* masm,
178 Label* miss,
179 Register elements,
180 Register name,
181 Register result,
182 Register scratch1,
183 Register scratch2) {
184 // Main use of the scratch registers.
185 // scratch1: Used as temporary and to hold the capacity of the property
186 // dictionary.
187 // scratch2: Used as temporary.
188 Label done;
189
190 // Probe the dictionary.
191 GenerateStringDictionaryProbes(masm,
192 miss,
193 &done,
194 elements,
195 name,
196 scratch1,
197 scratch2);
198
199 // If probing finds an entry check that the value is a normal
200 // property.
180 __ bind(&done); // scratch2 == elements + 4 * index 201 __ bind(&done); // scratch2 == elements + 4 * index
181 __ ldr(scratch1, 202 const int kElementsStartOffset = StringDictionary::kHeaderSize +
182 FieldMemOperand(scratch2, kElementsStartOffset + 2 * kPointerSize)); 203 StringDictionary::kElementsStartIndex * kPointerSize;
204 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
205 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
183 __ tst(scratch1, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize)); 206 __ tst(scratch1, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize));
184 __ b(ne, miss); 207 __ b(ne, miss);
185 208
186 // Get the value at the masked, scaled index and return. 209 // Get the value at the masked, scaled index and return.
187 __ ldr(result, 210 __ ldr(result,
188 FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); 211 FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize));
189 } 212 }
190 213
191 214
215 // Helper function used from StoreIC::GenerateNormal.
216 //
217 // elements: Property dictionary. It is not clobbered if a jump to the miss
218 // label is done.
219 // name: Property name. It is not clobbered if a jump to the miss label is
220 // done
221 // value: The value to store.
222 // The two scratch registers need to be different from elements, name and
223 // result.
224 // The generated code assumes that the receiver has slow properties,
225 // is not a global object and does not have interceptors.
226 static void GenerateDictionaryStore(MacroAssembler* masm,
227 Label* miss,
228 Register elements,
229 Register name,
230 Register value,
231 Register scratch1,
232 Register scratch2) {
233 // Main use of the scratch registers.
234 // scratch1: Used as temporary and to hold the capacity of the property
235 // dictionary.
236 // scratch2: Used as temporary.
237 Label done;
238
239 // Probe the dictionary.
240 GenerateStringDictionaryProbes(masm,
241 miss,
242 &done,
243 elements,
244 name,
245 scratch1,
246 scratch2);
247
248 // If probing finds an entry in the dictionary check that the value
249 // is a normal property that is not read only.
250 __ bind(&done); // scratch2 == elements + 4 * index
251 const int kElementsStartOffset = StringDictionary::kHeaderSize +
252 StringDictionary::kElementsStartIndex * kPointerSize;
253 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
254 const int kTypeAndReadOnlyMask
255 = (PropertyDetails::TypeField::mask() |
256 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
257 __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
258 __ tst(scratch1, Operand(kTypeAndReadOnlyMask));
259 __ b(ne, miss);
260
261 // Store the value at the masked, scaled index and return.
262 const int kValueOffset = kElementsStartOffset + kPointerSize;
263 __ add(scratch2, scratch2, Operand(kValueOffset - kHeapObjectTag));
264 __ str(value, MemOperand(scratch2));
265
266 // Update the write barrier. Make sure not to clobber the value.
267 __ mov(scratch1, value);
268 __ RecordWrite(elements, scratch2, scratch1);
269 }
270
271
192 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, 272 static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
193 Label* miss, 273 Label* miss,
194 Register elements, 274 Register elements,
195 Register key, 275 Register key,
196 Register result, 276 Register result,
197 Register t0, 277 Register t0,
198 Register t1, 278 Register t1,
199 Register t2) { 279 Register t2) {
200 // Register use: 280 // Register use:
201 // 281 //
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 static void GenerateCallNormal(MacroAssembler* masm, int argc) { 633 static void GenerateCallNormal(MacroAssembler* masm, int argc) {
554 // ----------- S t a t e ------------- 634 // ----------- S t a t e -------------
555 // -- r2 : name 635 // -- r2 : name
556 // -- lr : return address 636 // -- lr : return address
557 // ----------------------------------- 637 // -----------------------------------
558 Label miss; 638 Label miss;
559 639
560 // Get the receiver of the function from the stack into r1. 640 // Get the receiver of the function from the stack into r1.
561 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 641 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
562 642
563 GenerateDictionaryLoadReceiverCheck(masm, r1, r0, r3, r4, &miss); 643 GenerateStringDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss);
564 644
565 // r0: elements 645 // r0: elements
566 // Search the dictionary - put result in register r1. 646 // Search the dictionary - put result in register r1.
567 GenerateDictionaryLoad(masm, &miss, r0, r2, r1, r3, r4); 647 GenerateDictionaryLoad(masm, &miss, r0, r2, r1, r3, r4);
568 648
569 GenerateFunctionTailCall(masm, argc, &miss, r4); 649 GenerateFunctionTailCall(masm, argc, &miss, r4);
570 650
571 __ bind(&miss); 651 __ bind(&miss);
572 } 652 }
573 653
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
808 888
809 void LoadIC::GenerateNormal(MacroAssembler* masm) { 889 void LoadIC::GenerateNormal(MacroAssembler* masm) {
810 // ----------- S t a t e ------------- 890 // ----------- S t a t e -------------
811 // -- r2 : name 891 // -- r2 : name
812 // -- lr : return address 892 // -- lr : return address
813 // -- r0 : receiver 893 // -- r0 : receiver
814 // -- sp[0] : receiver 894 // -- sp[0] : receiver
815 // ----------------------------------- 895 // -----------------------------------
816 Label miss; 896 Label miss;
817 897
818 GenerateDictionaryLoadReceiverCheck(masm, r0, r1, r3, r4, &miss); 898 GenerateStringDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss);
819 899
820 // r1: elements 900 // r1: elements
821 GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4); 901 GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4);
822 __ Ret(); 902 __ Ret();
823 903
824 // Cache miss: Jump to runtime. 904 // Cache miss: Jump to runtime.
825 __ bind(&miss); 905 __ bind(&miss);
826 GenerateMiss(masm); 906 GenerateMiss(masm);
827 } 907 }
828 908
(...skipping 1302 matching lines...) Expand 10 before | Expand all | Expand 10 after
2131 2211
2132 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength)); 2212 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_ArrayLength));
2133 __ TailCallExternalReference(ref, 2, 1); 2213 __ TailCallExternalReference(ref, 2, 1);
2134 2214
2135 __ bind(&miss); 2215 __ bind(&miss);
2136 2216
2137 GenerateMiss(masm); 2217 GenerateMiss(masm);
2138 } 2218 }
2139 2219
2140 2220
2221 void StoreIC::GenerateNormal(MacroAssembler* masm) {
2222 // ----------- S t a t e -------------
2223 // -- r0 : value
2224 // -- r1 : receiver
2225 // -- r2 : name
2226 // -- lr : return address
2227 // -----------------------------------
2228 Label miss;
2229
2230 GenerateStringDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss);
2231
2232 GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5);
2233 __ IncrementCounter(&Counters::store_normal_hit, 1, r4, r5);
2234 __ Ret();
2235
2236 __ bind(&miss);
2237 __ IncrementCounter(&Counters::store_normal_miss, 1, r4, r5);
2238 GenerateMiss(masm);
2239 }
2240
2241
2141 #undef __ 2242 #undef __
2142 2243
2143 2244
2144 } } // namespace v8::internal 2245 } } // namespace v8::internal
2145 2246
2146 #endif // V8_TARGET_ARCH_ARM 2247 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.cc ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698