| OLD | NEW | 
|    1 // Copyright 2013 the V8 project authors. All rights reserved. |    1 // Copyright 2013 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 #if V8_TARGET_ARCH_ARM64 |    5 #if V8_TARGET_ARCH_ARM64 | 
|    6  |    6  | 
|    7 #include "src/codegen.h" |    7 #include "src/codegen.h" | 
|    8 #include "src/ic/ic.h" |    8 #include "src/ic/ic.h" | 
|    9 #include "src/ic/stub-cache.h" |    9 #include "src/ic/stub-cache.h" | 
|   10 #include "src/interface-descriptors.h" |   10 #include "src/interface-descriptors.h" | 
|   11  |   11  | 
|   12 namespace v8 { |   12 namespace v8 { | 
|   13 namespace internal { |   13 namespace internal { | 
|   14  |   14  | 
|   15  |   15  | 
|   16 #define __ ACCESS_MASM(masm) |   16 #define __ ACCESS_MASM(masm) | 
|   17  |   17  | 
|   18  |   18  | 
|   19 // Probe primary or secondary table. |   19 // Probe primary or secondary table. | 
|   20 // If the entry is found in the cache, the generated code jump to the first |   20 // If the entry is found in the cache, the generated code jump to the first | 
|   21 // instruction of the stub in the cache. |   21 // instruction of the stub in the cache. | 
|   22 // If there is a miss the code fall trough. |   22 // If there is a miss the code fall trough. | 
|   23 // |   23 // | 
|   24 // 'receiver', 'name' and 'offset' registers are preserved on miss. |   24 // 'receiver', 'name' and 'offset' registers are preserved on miss. | 
|   25 static void ProbeTable(StubCache* stub_cache, MacroAssembler* masm, |   25 static void ProbeTable(StubCache* stub_cache, MacroAssembler* masm, | 
|   26                        Code::Flags flags, StubCache::Table table, |   26                        StubCache::Table table, Register receiver, Register name, | 
|   27                        Register receiver, Register name, Register offset, |   27                        Register offset, Register scratch, Register scratch2, | 
|   28                        Register scratch, Register scratch2, Register scratch3) { |   28                        Register scratch3) { | 
|   29   // Some code below relies on the fact that the Entry struct contains |   29   // Some code below relies on the fact that the Entry struct contains | 
|   30   // 3 pointers (name, code, map). |   30   // 3 pointers (name, code, map). | 
|   31   STATIC_ASSERT(sizeof(StubCache::Entry) == (3 * kPointerSize)); |   31   STATIC_ASSERT(sizeof(StubCache::Entry) == (3 * kPointerSize)); | 
|   32  |   32  | 
|   33   ExternalReference key_offset(stub_cache->key_reference(table)); |   33   ExternalReference key_offset(stub_cache->key_reference(table)); | 
|   34   ExternalReference value_offset(stub_cache->value_reference(table)); |   34   ExternalReference value_offset(stub_cache->value_reference(table)); | 
|   35   ExternalReference map_offset(stub_cache->map_reference(table)); |   35   ExternalReference map_offset(stub_cache->map_reference(table)); | 
|   36  |   36  | 
|   37   uintptr_t key_off_addr = reinterpret_cast<uintptr_t>(key_offset.address()); |   37   uintptr_t key_off_addr = reinterpret_cast<uintptr_t>(key_offset.address()); | 
|   38   uintptr_t value_off_addr = |   38   uintptr_t value_off_addr = | 
|   39       reinterpret_cast<uintptr_t>(value_offset.address()); |   39       reinterpret_cast<uintptr_t>(value_offset.address()); | 
|   40   uintptr_t map_off_addr = reinterpret_cast<uintptr_t>(map_offset.address()); |   40   uintptr_t map_off_addr = reinterpret_cast<uintptr_t>(map_offset.address()); | 
|   41  |   41  | 
|   42   Label miss; |   42   Label miss; | 
|   43  |   43  | 
|   44   DCHECK(!AreAliased(name, offset, scratch, scratch2, scratch3)); |   44   DCHECK(!AreAliased(name, offset, scratch, scratch2, scratch3)); | 
|   45  |   45  | 
|   46   // Multiply by 3 because there are 3 fields per entry. |   46   // Multiply by 3 because there are 3 fields per entry. | 
|   47   __ Add(scratch3, offset, Operand(offset, LSL, 1)); |   47   __ Add(scratch3, offset, Operand(offset, LSL, 1)); | 
|   48  |   48  | 
|   49   // Calculate the base address of the entry. |   49   // Calculate the base address of the entry. | 
|   50   __ Mov(scratch, key_offset); |   50   __ Mov(scratch, key_offset); | 
|   51   __ Add(scratch, scratch, Operand(scratch3, LSL, kPointerSizeLog2)); |   51   __ Add( | 
 |   52       scratch, scratch, | 
 |   53       Operand(scratch3, LSL, kPointerSizeLog2 - StubCache::kCacheIndexShift)); | 
|   52  |   54  | 
|   53   // Check that the key in the entry matches the name. |   55   // Check that the key in the entry matches the name. | 
|   54   __ Ldr(scratch2, MemOperand(scratch)); |   56   __ Ldr(scratch2, MemOperand(scratch)); | 
|   55   __ Cmp(name, scratch2); |   57   __ Cmp(name, scratch2); | 
|   56   __ B(ne, &miss); |   58   __ B(ne, &miss); | 
|   57  |   59  | 
|   58   // Check the map matches. |   60   // Check the map matches. | 
|   59   __ Ldr(scratch2, MemOperand(scratch, map_off_addr - key_off_addr)); |   61   __ Ldr(scratch2, MemOperand(scratch, map_off_addr - key_off_addr)); | 
|   60   __ Ldr(scratch3, FieldMemOperand(receiver, HeapObject::kMapOffset)); |   62   __ Ldr(scratch3, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 
|   61   __ Cmp(scratch2, scratch3); |   63   __ Cmp(scratch2, scratch3); | 
|   62   __ B(ne, &miss); |   64   __ B(ne, &miss); | 
|   63  |   65  | 
|   64   // Get the code entry from the cache. |   66   // Get the code entry from the cache. | 
|   65   __ Ldr(scratch, MemOperand(scratch, value_off_addr - key_off_addr)); |   67   __ Ldr(scratch, MemOperand(scratch, value_off_addr - key_off_addr)); | 
|   66  |   68  | 
 |   69 #ifdef DEBUG | 
|   67   // Check that the flags match what we're looking for. |   70   // Check that the flags match what we're looking for. | 
 |   71   Code::Flags flags = Code::RemoveHolderFromFlags( | 
 |   72       Code::ComputeHandlerFlags(stub_cache->ic_kind())); | 
|   68   __ Ldr(scratch2.W(), FieldMemOperand(scratch, Code::kFlagsOffset)); |   73   __ Ldr(scratch2.W(), FieldMemOperand(scratch, Code::kFlagsOffset)); | 
|   69   __ Bic(scratch2.W(), scratch2.W(), Code::kFlagsNotUsedInLookup); |   74   __ Bic(scratch2.W(), scratch2.W(), Code::kFlagsNotUsedInLookup); | 
|   70   __ Cmp(scratch2.W(), flags); |   75   __ Cmp(scratch2.W(), flags); | 
|   71   __ B(ne, &miss); |   76   __ B(ne, &miss); | 
 |   77   __ Check(eq, kUnexpectedValue); | 
|   72  |   78  | 
|   73 #ifdef DEBUG |  | 
|   74   if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { |   79   if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { | 
|   75     __ B(&miss); |   80     __ B(&miss); | 
|   76   } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { |   81   } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { | 
|   77     __ B(&miss); |   82     __ B(&miss); | 
|   78   } |   83   } | 
|   79 #endif |   84 #endif | 
|   80  |   85  | 
|   81   // Jump to the first instruction in the code stub. |   86   // Jump to the first instruction in the code stub. | 
|   82   __ Add(scratch, scratch, Code::kHeaderSize - kHeapObjectTag); |   87   __ Add(scratch, scratch, Code::kHeaderSize - kHeapObjectTag); | 
|   83   __ Br(scratch); |   88   __ Br(scratch); | 
|   84  |   89  | 
|   85   // Miss: fall through. |   90   // Miss: fall through. | 
|   86   __ Bind(&miss); |   91   __ Bind(&miss); | 
|   87 } |   92 } | 
|   88  |   93  | 
|   89 void StubCache::GenerateProbe(MacroAssembler* masm, Register receiver, |   94 void StubCache::GenerateProbe(MacroAssembler* masm, Register receiver, | 
|   90                               Register name, Register scratch, Register extra, |   95                               Register name, Register scratch, Register extra, | 
|   91                               Register extra2, Register extra3) { |   96                               Register extra2, Register extra3) { | 
|   92   Code::Flags flags = |  | 
|   93       Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(ic_kind_)); |  | 
|   94  |  | 
|   95   Label miss; |   97   Label miss; | 
|   96  |   98  | 
|   97   // Make sure that there are no register conflicts. |   99   // Make sure that there are no register conflicts. | 
|   98   DCHECK(!AreAliased(receiver, name, scratch, extra, extra2, extra3)); |  100   DCHECK(!AreAliased(receiver, name, scratch, extra, extra2, extra3)); | 
|   99  |  101  | 
|  100   // Make sure extra and extra2 registers are valid. |  102   // Make sure extra and extra2 registers are valid. | 
|  101   DCHECK(!extra.is(no_reg)); |  103   DCHECK(!extra.is(no_reg)); | 
|  102   DCHECK(!extra2.is(no_reg)); |  104   DCHECK(!extra2.is(no_reg)); | 
|  103   DCHECK(!extra3.is(no_reg)); |  105   DCHECK(!extra3.is(no_reg)); | 
|  104  |  106  | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
|  121 #endif |  123 #endif | 
|  122  |  124  | 
|  123   Counters* counters = masm->isolate()->counters(); |  125   Counters* counters = masm->isolate()->counters(); | 
|  124   __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, extra2, |  126   __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, extra2, | 
|  125                       extra3); |  127                       extra3); | 
|  126  |  128  | 
|  127   // Check that the receiver isn't a smi. |  129   // Check that the receiver isn't a smi. | 
|  128   __ JumpIfSmi(receiver, &miss); |  130   __ JumpIfSmi(receiver, &miss); | 
|  129  |  131  | 
|  130   // Compute the hash for primary table. |  132   // Compute the hash for primary table. | 
|  131   __ Ldr(scratch, FieldMemOperand(name, Name::kHashFieldOffset)); |  133   __ Ldr(scratch.W(), FieldMemOperand(name, Name::kHashFieldOffset)); | 
|  132   __ Ldr(extra, FieldMemOperand(receiver, HeapObject::kMapOffset)); |  134   __ Ldr(extra, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 
|  133   __ Add(scratch, scratch, extra); |  135   __ Add(scratch, scratch, extra); | 
|  134   __ Eor(scratch, scratch, flags); |  136   __ Mov(extra, Operand(kPrimaryTableSize - 1)); | 
|  135   // We shift out the last two bits because they are not part of the hash. |  137   __ And(scratch, scratch, Operand(extra, LSL, kCacheIndexShift)); | 
|  136   __ Ubfx(scratch, scratch, kCacheIndexShift, |  | 
|  137           CountTrailingZeros(kPrimaryTableSize, 64)); |  | 
|  138  |  138  | 
|  139   // Probe the primary table. |  139   // Probe the primary table. | 
|  140   ProbeTable(this, masm, flags, kPrimary, receiver, name, scratch, extra, |  140   ProbeTable(this, masm, kPrimary, receiver, name, scratch, extra, extra2, | 
|  141              extra2, extra3); |  141              extra3); | 
|  142  |  142  | 
|  143   // Primary miss: Compute hash for secondary table. |  143   // Primary miss: Compute hash for secondary table. | 
|  144   __ Sub(scratch, scratch, Operand(name, LSR, kCacheIndexShift)); |  144   __ Sub(scratch, scratch, Operand(name)); | 
|  145   __ Add(scratch, scratch, flags >> kCacheIndexShift); |  145   __ Add(scratch, scratch, Operand(kSecondaryMagic)); | 
|  146   __ And(scratch, scratch, kSecondaryTableSize - 1); |  146   __ Mov(extra, Operand(kSecondaryTableSize - 1)); | 
 |  147   __ And(scratch, scratch, Operand(extra, LSL, kCacheIndexShift)); | 
|  147  |  148  | 
|  148   // Probe the secondary table. |  149   // Probe the secondary table. | 
|  149   ProbeTable(this, masm, flags, kSecondary, receiver, name, scratch, extra, |  150   ProbeTable(this, masm, kSecondary, receiver, name, scratch, extra, extra2, | 
|  150              extra2, extra3); |  151              extra3); | 
|  151  |  152  | 
|  152   // Cache miss: Fall-through and let caller handle the miss by |  153   // Cache miss: Fall-through and let caller handle the miss by | 
|  153   // entering the runtime system. |  154   // entering the runtime system. | 
|  154   __ Bind(&miss); |  155   __ Bind(&miss); | 
|  155   __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, extra2, |  156   __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, extra2, | 
|  156                       extra3); |  157                       extra3); | 
|  157 } |  158 } | 
|  158 }  // namespace internal |  159 }  // namespace internal | 
|  159 }  // namespace v8 |  160 }  // namespace v8 | 
|  160  |  161  | 
|  161 #endif  // V8_TARGET_ARCH_ARM64 |  162 #endif  // V8_TARGET_ARCH_ARM64 | 
| OLD | NEW |