| OLD | NEW | 
|---|
| 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 #include "src/v8.h" | 5 #include "src/v8.h" | 
| 6 | 6 | 
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 | 
| 8 | 8 | 
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" | 
| 10 #include "src/ic/ic.h" | 10 #include "src/ic/ic.h" | 
| 11 #include "src/ic/ic-compiler.h" | 11 #include "src/ic/ic-compiler.h" | 
| 12 #include "src/ic/stub-cache.h" | 12 #include "src/ic/stub-cache.h" | 
| 13 | 13 | 
| 14 namespace v8 { | 14 namespace v8 { | 
| 15 namespace internal { | 15 namespace internal { | 
| 16 | 16 | 
| 17 // ---------------------------------------------------------------------------- | 17 // ---------------------------------------------------------------------------- | 
| 18 // Static IC stub generators. | 18 // Static IC stub generators. | 
| 19 // | 19 // | 
| 20 | 20 | 
| 21 #define __ ACCESS_MASM(masm) | 21 #define __ ACCESS_MASM(masm) | 
| 22 | 22 | 
| 23 |  | 
| 24 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, Register type, |  | 
| 25                                             Label* global_object) { |  | 
| 26   // Register usage: |  | 
| 27   //   type: holds the receiver instance type on entry. |  | 
| 28   __ cmpb(type, Immediate(JS_GLOBAL_OBJECT_TYPE)); |  | 
| 29   __ j(equal, global_object); |  | 
| 30   __ cmpb(type, Immediate(JS_BUILTINS_OBJECT_TYPE)); |  | 
| 31   __ j(equal, global_object); |  | 
| 32   __ cmpb(type, Immediate(JS_GLOBAL_PROXY_TYPE)); |  | 
| 33   __ j(equal, global_object); |  | 
| 34 } |  | 
| 35 |  | 
| 36 |  | 
| 37 // Helper function used to load a property from a dictionary backing storage. | 23 // Helper function used to load a property from a dictionary backing storage. | 
| 38 // This function may return false negatives, so miss_label | 24 // This function may return false negatives, so miss_label | 
| 39 // must always call a backup property load that is complete. | 25 // must always call a backup property load that is complete. | 
| 40 // This function is safe to call if name is not an internalized string, | 26 // This function is safe to call if name is not an internalized string, | 
| 41 // and will jump to the miss_label in that case. | 27 // and will jump to the miss_label in that case. | 
| 42 // The generated code assumes that the receiver has slow properties, | 28 // The generated code assumes that the receiver has slow properties, | 
| 43 // is not a global object and does not have interceptors. | 29 // is not a global object and does not have interceptors. | 
| 44 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label, | 30 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label, | 
| 45                                    Register elements, Register name, | 31                                    Register elements, Register name, | 
| 46                                    Register r0, Register r1, Register result) { | 32                                    Register r0, Register r1, Register result) { | 
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 267   // bit test is enough. | 253   // bit test is enough. | 
| 268   STATIC_ASSERT(kNotInternalizedTag != 0); | 254   STATIC_ASSERT(kNotInternalizedTag != 0); | 
| 269   __ testb(FieldOperand(map, Map::kInstanceTypeOffset), | 255   __ testb(FieldOperand(map, Map::kInstanceTypeOffset), | 
| 270            Immediate(kIsNotInternalizedMask)); | 256            Immediate(kIsNotInternalizedMask)); | 
| 271   __ j(not_zero, not_unique); | 257   __ j(not_zero, not_unique); | 
| 272 | 258 | 
| 273   __ bind(&unique); | 259   __ bind(&unique); | 
| 274 } | 260 } | 
| 275 | 261 | 
| 276 | 262 | 
| 277 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 263 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 
| 278   // The return address is on the stack. | 264   // The return address is on the stack. | 
| 279   Label slow, check_name, index_smi, index_name, property_array_property; | 265   Label slow, check_name, index_smi, index_name, property_array_property; | 
| 280   Label probe_dictionary, check_number_dictionary; | 266   Label probe_dictionary, check_number_dictionary; | 
| 281 | 267 | 
| 282   Register receiver = LoadDescriptor::ReceiverRegister(); | 268   Register receiver = LoadDescriptor::ReceiverRegister(); | 
| 283   Register key = LoadDescriptor::NameRegister(); | 269   Register key = LoadDescriptor::NameRegister(); | 
| 284   DCHECK(receiver.is(rdx)); | 270   DCHECK(receiver.is(rdx)); | 
| 285   DCHECK(key.is(rcx)); | 271   DCHECK(key.is(rcx)); | 
| 286 | 272 | 
| 287   // Check that the key is a smi. | 273   // Check that the key is a smi. | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 325   GenerateKeyedLoadReceiverCheck(masm, receiver, rax, Map::kHasNamedInterceptor, | 311   GenerateKeyedLoadReceiverCheck(masm, receiver, rax, Map::kHasNamedInterceptor, | 
| 326                                  &slow); | 312                                  &slow); | 
| 327 | 313 | 
| 328   // If the receiver is a fast-case object, check the keyed lookup | 314   // If the receiver is a fast-case object, check the keyed lookup | 
| 329   // cache. Otherwise probe the dictionary leaving result in key. | 315   // cache. Otherwise probe the dictionary leaving result in key. | 
| 330   __ movp(rbx, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 316   __ movp(rbx, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 
| 331   __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 317   __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 
| 332                  Heap::kHashTableMapRootIndex); | 318                  Heap::kHashTableMapRootIndex); | 
| 333   __ j(equal, &probe_dictionary); | 319   __ j(equal, &probe_dictionary); | 
| 334 | 320 | 
| 335   // Load the map of the receiver, compute the keyed lookup cache hash |  | 
| 336   // based on 32 bits of the map pointer and the string hash. |  | 
| 337   __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset)); |  | 
| 338   __ movl(rax, rbx); |  | 
| 339   __ shrl(rax, Immediate(KeyedLookupCache::kMapHashShift)); |  | 
| 340   __ movl(rdi, FieldOperand(key, String::kHashFieldOffset)); |  | 
| 341   __ shrl(rdi, Immediate(String::kHashShift)); |  | 
| 342   __ xorp(rax, rdi); |  | 
| 343   int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask); |  | 
| 344   __ andp(rax, Immediate(mask)); |  | 
| 345 | 321 | 
| 346   // Load the key (consisting of map and internalized string) from the cache and | 322   Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | 
| 347   // check for match. | 323       Code::ComputeHandlerFlags(Code::LOAD_IC)); | 
| 348   Label load_in_object_property; | 324   masm->isolate()->stub_cache()->GenerateProbe( | 
| 349   static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; | 325       masm, Code::LOAD_IC, flags, false, receiver, key, rbx, no_reg); | 
| 350   Label hit_on_nth_entry[kEntriesPerBucket]; | 326   // Cache miss. | 
| 351   ExternalReference cache_keys = | 327   GenerateMiss(masm); | 
| 352       ExternalReference::keyed_lookup_cache_keys(masm->isolate()); |  | 
| 353 |  | 
| 354   for (int i = 0; i < kEntriesPerBucket - 1; i++) { |  | 
| 355     Label try_next_entry; |  | 
| 356     __ movp(rdi, rax); |  | 
| 357     __ shlp(rdi, Immediate(kPointerSizeLog2 + 1)); |  | 
| 358     __ LoadAddress(kScratchRegister, cache_keys); |  | 
| 359     int off = kPointerSize * i * 2; |  | 
| 360     __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off)); |  | 
| 361     __ j(not_equal, &try_next_entry); |  | 
| 362     __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize)); |  | 
| 363     __ j(equal, &hit_on_nth_entry[i]); |  | 
| 364     __ bind(&try_next_entry); |  | 
| 365   } |  | 
| 366 |  | 
| 367   int off = kPointerSize * (kEntriesPerBucket - 1) * 2; |  | 
| 368   __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off)); |  | 
| 369   __ j(not_equal, &slow); |  | 
| 370   __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize)); |  | 
| 371   __ j(not_equal, &slow); |  | 
| 372 |  | 
| 373   // Get field offset, which is a 32-bit integer. |  | 
| 374   ExternalReference cache_field_offsets = |  | 
| 375       ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate()); |  | 
| 376 |  | 
| 377   // Hit on nth entry. |  | 
| 378   for (int i = kEntriesPerBucket - 1; i >= 0; i--) { |  | 
| 379     __ bind(&hit_on_nth_entry[i]); |  | 
| 380     if (i != 0) { |  | 
| 381       __ addl(rax, Immediate(i)); |  | 
| 382     } |  | 
| 383     __ LoadAddress(kScratchRegister, cache_field_offsets); |  | 
| 384     __ movl(rdi, Operand(kScratchRegister, rax, times_4, 0)); |  | 
| 385     __ movzxbp(rax, FieldOperand(rbx, Map::kInObjectPropertiesOffset)); |  | 
| 386     __ subp(rdi, rax); |  | 
| 387     __ j(above_equal, &property_array_property); |  | 
| 388     if (i != 0) { |  | 
| 389       __ jmp(&load_in_object_property); |  | 
| 390     } |  | 
| 391   } |  | 
| 392 |  | 
| 393   // Load in-object property. |  | 
| 394   __ bind(&load_in_object_property); |  | 
| 395   __ movzxbp(rax, FieldOperand(rbx, Map::kInstanceSizeOffset)); |  | 
| 396   __ addp(rax, rdi); |  | 
| 397   __ movp(rax, FieldOperand(receiver, rax, times_pointer_size, 0)); |  | 
| 398   __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); |  | 
| 399   __ ret(0); |  | 
| 400 |  | 
| 401   // Load property array property. |  | 
| 402   __ bind(&property_array_property); |  | 
| 403   __ movp(rax, FieldOperand(receiver, JSObject::kPropertiesOffset)); |  | 
| 404   __ movp(rax, |  | 
| 405           FieldOperand(rax, rdi, times_pointer_size, FixedArray::kHeaderSize)); |  | 
| 406   __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); |  | 
| 407   __ ret(0); |  | 
| 408 | 328 | 
| 409   // Do a quick inline probe of the receiver's dictionary, if it | 329   // Do a quick inline probe of the receiver's dictionary, if it | 
| 410   // exists. | 330   // exists. | 
| 411   __ bind(&probe_dictionary); | 331   __ bind(&probe_dictionary); | 
| 412   // rbx: elements | 332   // rbx: elements | 
| 413 | 333 | 
| 414   __ movp(rax, FieldOperand(receiver, JSObject::kMapOffset)); | 334   __ movp(rax, FieldOperand(receiver, JSObject::kMapOffset)); | 
| 415   __ movb(rax, FieldOperand(rax, Map::kInstanceTypeOffset)); | 335   __ movb(rax, FieldOperand(rax, Map::kInstanceTypeOffset)); | 
| 416   GenerateGlobalInstanceTypeCheck(masm, rax, &slow); |  | 
| 417 | 336 | 
| 418   GenerateDictionaryLoad(masm, &slow, rbx, key, rax, rdi, rax); | 337   GenerateDictionaryLoad(masm, &slow, rbx, key, rax, rdi, rax); | 
| 419   __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); | 338   __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); | 
| 420   __ ret(0); | 339   __ ret(0); | 
| 421 | 340 | 
| 422   __ bind(&index_name); | 341   __ bind(&index_name); | 
| 423   __ IndexFromHash(rbx, key); | 342   __ IndexFromHash(rbx, key); | 
| 424   __ jmp(&index_smi); | 343   __ jmp(&index_smi); | 
| 425 } | 344 } | 
| 426 | 345 | 
| (...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1013   Condition cc = | 932   Condition cc = | 
| 1014       (check == ENABLE_INLINED_SMI_CHECK) | 933       (check == ENABLE_INLINED_SMI_CHECK) | 
| 1015           ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 934           ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 
| 1016           : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 935           : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 
| 1017   *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 936   *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 
| 1018 } | 937 } | 
| 1019 } | 938 } | 
| 1020 }  // namespace v8::internal | 939 }  // namespace v8::internal | 
| 1021 | 940 | 
| 1022 #endif  // V8_TARGET_ARCH_X64 | 941 #endif  // V8_TARGET_ARCH_X64 | 
| OLD | NEW | 
|---|