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

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

Issue 2424433002: [ic] Delete old KeyedLoadIC code (Closed)
Patch Set: fix failing test Created 4 years, 2 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
« no previous file with comments | « src/ic/s390/ic-s390.cc ('k') | src/ic/x87/ic-x87.cc » ('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 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_X64 5 #if V8_TARGET_ARCH_X64
6 6
7 #include "src/codegen.h" 7 #include "src/codegen.h"
8 #include "src/ic/ic.h" 8 #include "src/ic/ic.h"
9 #include "src/ic/ic-compiler.h" 9 #include "src/ic/ic-compiler.h"
10 #include "src/ic/stub-cache.h" 10 #include "src/ic/stub-cache.h"
11 11
12 namespace v8 { 12 namespace v8 {
13 namespace internal { 13 namespace internal {
14 14
15 // ---------------------------------------------------------------------------- 15 // ----------------------------------------------------------------------------
16 // Static IC stub generators. 16 // Static IC stub generators.
17 // 17 //
18 18
19 #define __ ACCESS_MASM(masm) 19 #define __ ACCESS_MASM(masm)
20 20
21
22 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, Register type,
23 Label* global_object) {
24 // Register usage:
25 // type: holds the receiver instance type on entry.
26 __ cmpb(type, Immediate(JS_GLOBAL_OBJECT_TYPE));
27 __ j(equal, global_object);
28 __ cmpb(type, Immediate(JS_GLOBAL_PROXY_TYPE));
29 __ j(equal, global_object);
30 }
31
32
33 // Helper function used to load a property from a dictionary backing storage. 21 // Helper function used to load a property from a dictionary backing storage.
34 // This function may return false negatives, so miss_label 22 // This function may return false negatives, so miss_label
35 // must always call a backup property load that is complete. 23 // must always call a backup property load that is complete.
36 // This function is safe to call if name is not an internalized string, 24 // This function is safe to call if name is not an internalized string,
37 // and will jump to the miss_label in that case. 25 // and will jump to the miss_label in that case.
38 // The generated code assumes that the receiver has slow properties, 26 // The generated code assumes that the receiver has slow properties,
39 // is not a global object and does not have interceptors. 27 // is not a global object and does not have interceptors.
40 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label, 28 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label,
41 Register elements, Register name, 29 Register elements, Register name,
42 Register r0, Register r1, Register result) { 30 Register r0, Register r1, Register result) {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 const int kValueOffset = kElementsStartOffset + kPointerSize; 114 const int kValueOffset = kElementsStartOffset + kPointerSize;
127 __ leap(scratch1, Operand(elements, scratch1, times_pointer_size, 115 __ leap(scratch1, Operand(elements, scratch1, times_pointer_size,
128 kValueOffset - kHeapObjectTag)); 116 kValueOffset - kHeapObjectTag));
129 __ movp(Operand(scratch1, 0), value); 117 __ movp(Operand(scratch1, 0), value);
130 118
131 // Update write barrier. Make sure not to clobber the value. 119 // Update write barrier. Make sure not to clobber the value.
132 __ movp(scratch0, value); 120 __ movp(scratch0, value);
133 __ RecordWrite(elements, scratch1, scratch0, kDontSaveFPRegs); 121 __ RecordWrite(elements, scratch1, scratch0, kDontSaveFPRegs);
134 } 122 }
135 123
136
137 // Checks the receiver for special cases (value type, slow case bits).
138 // Falls through for regular JS object.
139 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
140 Register receiver, Register map,
141 int interceptor_bit, Label* slow) {
142 // Register use:
143 // receiver - holds the receiver and is unchanged.
144 // Scratch registers:
145 // map - used to hold the map of the receiver.
146
147 // Check that the object isn't a smi.
148 __ JumpIfSmi(receiver, slow);
149
150 // Check that the object is some kind of JS object EXCEPT JS Value type.
151 // In the case that the object is a value-wrapper object,
152 // we enter the runtime system to make sure that indexing
153 // into string objects work as intended.
154 DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE);
155 __ CmpObjectType(receiver, JS_OBJECT_TYPE, map);
156 __ j(below, slow);
157
158 // Check bit field.
159 __ testb(
160 FieldOperand(map, Map::kBitFieldOffset),
161 Immediate((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)));
162 __ j(not_zero, slow);
163 }
164
165
166 // Loads an indexed element from a fast case array.
167 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
168 Register key, Register elements,
169 Register scratch, Register result,
170 Label* slow) {
171 // Register use:
172 //
173 // receiver - holds the receiver on entry.
174 // Unchanged unless 'result' is the same register.
175 //
176 // key - holds the smi key on entry.
177 // Unchanged unless 'result' is the same register.
178 //
179 // result - holds the result on exit if the load succeeded.
180 // Allowed to be the the same as 'receiver' or 'key'.
181 // Unchanged on bailout so 'receiver' and 'key' can be safely
182 // used by further computation.
183 //
184 // Scratch registers:
185 //
186 // elements - holds the elements of the receiver and its prototypes.
187 //
188 // scratch - used to hold maps, prototypes, and the loaded value.
189 Label check_prototypes, check_next_prototype;
190 Label done, in_bounds, absent;
191
192 __ movp(elements, FieldOperand(receiver, JSObject::kElementsOffset));
193 __ AssertFastElements(elements);
194 // Check that the key (index) is within bounds.
195 __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset));
196 // Unsigned comparison rejects negative indices.
197 __ j(below, &in_bounds);
198
199 // Out-of-bounds. Check the prototype chain to see if we can just return
200 // 'undefined'.
201 __ SmiCompare(key, Smi::kZero);
202 __ j(less, slow); // Negative keys can't take the fast OOB path.
203 __ bind(&check_prototypes);
204 __ movp(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
205 __ bind(&check_next_prototype);
206 __ movp(scratch, FieldOperand(scratch, Map::kPrototypeOffset));
207 // scratch: current prototype
208 __ CompareRoot(scratch, Heap::kNullValueRootIndex);
209 __ j(equal, &absent);
210 __ movp(elements, FieldOperand(scratch, JSObject::kElementsOffset));
211 __ movp(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
212 // elements: elements of current prototype
213 // scratch: map of current prototype
214 __ CmpInstanceType(scratch, JS_OBJECT_TYPE);
215 __ j(below, slow);
216 __ testb(FieldOperand(scratch, Map::kBitFieldOffset),
217 Immediate((1 << Map::kIsAccessCheckNeeded) |
218 (1 << Map::kHasIndexedInterceptor)));
219 __ j(not_zero, slow);
220 __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex);
221 __ j(not_equal, slow);
222 __ jmp(&check_next_prototype);
223
224 __ bind(&absent);
225 __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
226 __ jmp(&done);
227
228 __ bind(&in_bounds);
229 // Fast case: Do the load.
230 SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2);
231 __ movp(scratch, FieldOperand(elements, index.reg, index.scale,
232 FixedArray::kHeaderSize));
233 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex);
234 // In case the loaded value is the_hole we have to check the prototype chain.
235 __ j(equal, &check_prototypes);
236 __ Move(result, scratch);
237 __ bind(&done);
238 }
239
240
241 // Checks whether a key is an array index string or a unique name.
242 // Falls through if the key is a unique name.
243 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
244 Register map, Register hash,
245 Label* index_string, Label* not_unique) {
246 // Register use:
247 // key - holds the key and is unchanged. Assumed to be non-smi.
248 // Scratch registers:
249 // map - used to hold the map of the key.
250 // hash - used to hold the hash of the key.
251 Label unique;
252 __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map);
253 __ j(above, not_unique);
254 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
255 __ j(equal, &unique);
256
257 // Is the string an array index, with cached numeric value?
258 __ movl(hash, FieldOperand(key, Name::kHashFieldOffset));
259 __ testl(hash, Immediate(Name::kContainsCachedArrayIndexMask));
260 __ j(zero, index_string); // The value in hash is used at jump target.
261
262 // Is the string internalized? We already know it's a string so a single
263 // bit test is enough.
264 STATIC_ASSERT(kNotInternalizedTag != 0);
265 __ testb(FieldOperand(map, Map::kInstanceTypeOffset),
266 Immediate(kIsNotInternalizedMask));
267 __ j(not_zero, not_unique);
268
269 __ bind(&unique);
270 }
271
272 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
273 // The return address is on the stack.
274 Label slow, check_name, index_smi, index_name, property_array_property;
275 Label probe_dictionary, check_number_dictionary;
276
277 Register receiver = LoadDescriptor::ReceiverRegister();
278 Register key = LoadDescriptor::NameRegister();
279 DCHECK(receiver.is(rdx));
280 DCHECK(key.is(rcx));
281
282 // Check that the key is a smi.
283 __ JumpIfNotSmi(key, &check_name);
284 __ bind(&index_smi);
285 // Now the key is known to be a smi. This place is also jumped to from below
286 // where a numeric string is converted to a smi.
287
288 GenerateKeyedLoadReceiverCheck(masm, receiver, rax,
289 Map::kHasIndexedInterceptor, &slow);
290
291 // Check the receiver's map to see if it has fast elements.
292 __ CheckFastElements(rax, &check_number_dictionary);
293
294 GenerateFastArrayLoad(masm, receiver, key, rax, rbx, rax, &slow);
295 Counters* counters = masm->isolate()->counters();
296 __ IncrementCounter(counters->ic_keyed_load_generic_smi(), 1);
297 __ ret(0);
298
299 __ bind(&check_number_dictionary);
300 __ SmiToInteger32(rbx, key);
301 __ movp(rax, FieldOperand(receiver, JSObject::kElementsOffset));
302
303 // Check whether the elements is a number dictionary.
304 // rbx: key as untagged int32
305 // rax: elements
306 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
307 Heap::kHashTableMapRootIndex);
308 __ j(not_equal, &slow);
309 __ LoadFromNumberDictionary(&slow, rax, key, rbx, r9, rdi, rax);
310 __ ret(0);
311
312 __ bind(&slow);
313 // Slow case: Jump to runtime.
314 __ IncrementCounter(counters->ic_keyed_load_generic_slow(), 1);
315 KeyedLoadIC::GenerateRuntimeGetProperty(masm);
316
317 __ bind(&check_name);
318 GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow);
319
320 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, Map::kHasNamedInterceptor,
321 &slow);
322
323 // If the receiver is a fast-case object, check the stub cache. Otherwise
324 // probe the dictionary.
325 __ movp(rbx, FieldOperand(receiver, JSObject::kPropertiesOffset));
326 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
327 Heap::kHashTableMapRootIndex);
328 __ j(equal, &probe_dictionary);
329
330 Register megamorphic_scratch = rdi;
331 // The handlers in the stub cache expect a vector and slot. Since we won't
332 // change the IC from any downstream misses, a dummy vector can be used.
333 Register vector = LoadWithVectorDescriptor::VectorRegister();
334 Register slot = LoadDescriptor::SlotRegister();
335 DCHECK(!AreAliased(megamorphic_scratch, vector, slot));
336 Handle<TypeFeedbackVector> dummy_vector =
337 TypeFeedbackVector::DummyVector(masm->isolate());
338 int slot_index = dummy_vector->GetIndex(
339 FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedLoadICSlot));
340 __ Move(vector, dummy_vector);
341 __ Move(slot, Smi::FromInt(slot_index));
342
343 masm->isolate()->load_stub_cache()->GenerateProbe(
344 masm, receiver, key, megamorphic_scratch, no_reg);
345 // Cache miss.
346 GenerateMiss(masm);
347
348 // Do a quick inline probe of the receiver's dictionary, if it
349 // exists.
350 __ bind(&probe_dictionary);
351 // rbx: elements
352
353 __ movp(rax, FieldOperand(receiver, JSObject::kMapOffset));
354 __ movb(rax, FieldOperand(rax, Map::kInstanceTypeOffset));
355 GenerateGlobalInstanceTypeCheck(masm, rax, &slow);
356
357 GenerateDictionaryLoad(masm, &slow, rbx, key, rax, rdi, rax);
358 __ IncrementCounter(counters->ic_keyed_load_generic_symbol(), 1);
359 __ ret(0);
360
361 __ bind(&index_name);
362 __ IndexFromHash(rbx, key);
363 __ jmp(&index_smi);
364 }
365
366
367 static void KeyedStoreGenerateMegamorphicHelper( 124 static void KeyedStoreGenerateMegamorphicHelper(
368 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, 125 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow,
369 KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length) { 126 KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length) {
370 Label transition_smi_elements; 127 Label transition_smi_elements;
371 Label finish_object_store, non_double_value, transition_double_elements; 128 Label finish_object_store, non_double_value, transition_double_elements;
372 Label fast_double_without_map_check; 129 Label fast_double_without_map_check;
373 Register receiver = StoreDescriptor::ReceiverRegister(); 130 Register receiver = StoreDescriptor::ReceiverRegister();
374 Register key = StoreDescriptor::NameRegister(); 131 Register key = StoreDescriptor::NameRegister();
375 Register value = StoreDescriptor::ValueRegister(); 132 Register value = StoreDescriptor::ValueRegister();
376 DCHECK(receiver.is(rdx)); 133 DCHECK(receiver.is(rdx));
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 Condition cc = 597 Condition cc =
841 (check == ENABLE_INLINED_SMI_CHECK) 598 (check == ENABLE_INLINED_SMI_CHECK)
842 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) 599 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero)
843 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); 600 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry);
844 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 601 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
845 } 602 }
846 } // namespace internal 603 } // namespace internal
847 } // namespace v8 604 } // namespace v8
848 605
849 #endif // V8_TARGET_ARCH_X64 606 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/ic/s390/ic-s390.cc ('k') | src/ic/x87/ic-x87.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698