| OLD | NEW | 
 | (Empty) | 
|    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 |  | 
|    3 // found in the LICENSE file. |  | 
|    4  |  | 
|    5 #if V8_TARGET_ARCH_MIPS64 |  | 
|    6  |  | 
|    7 #include "src/codegen.h" |  | 
|    8 #include "src/ic/ic.h" |  | 
|    9 #include "src/ic/stub-cache.h" |  | 
|   10 #include "src/interface-descriptors.h" |  | 
|   11  |  | 
|   12 namespace v8 { |  | 
|   13 namespace internal { |  | 
|   14  |  | 
|   15 #define __ ACCESS_MASM(masm) |  | 
|   16  |  | 
|   17 static void ProbeTable(StubCache* stub_cache, MacroAssembler* masm, |  | 
|   18                        StubCache::Table table, Register receiver, Register name, |  | 
|   19                        // The offset is scaled by 4, based on |  | 
|   20                        // kCacheIndexShift, which is two bits |  | 
|   21                        Register offset, Register scratch, Register scratch2, |  | 
|   22                        Register offset_scratch) { |  | 
|   23   ExternalReference key_offset(stub_cache->key_reference(table)); |  | 
|   24   ExternalReference value_offset(stub_cache->value_reference(table)); |  | 
|   25   ExternalReference map_offset(stub_cache->map_reference(table)); |  | 
|   26  |  | 
|   27   uint64_t key_off_addr = reinterpret_cast<uint64_t>(key_offset.address()); |  | 
|   28   uint64_t value_off_addr = reinterpret_cast<uint64_t>(value_offset.address()); |  | 
|   29   uint64_t map_off_addr = reinterpret_cast<uint64_t>(map_offset.address()); |  | 
|   30  |  | 
|   31   // Check the relative positions of the address fields. |  | 
|   32   DCHECK(value_off_addr > key_off_addr); |  | 
|   33   DCHECK((value_off_addr - key_off_addr) % 4 == 0); |  | 
|   34   DCHECK((value_off_addr - key_off_addr) < (256 * 4)); |  | 
|   35   DCHECK(map_off_addr > key_off_addr); |  | 
|   36   DCHECK((map_off_addr - key_off_addr) % 4 == 0); |  | 
|   37   DCHECK((map_off_addr - key_off_addr) < (256 * 4)); |  | 
|   38  |  | 
|   39   Label miss; |  | 
|   40   Register base_addr = scratch; |  | 
|   41   scratch = no_reg; |  | 
|   42  |  | 
|   43   // Multiply by 3 because there are 3 fields per entry (name, code, map). |  | 
|   44   __ Dlsa(offset_scratch, offset, offset, 1); |  | 
|   45  |  | 
|   46   // Calculate the base address of the entry. |  | 
|   47   __ li(base_addr, Operand(key_offset)); |  | 
|   48   __ Dlsa(base_addr, base_addr, offset_scratch, |  | 
|   49           kPointerSizeLog2 - StubCache::kCacheIndexShift); |  | 
|   50  |  | 
|   51   // Check that the key in the entry matches the name. |  | 
|   52   __ ld(at, MemOperand(base_addr, 0)); |  | 
|   53   __ Branch(&miss, ne, name, Operand(at)); |  | 
|   54  |  | 
|   55   // Check the map matches. |  | 
|   56   __ ld(at, MemOperand(base_addr, |  | 
|   57                        static_cast<int32_t>(map_off_addr - key_off_addr))); |  | 
|   58   __ ld(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset)); |  | 
|   59   __ Branch(&miss, ne, at, Operand(scratch2)); |  | 
|   60  |  | 
|   61   // Get the code entry from the cache. |  | 
|   62   Register code = scratch2; |  | 
|   63   scratch2 = no_reg; |  | 
|   64   __ ld(code, MemOperand(base_addr, |  | 
|   65                          static_cast<int32_t>(value_off_addr - key_off_addr))); |  | 
|   66  |  | 
|   67 #ifdef DEBUG |  | 
|   68   if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { |  | 
|   69     __ jmp(&miss); |  | 
|   70   } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { |  | 
|   71     __ jmp(&miss); |  | 
|   72   } |  | 
|   73 #endif |  | 
|   74  |  | 
|   75   // Jump to the first instruction in the code stub. |  | 
|   76   __ Daddu(at, code, Operand(Code::kHeaderSize - kHeapObjectTag)); |  | 
|   77   __ Jump(at); |  | 
|   78  |  | 
|   79   // Miss: fall through. |  | 
|   80   __ bind(&miss); |  | 
|   81 } |  | 
|   82  |  | 
|   83 void StubCache::GenerateProbe(MacroAssembler* masm, Register receiver, |  | 
|   84                               Register name, Register scratch, Register extra, |  | 
|   85                               Register extra2, Register extra3) { |  | 
|   86   Label miss; |  | 
|   87  |  | 
|   88   // Make sure that code is valid. The multiplying code relies on the |  | 
|   89   // entry size being 12. |  | 
|   90   // DCHECK(sizeof(Entry) == 12); |  | 
|   91   // DCHECK(sizeof(Entry) == 3 * kPointerSize); |  | 
|   92  |  | 
|   93   // Make sure that there are no register conflicts. |  | 
|   94   DCHECK(!AreAliased(receiver, name, scratch, extra, extra2, extra3)); |  | 
|   95  |  | 
|   96   // Check register validity. |  | 
|   97   DCHECK(!scratch.is(no_reg)); |  | 
|   98   DCHECK(!extra.is(no_reg)); |  | 
|   99   DCHECK(!extra2.is(no_reg)); |  | 
|  100   DCHECK(!extra3.is(no_reg)); |  | 
|  101  |  | 
|  102 #ifdef DEBUG |  | 
|  103   // If vector-based ics are in use, ensure that scratch, extra, extra2 and |  | 
|  104   // extra3 don't conflict with the vector and slot registers, which need |  | 
|  105   // to be preserved for a handler call or miss. |  | 
|  106   if (IC::ICUseVector(ic_kind_)) { |  | 
|  107     Register vector, slot; |  | 
|  108     if (ic_kind_ == Code::STORE_IC || ic_kind_ == Code::KEYED_STORE_IC) { |  | 
|  109       vector = StoreWithVectorDescriptor::VectorRegister(); |  | 
|  110       slot = StoreWithVectorDescriptor::SlotRegister(); |  | 
|  111     } else { |  | 
|  112       DCHECK(ic_kind_ == Code::LOAD_IC || ic_kind_ == Code::KEYED_LOAD_IC); |  | 
|  113       vector = LoadWithVectorDescriptor::VectorRegister(); |  | 
|  114       slot = LoadWithVectorDescriptor::SlotRegister(); |  | 
|  115     } |  | 
|  116     DCHECK(!AreAliased(vector, slot, scratch, extra, extra2, extra3)); |  | 
|  117   } |  | 
|  118 #endif |  | 
|  119  |  | 
|  120   Counters* counters = masm->isolate()->counters(); |  | 
|  121   __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, extra2, |  | 
|  122                       extra3); |  | 
|  123  |  | 
|  124   // Check that the receiver isn't a smi. |  | 
|  125   __ JumpIfSmi(receiver, &miss); |  | 
|  126  |  | 
|  127   // Get the map of the receiver and compute the hash. |  | 
|  128   __ lwu(scratch, FieldMemOperand(name, Name::kHashFieldOffset)); |  | 
|  129   __ ld(at, FieldMemOperand(receiver, HeapObject::kMapOffset)); |  | 
|  130   __ Addu(scratch, scratch, at); |  | 
|  131   __ Xor(scratch, scratch, Operand(kPrimaryMagic)); |  | 
|  132   __ And(scratch, scratch, |  | 
|  133          Operand((kPrimaryTableSize - 1) << kCacheIndexShift)); |  | 
|  134  |  | 
|  135   // Probe the primary table. |  | 
|  136   ProbeTable(this, masm, kPrimary, receiver, name, scratch, extra, extra2, |  | 
|  137              extra3); |  | 
|  138  |  | 
|  139   // Primary miss: Compute hash for secondary probe. |  | 
|  140   __ Subu(scratch, scratch, name); |  | 
|  141   __ Addu(scratch, scratch, kSecondaryMagic); |  | 
|  142   __ And(scratch, scratch, |  | 
|  143          Operand((kSecondaryTableSize - 1) << kCacheIndexShift)); |  | 
|  144  |  | 
|  145   // Probe the secondary table. |  | 
|  146   ProbeTable(this, masm, kSecondary, receiver, name, scratch, extra, extra2, |  | 
|  147              extra3); |  | 
|  148  |  | 
|  149   // Cache miss: Fall-through and let caller handle the miss by |  | 
|  150   // entering the runtime system. |  | 
|  151   __ bind(&miss); |  | 
|  152   __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, extra2, |  | 
|  153                       extra3); |  | 
|  154 } |  | 
|  155  |  | 
|  156  |  | 
|  157 #undef __ |  | 
|  158 }  // namespace internal |  | 
|  159 }  // namespace v8 |  | 
|  160  |  | 
|  161 #endif  // V8_TARGET_ARCH_MIPS64 |  | 
| OLD | NEW |