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

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

Issue 1113001: Port number-dictionary probing in generated code to x64. (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 | « src/x64/assembler-x64.cc ('k') | 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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 Smi::FromInt(PropertyDetails::TypeField::mask())); 144 Smi::FromInt(PropertyDetails::TypeField::mask()));
145 __ j(not_zero, miss_label); 145 __ j(not_zero, miss_label);
146 146
147 // Get the value at the masked, scaled index. 147 // Get the value at the masked, scaled index.
148 const int kValueOffset = kElementsStartOffset + kPointerSize; 148 const int kValueOffset = kElementsStartOffset + kPointerSize;
149 __ movq(r1, 149 __ movq(r1,
150 Operand(r0, r1, times_pointer_size, kValueOffset - kHeapObjectTag)); 150 Operand(r0, r1, times_pointer_size, kValueOffset - kHeapObjectTag));
151 } 151 }
152 152
153 153
154 static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
155 Label* miss,
156 Register elements,
157 Register key,
158 Register r0,
159 Register r1,
160 Register r2) {
161 // Register use:
162 //
163 // elements - holds the slow-case elements of the receiver and is unchanged.
164 //
165 // key - holds the smi key on entry and is unchanged if a branch is
166 // performed to the miss label.
167 //
168 // Scratch registers:
169 //
170 // r0 - holds the untagged key on entry and holds the hash once computed.
171 // Holds the result on exit if the load succeeded.
172 //
173 // r1 - used to hold the capacity mask of the dictionary
174 //
175 // r2 - used for the index into the dictionary.
176 Label done;
177
178 // Compute the hash code from the untagged key. This must be kept in sync
179 // with ComputeIntegerHash in utils.h.
180 //
181 // hash = ~hash + (hash << 15);
182 __ movl(r1, r0);
183 __ notl(r0);
184 __ shll(r1, Immediate(15));
185 __ addl(r0, r1);
186 // hash = hash ^ (hash >> 12);
187 __ movl(r1, r0);
188 __ shrl(r1, Immediate(12));
189 __ xorl(r0, r1);
190 // hash = hash + (hash << 2);
191 __ leal(r0, Operand(r0, r0, times_4, 0));
192 // hash = hash ^ (hash >> 4);
193 __ movl(r1, r0);
194 __ shrl(r1, Immediate(4));
195 __ xorl(r0, r1);
196 // hash = hash * 2057;
197 __ imull(r0, r0, Immediate(2057));
198 // hash = hash ^ (hash >> 16);
199 __ movl(r1, r0);
200 __ shrl(r1, Immediate(16));
201 __ xorl(r0, r1);
202
203 // Compute capacity mask.
204 const int kCapacityOffset =
205 StringDictionary::kHeaderSize +
206 StringDictionary::kCapacityIndex * kPointerSize;
207 __ movq(r1, FieldOperand(elements, kCapacityOffset));
208 __ SmiToInteger32(r1, r1);
209 __ decl(r1);
210
211 const int kElementsStartOffset =
212 NumberDictionary::kHeaderSize +
213 NumberDictionary::kElementsStartIndex * kPointerSize;
214
215 // Generate an unrolled loop that performs a few probes before giving up.
216 const int kProbes = 4;
217 for (int i = 0; i < kProbes; i++) {
218 // Use r2 for index calculations and keep the hash intact in r0.
219 __ movq(r2, r0);
220 // Compute the masked index: (hash + i + i * i) & mask.
221 if (i > 0) {
222 __ addl(r2, Immediate(NumberDictionary::GetProbeOffset(i)));
223 }
224 __ and_(r2, r1);
225
226 // Scale the index by multiplying by the entry size.
227 ASSERT(NumberDictionary::kEntrySize == 3);
228 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3
229
230 // Check if the key matches.
231 __ cmpq(key, FieldOperand(elements,
232 r2,
233 times_pointer_size,
234 kElementsStartOffset));
235 if (i != (kProbes - 1)) {
236 __ j(equal, &done);
237 } else {
238 __ j(not_equal, miss);
239 }
240 }
241
242 __ bind(&done);
243 // Check that the value is a normal propety.
244 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
245 ASSERT_EQ(NORMAL, 0);
246 __ Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
247 Smi::FromInt(PropertyDetails::TypeField::mask()));
248 __ j(not_zero, miss);
249
250 // Get the value at the masked, scaled index.
251 const int kValueOffset = kElementsStartOffset + kPointerSize;
252 __ movq(r0, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
253 }
254
255
154 // Helper function used to check that a value is either not an object 256 // Helper function used to check that a value is either not an object
155 // or is loaded if it is an object. 257 // or is loaded if it is an object.
156 static void GenerateCheckNonObjectOrLoaded(MacroAssembler* masm, Label* miss, 258 static void GenerateCheckNonObjectOrLoaded(MacroAssembler* masm, Label* miss,
157 Register value) { 259 Register value) {
158 Label done; 260 Label done;
159 // Check if the value is a Smi. 261 // Check if the value is a Smi.
160 __ JumpIfSmi(value, &done); 262 __ JumpIfSmi(value, &done);
161 // Check if the object has been loaded. 263 // Check if the object has been loaded.
162 __ movq(kScratchRegister, FieldOperand(value, JSFunction::kMapOffset)); 264 __ movq(kScratchRegister, FieldOperand(value, JSFunction::kMapOffset));
163 __ testb(FieldOperand(kScratchRegister, Map::kBitField2Offset), 265 __ testb(FieldOperand(kScratchRegister, Map::kBitField2Offset),
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 366
265 367
266 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 368 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
267 // ----------- S t a t e ------------- 369 // ----------- S t a t e -------------
268 // -- rsp[0] : return address 370 // -- rsp[0] : return address
269 // -- rsp[8] : name 371 // -- rsp[8] : name
270 // -- rsp[16] : receiver 372 // -- rsp[16] : receiver
271 // ----------------------------------- 373 // -----------------------------------
272 Label slow, check_string, index_int, index_string; 374 Label slow, check_string, index_int, index_string;
273 Label check_pixel_array, probe_dictionary; 375 Label check_pixel_array, probe_dictionary;
376 Label check_number_dictionary;
274 377
275 // Load name and receiver. 378 // Load name and receiver.
276 __ movq(rax, Operand(rsp, kPointerSize)); 379 __ movq(rax, Operand(rsp, kPointerSize));
277 __ movq(rcx, Operand(rsp, 2 * kPointerSize)); 380 __ movq(rcx, Operand(rsp, 2 * kPointerSize));
278 381
279 // Check that the object isn't a smi. 382 // Check that the object isn't a smi.
280 __ JumpIfSmi(rcx, &slow); 383 __ JumpIfSmi(rcx, &slow);
281 384
282 // Check that the object is some kind of JS object EXCEPT JS Value type. 385 // Check that the object is some kind of JS object EXCEPT JS Value type.
283 // In the case that the object is a value-wrapper object, 386 // In the case that the object is a value-wrapper object,
284 // we enter the runtime system to make sure that indexing 387 // we enter the runtime system to make sure that indexing
285 // into string objects work as intended. 388 // into string objects work as intended.
286 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 389 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
287 __ CmpObjectType(rcx, JS_OBJECT_TYPE, rdx); 390 __ CmpObjectType(rcx, JS_OBJECT_TYPE, rdx);
288 __ j(below, &slow); 391 __ j(below, &slow);
289 392
290 // Check bit field. 393 // Check bit field.
291 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 394 __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
292 Immediate(kSlowCaseBitFieldMask)); 395 Immediate(kSlowCaseBitFieldMask));
293 __ j(not_zero, &slow); 396 __ j(not_zero, &slow);
294 397
295 // Check that the key is a smi. 398 // Check that the key is a smi.
296 __ JumpIfNotSmi(rax, &check_string); 399 __ JumpIfNotSmi(rax, &check_string);
400 // Save key in rbx in case we want it for the number dictionary
401 // case.
402 __ movq(rbx, rax);
297 __ SmiToInteger32(rax, rax); 403 __ SmiToInteger32(rax, rax);
298 // Get the elements array of the object. 404 // Get the elements array of the object.
299 __ bind(&index_int); 405 __ bind(&index_int);
300 __ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset)); 406 __ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset));
301 // Check that the object is in fast mode (not dictionary). 407 // Check that the object is in fast mode (not dictionary).
302 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 408 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
303 Heap::kFixedArrayMapRootIndex); 409 Heap::kFixedArrayMapRootIndex);
304 __ j(not_equal, &check_pixel_array); 410 __ j(not_equal, &check_pixel_array);
305 // Check that the key (index) is within bounds. 411 // Check that the key (index) is within bounds.
306 __ cmpl(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); 412 __ cmpl(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
307 __ j(above_equal, &slow); // Unsigned comparison rejects negative indices. 413 __ j(above_equal, &slow); // Unsigned comparison rejects negative indices.
308 // Fast case: Do the load. 414 // Fast case: Do the load.
309 __ movq(rax, Operand(rcx, rax, times_pointer_size, 415 __ movq(rax, Operand(rcx, rax, times_pointer_size,
310 FixedArray::kHeaderSize - kHeapObjectTag)); 416 FixedArray::kHeaderSize - kHeapObjectTag));
311 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 417 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
312 // In case the loaded value is the_hole we have to consult GetProperty 418 // In case the loaded value is the_hole we have to consult GetProperty
313 // to ensure the prototype chain is searched. 419 // to ensure the prototype chain is searched.
314 __ j(equal, &slow); 420 __ j(equal, &slow);
315 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 421 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
316 __ ret(0); 422 __ ret(0);
317 423
318 // Check whether the elements is a pixel array. 424 // Check whether the elements is a pixel array.
319 // rax: untagged index 425 // rax: untagged index
320 // rcx: elements array 426 // rcx: elements array
321 __ bind(&check_pixel_array); 427 __ bind(&check_pixel_array);
322 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 428 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
323 Heap::kPixelArrayMapRootIndex); 429 Heap::kPixelArrayMapRootIndex);
324 __ j(not_equal, &slow); 430 __ j(not_equal, &check_number_dictionary);
325 __ cmpl(rax, FieldOperand(rcx, PixelArray::kLengthOffset)); 431 __ cmpl(rax, FieldOperand(rcx, PixelArray::kLengthOffset));
326 __ j(above_equal, &slow); 432 __ j(above_equal, &slow);
327 __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); 433 __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset));
328 __ movzxbq(rax, Operand(rcx, rax, times_1, 0)); 434 __ movzxbq(rax, Operand(rcx, rax, times_1, 0));
329 __ Integer32ToSmi(rax, rax); 435 __ Integer32ToSmi(rax, rax);
330 __ ret(0); 436 __ ret(0);
331 437
438 __ bind(&check_number_dictionary);
439 // Check whether the elements is a number dictionary.
440 // rax: untagged index
441 // rbx: key
442 // rcx: elements
443 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
444 Heap::kHashTableMapRootIndex);
445 __ j(not_equal, &slow);
446 GenerateNumberDictionaryLoad(masm, &slow, rcx, rbx, rax, rdx, rdi);
447 __ ret(0);
448
332 // Slow case: Load name and receiver from stack and jump to runtime. 449 // Slow case: Load name and receiver from stack and jump to runtime.
333 __ bind(&slow); 450 __ bind(&slow);
334 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 451 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
335 GenerateRuntimeGetProperty(masm); 452 GenerateRuntimeGetProperty(masm);
336 __ bind(&check_string); 453 __ bind(&check_string);
337 // The key is not a smi. 454 // The key is not a smi.
338 // Is it a string? 455 // Is it a string?
339 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); 456 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
340 __ j(above_equal, &slow); 457 __ j(above_equal, &slow);
341 // Is the string an array index, with cached numeric value? 458 // Is the string an array index, with cached numeric value?
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1459 __ bind(&miss); 1576 __ bind(&miss);
1460 1577
1461 GenerateMiss(masm); 1578 GenerateMiss(masm);
1462 } 1579 }
1463 1580
1464 1581
1465 #undef __ 1582 #undef __
1466 1583
1467 1584
1468 } } // namespace v8::internal 1585 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698