OLD | NEW |
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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 __ j(equal, miss_label, not_taken); | 82 __ j(equal, miss_label, not_taken); |
83 | 83 |
84 // Check that the properties array is a dictionary. | 84 // Check that the properties array is a dictionary. |
85 __ mov(r0, FieldOperand(r1, JSObject::kPropertiesOffset)); | 85 __ mov(r0, FieldOperand(r1, JSObject::kPropertiesOffset)); |
86 __ cmp(FieldOperand(r0, HeapObject::kMapOffset), | 86 __ cmp(FieldOperand(r0, HeapObject::kMapOffset), |
87 Immediate(Factory::hash_table_map())); | 87 Immediate(Factory::hash_table_map())); |
88 __ j(not_equal, miss_label); | 88 __ j(not_equal, miss_label); |
89 | 89 |
90 // Compute the capacity mask. | 90 // Compute the capacity mask. |
91 const int kCapacityOffset = | 91 const int kCapacityOffset = |
92 Array::kHeaderSize + StringDictionary::kCapacityIndex * kPointerSize; | 92 StringDictionary::kHeaderSize + |
| 93 StringDictionary::kCapacityIndex * kPointerSize; |
93 __ mov(r2, FieldOperand(r0, kCapacityOffset)); | 94 __ mov(r2, FieldOperand(r0, kCapacityOffset)); |
94 __ shr(r2, kSmiTagSize); // convert smi to int | 95 __ shr(r2, kSmiTagSize); // convert smi to int |
95 __ dec(r2); | 96 __ dec(r2); |
96 | 97 |
97 // Generate an unrolled loop that performs a few probes before | 98 // Generate an unrolled loop that performs a few probes before |
98 // giving up. Measurements done on Gmail indicate that 2 probes | 99 // giving up. Measurements done on Gmail indicate that 2 probes |
99 // cover ~93% of loads from dictionaries. | 100 // cover ~93% of loads from dictionaries. |
100 static const int kProbes = 4; | 101 static const int kProbes = 4; |
101 const int kElementsStartOffset = | 102 const int kElementsStartOffset = |
102 Array::kHeaderSize + StringDictionary::kElementsStartIndex * kPointerSize; | 103 StringDictionary::kHeaderSize + |
| 104 StringDictionary::kElementsStartIndex * kPointerSize; |
103 for (int i = 0; i < kProbes; i++) { | 105 for (int i = 0; i < kProbes; i++) { |
104 // Compute the masked index: (hash + i + i * i) & mask. | 106 // Compute the masked index: (hash + i + i * i) & mask. |
105 __ mov(r1, FieldOperand(name, String::kLengthOffset)); | 107 __ mov(r1, FieldOperand(name, String::kLengthOffset)); |
106 __ shr(r1, String::kHashShift); | 108 __ shr(r1, String::kHashShift); |
107 if (i > 0) { | 109 if (i > 0) { |
108 __ add(Operand(r1), Immediate(StringDictionary::GetProbeOffset(i))); | 110 __ add(Operand(r1), Immediate(StringDictionary::GetProbeOffset(i))); |
109 } | 111 } |
110 __ and_(r1, Operand(r2)); | 112 __ and_(r1, Operand(r2)); |
111 | 113 |
112 // Scale the index by multiplying by the entry size. | 114 // Scale the index by multiplying by the entry size. |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 __ j(not_zero, &check_string, not_taken); | 261 __ j(not_zero, &check_string, not_taken); |
260 __ sar(eax, kSmiTagSize); | 262 __ sar(eax, kSmiTagSize); |
261 // Get the elements array of the object. | 263 // Get the elements array of the object. |
262 __ bind(&index_int); | 264 __ bind(&index_int); |
263 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); | 265 __ mov(ecx, FieldOperand(ecx, JSObject::kElementsOffset)); |
264 // Check that the object is in fast mode (not dictionary). | 266 // Check that the object is in fast mode (not dictionary). |
265 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 267 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
266 Immediate(Factory::hash_table_map())); | 268 Immediate(Factory::hash_table_map())); |
267 __ j(equal, &slow, not_taken); | 269 __ j(equal, &slow, not_taken); |
268 // Check that the key (index) is within bounds. | 270 // Check that the key (index) is within bounds. |
269 __ cmp(eax, FieldOperand(ecx, Array::kLengthOffset)); | 271 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); |
270 __ j(below, &fast, taken); | 272 __ j(below, &fast, taken); |
271 // Slow case: Load name and receiver from stack and jump to runtime. | 273 // Slow case: Load name and receiver from stack and jump to runtime. |
272 __ bind(&slow); | 274 __ bind(&slow); |
273 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); | 275 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); |
274 KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); | 276 KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kKeyedGetProperty)); |
275 // Check if the key is a symbol that is not an array index. | 277 // Check if the key is a symbol that is not an array index. |
276 __ bind(&check_string); | 278 __ bind(&check_string); |
277 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); | 279 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); |
278 __ test(ebx, Immediate(String::kIsArrayIndexMask)); | 280 __ test(ebx, Immediate(String::kIsArrayIndexMask)); |
279 __ j(not_zero, &index_string, not_taken); | 281 __ j(not_zero, &index_string, not_taken); |
(...skipping 17 matching lines...) Expand all Loading... |
297 const int kLengthFieldLimit = | 299 const int kLengthFieldLimit = |
298 (String::kMaxCachedArrayIndexLength + 1) << String::kShortLengthShift; | 300 (String::kMaxCachedArrayIndexLength + 1) << String::kShortLengthShift; |
299 __ cmp(ebx, kLengthFieldLimit); | 301 __ cmp(ebx, kLengthFieldLimit); |
300 __ j(above_equal, &slow); | 302 __ j(above_equal, &slow); |
301 __ mov(eax, Operand(ebx)); | 303 __ mov(eax, Operand(ebx)); |
302 __ and_(eax, (1 << String::kShortLengthShift) - 1); | 304 __ and_(eax, (1 << String::kShortLengthShift) - 1); |
303 __ shr(eax, String::kLongLengthShift); | 305 __ shr(eax, String::kLongLengthShift); |
304 __ jmp(&index_int); | 306 __ jmp(&index_int); |
305 // Fast case: Do the load. | 307 // Fast case: Do the load. |
306 __ bind(&fast); | 308 __ bind(&fast); |
307 __ mov(eax, Operand(ecx, eax, times_4, Array::kHeaderSize - kHeapObjectTag)); | 309 __ mov(eax, |
| 310 Operand(ecx, eax, times_4, FixedArray::kHeaderSize - kHeapObjectTag)); |
308 __ cmp(Operand(eax), Immediate(Factory::the_hole_value())); | 311 __ cmp(Operand(eax), Immediate(Factory::the_hole_value())); |
309 // In case the loaded value is the_hole we have to consult GetProperty | 312 // In case the loaded value is the_hole we have to consult GetProperty |
310 // to ensure the prototype chain is searched. | 313 // to ensure the prototype chain is searched. |
311 __ j(equal, &slow, not_taken); | 314 __ j(equal, &slow, not_taken); |
312 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); | 315 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); |
313 __ ret(0); | 316 __ ret(0); |
314 } | 317 } |
315 | 318 |
316 | 319 |
317 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 320 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 // address to store into and fall through to fast case. | 418 // address to store into and fall through to fast case. |
416 __ cmp(ebx, FieldOperand(edx, JSArray::kLengthOffset)); | 419 __ cmp(ebx, FieldOperand(edx, JSArray::kLengthOffset)); |
417 __ j(above_equal, &extra, not_taken); | 420 __ j(above_equal, &extra, not_taken); |
418 | 421 |
419 | 422 |
420 // Fast case: Do the store. | 423 // Fast case: Do the store. |
421 __ bind(&fast); | 424 __ bind(&fast); |
422 // eax: value | 425 // eax: value |
423 // ecx: FixedArray | 426 // ecx: FixedArray |
424 // ebx: index (as a smi) | 427 // ebx: index (as a smi) |
425 __ mov(Operand(ecx, ebx, times_2, Array::kHeaderSize - kHeapObjectTag), eax); | 428 __ mov(Operand(ecx, ebx, times_2, FixedArray::kHeaderSize - kHeapObjectTag), |
| 429 eax); |
426 // Update write barrier for the elements array address. | 430 // Update write barrier for the elements array address. |
427 __ mov(edx, Operand(eax)); | 431 __ mov(edx, Operand(eax)); |
428 __ RecordWrite(ecx, 0, edx, ebx); | 432 __ RecordWrite(ecx, 0, edx, ebx); |
429 __ ret(0); | 433 __ ret(0); |
430 } | 434 } |
431 | 435 |
432 | 436 |
433 // Defined in ic.cc. | 437 // Defined in ic.cc. |
434 Object* CallIC_Miss(Arguments args); | 438 Object* CallIC_Miss(Arguments args); |
435 | 439 |
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
975 | 979 |
976 // Do tail-call to runtime routine. | 980 // Do tail-call to runtime routine. |
977 __ TailCallRuntime( | 981 __ TailCallRuntime( |
978 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); | 982 ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); |
979 } | 983 } |
980 | 984 |
981 #undef __ | 985 #undef __ |
982 | 986 |
983 | 987 |
984 } } // namespace v8::internal | 988 } } // namespace v8::internal |
OLD | NEW |