| Index: src/mips/stub-cache-mips.cc
|
| diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
|
| index b9ab2422aeda98e65977b9060c8e87e0c51c9ad8..fde5ba994c1cf04b7583173da8d38ac1d40adbd5 100644
|
| --- a/src/mips/stub-cache-mips.cc
|
| +++ b/src/mips/stub-cache-mips.cc
|
| @@ -43,51 +43,74 @@ static void ProbeTable(Isolate* isolate,
|
| MacroAssembler* masm,
|
| Code::Flags flags,
|
| StubCache::Table table,
|
| + Register receiver,
|
| Register name,
|
| + // Number of the cache entry, not scaled.
|
| Register offset,
|
| Register scratch,
|
| - Register scratch2) {
|
| + Register scratch2,
|
| + Register offset_scratch) {
|
| ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
|
| ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
|
| + ExternalReference map_offset(isolate->stub_cache()->map_reference(table));
|
|
|
| uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address());
|
| uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address());
|
| + uint32_t map_off_addr = reinterpret_cast<uint32_t>(map_offset.address());
|
|
|
| // Check the relative positions of the address fields.
|
| ASSERT(value_off_addr > key_off_addr);
|
| ASSERT((value_off_addr - key_off_addr) % 4 == 0);
|
| ASSERT((value_off_addr - key_off_addr) < (256 * 4));
|
| + ASSERT(map_off_addr > key_off_addr);
|
| + ASSERT((map_off_addr - key_off_addr) % 4 == 0);
|
| + ASSERT((map_off_addr - key_off_addr) < (256 * 4));
|
|
|
| Label miss;
|
| - Register offsets_base_addr = scratch;
|
| + Register base_addr = scratch;
|
| + scratch = no_reg;
|
| +
|
| + // Multiply by 3 because there are 3 fields per entry (name, code, map).
|
| + __ sll(offset_scratch, offset, 1);
|
| + __ Addu(offset_scratch, offset_scratch, offset);
|
| +
|
| + // Calculate the base address of the entry.
|
| + __ li(base_addr, Operand(key_offset));
|
| + __ sll(at, offset_scratch, kPointerSizeLog2);
|
| + __ Addu(base_addr, base_addr, at);
|
|
|
| // Check that the key in the entry matches the name.
|
| - __ li(offsets_base_addr, Operand(key_offset));
|
| - __ sll(scratch2, offset, 1);
|
| - __ addu(scratch2, offsets_base_addr, scratch2);
|
| - __ lw(scratch2, MemOperand(scratch2));
|
| - __ Branch(&miss, ne, name, Operand(scratch2));
|
| + __ lw(at, MemOperand(base_addr, 0));
|
| + __ Branch(&miss, ne, name, Operand(at));
|
| +
|
| + // Check the map matches.
|
| + __ lw(at, MemOperand(base_addr, map_off_addr - key_off_addr));
|
| + __ lw(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
| + __ Branch(&miss, ne, at, Operand(scratch2));
|
|
|
| // Get the code entry from the cache.
|
| - __ Addu(offsets_base_addr, offsets_base_addr,
|
| - Operand(value_off_addr - key_off_addr));
|
| - __ sll(scratch2, offset, 1);
|
| - __ addu(scratch2, offsets_base_addr, scratch2);
|
| - __ lw(scratch2, MemOperand(scratch2));
|
| + Register code = scratch2;
|
| + scratch2 = no_reg;
|
| + __ lw(code, MemOperand(base_addr, value_off_addr - key_off_addr));
|
|
|
| // Check that the flags match what we're looking for.
|
| - __ lw(scratch2, FieldMemOperand(scratch2, Code::kFlagsOffset));
|
| - __ And(scratch2, scratch2, Operand(~Code::kFlagsNotUsedInLookup));
|
| - __ Branch(&miss, ne, scratch2, Operand(flags));
|
| + Register flags_reg = base_addr;
|
| + base_addr = no_reg;
|
| + __ lw(flags_reg, FieldMemOperand(code, Code::kFlagsOffset));
|
| + __ And(flags_reg, flags_reg, Operand(~Code::kFlagsNotUsedInLookup));
|
| + __ Branch(&miss, ne, flags_reg, Operand(flags));
|
|
|
| - // Re-load code entry from cache.
|
| - __ sll(offset, offset, 1);
|
| - __ addu(offset, offset, offsets_base_addr);
|
| - __ lw(offset, MemOperand(offset));
|
| +#ifdef DEBUG
|
| + if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
|
| + __ jmp(&miss);
|
| + } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
|
| + __ jmp(&miss);
|
| + }
|
| +#endif
|
|
|
| // Jump to the first instruction in the code stub.
|
| - __ Addu(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag));
|
| - __ Jump(offset);
|
| + __ Addu(at, code, Operand(Code::kHeaderSize - kHeapObjectTag));
|
| + __ Jump(at);
|
|
|
| // Miss: fall through.
|
| __ bind(&miss);
|
| @@ -157,13 +180,14 @@ void StubCache::GenerateProbe(MacroAssembler* masm,
|
| Register name,
|
| Register scratch,
|
| Register extra,
|
| - Register extra2) {
|
| + Register extra2,
|
| + Register extra3) {
|
| Isolate* isolate = masm->isolate();
|
| Label miss;
|
|
|
| - // Make sure that code is valid. The shifting code relies on the
|
| - // entry size being 8.
|
| - ASSERT(sizeof(Entry) == 8);
|
| + // Make sure that code is valid. The multiplying code relies on the
|
| + // entry size being 12.
|
| + ASSERT(sizeof(Entry) == 12);
|
|
|
| // Make sure the flags does not name a specific type.
|
| ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
|
| @@ -179,39 +203,66 @@ void StubCache::GenerateProbe(MacroAssembler* masm,
|
| ASSERT(!extra2.is(scratch));
|
| ASSERT(!extra2.is(extra));
|
|
|
| - // Check scratch, extra and extra2 registers are valid.
|
| + // Check register validity.
|
| ASSERT(!scratch.is(no_reg));
|
| ASSERT(!extra.is(no_reg));
|
| ASSERT(!extra2.is(no_reg));
|
| + ASSERT(!extra3.is(no_reg));
|
| +
|
| + Counters* counters = masm->isolate()->counters();
|
| + __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1,
|
| + extra2, extra3);
|
|
|
| // Check that the receiver isn't a smi.
|
| - __ JumpIfSmi(receiver, &miss, t0);
|
| + __ JumpIfSmi(receiver, &miss);
|
|
|
| // Get the map of the receiver and compute the hash.
|
| __ lw(scratch, FieldMemOperand(name, String::kHashFieldOffset));
|
| - __ lw(t8, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
| - __ Addu(scratch, scratch, Operand(t8));
|
| - __ Xor(scratch, scratch, Operand(flags));
|
| - __ And(scratch,
|
| - scratch,
|
| - Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize));
|
| + __ lw(at, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
| + __ Addu(scratch, scratch, at);
|
| + uint32_t mask = kPrimaryTableSize - 1;
|
| + // We shift out the last two bits because they are not part of the hash and
|
| + // they are always 01 for maps.
|
| + __ srl(scratch, scratch, kHeapObjectTagSize);
|
| + __ Xor(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask));
|
| + __ And(scratch, scratch, Operand(mask));
|
|
|
| // Probe the primary table.
|
| - ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra, extra2);
|
| + ProbeTable(isolate,
|
| + masm,
|
| + flags,
|
| + kPrimary,
|
| + receiver,
|
| + name,
|
| + scratch,
|
| + extra,
|
| + extra2,
|
| + extra3);
|
|
|
| // Primary miss: Compute hash for secondary probe.
|
| - __ Subu(scratch, scratch, Operand(name));
|
| - __ Addu(scratch, scratch, Operand(flags));
|
| - __ And(scratch,
|
| - scratch,
|
| - Operand((kSecondaryTableSize - 1) << kHeapObjectTagSize));
|
| + __ srl(at, name, kHeapObjectTagSize);
|
| + __ Subu(scratch, scratch, at);
|
| + uint32_t mask2 = kSecondaryTableSize - 1;
|
| + __ Addu(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask2));
|
| + __ And(scratch, scratch, Operand(mask2));
|
|
|
| // Probe the secondary table.
|
| - ProbeTable(isolate, masm, flags, kSecondary, name, scratch, extra, extra2);
|
| + ProbeTable(isolate,
|
| + masm,
|
| + flags,
|
| + kSecondary,
|
| + receiver,
|
| + name,
|
| + scratch,
|
| + extra,
|
| + extra2,
|
| + extra3);
|
|
|
| // Cache miss: Fall-through and let caller handle the miss by
|
| // entering the runtime system.
|
| __ bind(&miss);
|
| + __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1,
|
| + extra2, extra3);
|
| }
|
|
|
|
|
|
|