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

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

Issue 857003: Probe number dictionaries in generated code on ia32. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 9 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 | « no previous file | no next file » | 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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 __ test(Operand(r0, r1, times_4, kDetailsOffset - kHeapObjectTag), 145 __ test(Operand(r0, r1, times_4, kDetailsOffset - kHeapObjectTag),
146 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); 146 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
147 __ j(not_zero, miss_label, not_taken); 147 __ j(not_zero, miss_label, not_taken);
148 148
149 // Get the value at the masked, scaled index. 149 // Get the value at the masked, scaled index.
150 const int kValueOffset = kElementsStartOffset + kPointerSize; 150 const int kValueOffset = kElementsStartOffset + kPointerSize;
151 __ mov(r1, Operand(r0, r1, times_4, kValueOffset - kHeapObjectTag)); 151 __ mov(r1, Operand(r0, r1, times_4, kValueOffset - kHeapObjectTag));
152 } 152 }
153 153
154 154
155 static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
156 Label* miss,
157 Register elements,
158 Register key,
159 Register r0,
160 Register r1,
161 Register r2) {
162 // Register use:
163 //
164 // elements - holds the slow-case elements of the receiver and is unchanged.
165 //
166 // key - holds the smi key on entry and is unchanged if a branch is
167 // performed to the miss label. If the load succeeds and we
168 // fall through, key holds the result on exit.
169 //
170 // Scratch registers:
171 //
172 // r0 - holds the untagged key on entry and holds the hash once computed.
173 //
174 // r1 - used to hold the capacity mask of the dictionary
175 //
176 // r2 - used for the index into the dictionary.
177 Label done;
178
179 // Compute the hash code from the untagged key. This must be kept in sync
180 // with ComputeIntegerHash in utils.h.
181 //
182 // hash = ~hash + (hash << 15);
183 __ mov(r1, r0);
184 __ not_(r0);
185 __ shl(r1, 15);
186 __ add(r0, Operand(r1));
187 // hash = hash ^ (hash >> 12);
188 __ mov(r1, r0);
189 __ shr(r1, 12);
190 __ xor_(r0, Operand(r1));
191 // hash = hash + (hash << 2);
192 __ lea(r0, Operand(r0, r0, times_4, 0));
193 // hash = hash ^ (hash >> 4);
194 __ mov(r1, r0);
195 __ shr(r1, 4);
196 __ xor_(r0, Operand(r1));
197 // hash = hash * 2057;
198 __ imul(r0, r0, 2057);
199 // hash = hash ^ (hash >> 16);
200 __ mov(r1, r0);
201 __ shr(r1, 16);
202 __ xor_(r0, Operand(r1));
203
204 // Compute capacity mask.
205 const int kCapacityOffset =
206 NumberDictionary::kHeaderSize +
207 NumberDictionary::kCapacityIndex * kPointerSize;
208 __ mov(r1, FieldOperand(elements, kCapacityOffset));
209 __ shr(r1, kSmiTagSize); // convert smi to int
210 __ dec(r1);
211
212 const int kElementsStartOffset =
213 NumberDictionary::kHeaderSize +
214 NumberDictionary::kElementsStartIndex * kPointerSize;
215
216 // Generate an unrolled loop that performs a few probes before giving up.
217 const int kProbes = 4;
218 for (int i = 0; i < kProbes; i++) {
219 // Use r2 for index calculations and keep the hash intact in r0.
220 __ mov(r2, r0);
221 // Compute the masked index: (hash + i + i * i) & mask.
222 if (i > 0) {
223 __ add(Operand(r2), Immediate(NumberDictionary::GetProbeOffset(i)));
224 }
225 __ and_(r2, Operand(r1));
226
227 // Scale the index by multiplying by the entry size.
228 ASSERT(NumberDictionary::kEntrySize == 3);
229 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3
230
231 // Check if the key matches.
232 __ cmp(key, FieldOperand(elements,
233 r2,
234 times_pointer_size,
235 kElementsStartOffset));
236 if (i != (kProbes - 1)) {
237 __ j(equal, &done, taken);
238 } else {
239 __ j(not_equal, miss, not_taken);
240 }
241 }
242
243 __ bind(&done);
244 // Check that the value is a normal propety.
245 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
246 ASSERT_EQ(NORMAL, 0);
247 __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
248 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize));
249 __ j(not_zero, miss);
250
251 // Get the value at the masked, scaled index.
252 const int kValueOffset = kElementsStartOffset + kPointerSize;
253 __ mov(key, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
254 }
255
256
155 // Helper function used to check that a value is either not an object 257 // Helper function used to check that a value is either not an object
156 // or is loaded if it is an object. 258 // or is loaded if it is an object.
157 static void GenerateCheckNonObjectOrLoaded(MacroAssembler* masm, Label* miss, 259 static void GenerateCheckNonObjectOrLoaded(MacroAssembler* masm, Label* miss,
158 Register value, Register scratch) { 260 Register value, Register scratch) {
159 Label done; 261 Label done;
160 // Check if the value is a Smi. 262 // Check if the value is a Smi.
161 __ test(value, Immediate(kSmiTagMask)); 263 __ test(value, Immediate(kSmiTagMask));
162 __ j(zero, &done, not_taken); 264 __ j(zero, &done, not_taken);
163 // Check if the object has been loaded. 265 // Check if the object has been loaded.
164 __ mov(scratch, FieldOperand(value, JSFunction::kMapOffset)); 266 __ mov(scratch, FieldOperand(value, JSFunction::kMapOffset));
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 320
219 321
220 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 322 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
221 // ----------- S t a t e ------------- 323 // ----------- S t a t e -------------
222 // -- eax : key 324 // -- eax : key
223 // -- edx : receiver 325 // -- edx : receiver
224 // -- esp[0] : return address 326 // -- esp[0] : return address
225 // ----------------------------------- 327 // -----------------------------------
226 Label slow, check_string, index_int, index_string; 328 Label slow, check_string, index_int, index_string;
227 Label check_pixel_array, probe_dictionary; 329 Label check_pixel_array, probe_dictionary;
330 Label check_number_dictionary;
228 331
229 // Check that the object isn't a smi. 332 // Check that the object isn't a smi.
230 __ test(edx, Immediate(kSmiTagMask)); 333 __ test(edx, Immediate(kSmiTagMask));
231 __ j(zero, &slow, not_taken); 334 __ j(zero, &slow, not_taken);
232 335
233 // Get the map of the receiver. 336 // Get the map of the receiver.
234 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 337 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
235 338
236 // Check bit field. 339 // Check bit field.
237 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); 340 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset));
(...skipping 28 matching lines...) Expand all
266 __ mov(eax, ecx); 369 __ mov(eax, ecx);
267 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 370 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
268 __ ret(0); 371 __ ret(0);
269 372
270 __ bind(&check_pixel_array); 373 __ bind(&check_pixel_array);
271 // Check whether the elements is a pixel array. 374 // Check whether the elements is a pixel array.
272 // edx: receiver 375 // edx: receiver
273 // ebx: untagged index 376 // ebx: untagged index
274 // eax: key 377 // eax: key
275 // ecx: elements 378 // ecx: elements
276 __ CheckMap(ecx, Factory::pixel_array_map(), &slow, true); 379 __ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true);
277 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); 380 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset));
278 __ j(above_equal, &slow); 381 __ j(above_equal, &slow);
279 __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); 382 __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset));
280 __ movzx_b(eax, Operand(eax, ebx, times_1, 0)); 383 __ movzx_b(eax, Operand(eax, ebx, times_1, 0));
281 __ SmiTag(eax); 384 __ SmiTag(eax);
282 __ ret(0); 385 __ ret(0);
283 386
387 __ bind(&check_number_dictionary);
388 // Check whether the elements is a number dictionary.
389 // edx: receiver
390 // ebx: untagged index
391 // eax: key
392 // ecx: elements
393 __ CheckMap(ecx, Factory::hash_table_map(), &slow, true);
394 Label slow_pop_receiver;
395 // Push receiver on the stack to free up a register for the dictionary
396 // probing.
397 __ push(edx);
398 GenerateNumberDictionaryLoad(masm,
399 &slow_pop_receiver,
400 ecx,
401 eax,
402 ebx,
403 edx,
404 edi);
405 // Pop receiver before returning.
406 __ pop(edx);
407 __ ret(0);
408
409 __ bind(&slow_pop_receiver);
410 // Pop the receiver from the stack and jump to runtime.
411 __ pop(edx);
412
284 __ bind(&slow); 413 __ bind(&slow);
285 // Slow case: jump to runtime. 414 // Slow case: jump to runtime.
286 // edx: receiver 415 // edx: receiver
287 // eax: key 416 // eax: key
288 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 417 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
289 GenerateRuntimeGetProperty(masm); 418 GenerateRuntimeGetProperty(masm);
290 419
291 __ bind(&check_string); 420 __ bind(&check_string);
292 // The key is not a smi. 421 // The key is not a smi.
293 // Is it a string? 422 // Is it a string?
(...skipping 1212 matching lines...) Expand 10 before | Expand all | Expand 10 after
1506 1635
1507 // Do tail-call to runtime routine. 1636 // Do tail-call to runtime routine.
1508 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); 1637 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss));
1509 __ TailCallExternalReference(ref, 3, 1); 1638 __ TailCallExternalReference(ref, 3, 1);
1510 } 1639 }
1511 1640
1512 #undef __ 1641 #undef __
1513 1642
1514 1643
1515 } } // namespace v8::internal 1644 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698