| 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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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 | 
| OLD | NEW | 
|---|