Chromium Code Reviews| Index: src/arm/stub-cache-arm.cc |
| =================================================================== |
| --- src/arm/stub-cache-arm.cc (revision 10860) |
| +++ src/arm/stub-cache-arm.cc (working copy) |
| @@ -43,59 +43,82 @@ |
| MacroAssembler* masm, |
| Code::Flags flags, |
| StubCache::Table table, |
| + Register receiver, |
| Register name, |
| Register offset, |
| - int offset_shift_bits, |
| 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. |
| + __ add(offset_scratch, offset, Operand(offset, LSL, 1)); |
| + |
| + // Calculate the base address of the entry. |
| + __ mov(base_addr, Operand(key_offset)); |
| + __ add(base_addr, base_addr, Operand(offset_scratch, LSL, 1)); |
| + |
| // Check that the key in the entry matches the name. |
| - __ mov(offsets_base_addr, Operand(key_offset)); |
| - __ ldr(ip, MemOperand(offsets_base_addr, offset, LSL, 1 + offset_shift_bits)); |
| + __ ldr(ip, MemOperand(base_addr, 0)); |
| __ cmp(name, ip); |
| __ b(ne, &miss); |
| + // Check the map matches. |
| + __ ldr(ip, MemOperand(base_addr, map_off_addr - key_off_addr)); |
| + __ ldr(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| + __ cmp(ip, scratch2); |
| + __ b(ne, &miss); |
| + |
| // Get the code entry from the cache. |
| - __ add(offsets_base_addr, offsets_base_addr, |
| - Operand(value_off_addr - key_off_addr)); |
| - __ ldr(scratch2, |
| - MemOperand(offsets_base_addr, offset, LSL, 1 + offset_shift_bits)); |
| + Register code = scratch2; |
| + scratch2 = no_reg; |
| + __ ldr(code, MemOperand(base_addr, value_off_addr - key_off_addr)); |
| // Check that the flags match what we're looking for. |
| - __ ldr(scratch2, FieldMemOperand(scratch2, Code::kFlagsOffset)); |
| + Register flags_reg = base_addr; |
| + base_addr = no_reg; |
| + __ ldr(flags_reg, FieldMemOperand(code, Code::kFlagsOffset)); |
| // It's a nice optimization if this constant is encodable in the bic insn. |
| uint32_t mask = Code::kFlagsNotUsedInLookup; |
| ASSERT(__ ImmediateFitsAddrMode1Instruction(mask)); |
| - __ bic(scratch2, scratch2, Operand(mask)); |
| + __ bic(flags_reg, flags_reg, Operand(mask)); |
| // Using cmn and the negative instead of cmp means we can use movw. |
| if (flags < 0) { |
| - __ cmn(scratch2, Operand(-flags)); |
| + __ cmn(flags_reg, Operand(-flags)); |
| } else { |
| - __ cmp(scratch2, Operand(flags)); |
| + __ cmp(flags_reg, Operand(flags)); |
| } |
| __ b(ne, &miss); |
| - // Re-load code entry from cache. |
| - __ ldr(offset, |
| - MemOperand(offsets_base_addr, offset, LSL, 1 + offset_shift_bits)); |
| +#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. |
| - __ add(offset, offset, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| - __ Jump(offset); |
| + __ add(pc, code, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| // Miss: fall through. |
| __ bind(&miss); |
| @@ -167,13 +190,14 @@ |
| 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. |
|
Sven Panne
2012/02/29 09:37:42
Hmmm, I can see multiplication by 3 and a left shi
Erik Corry
2012/02/29 10:45:59
Done.
|
| + ASSERT(sizeof(Entry) == 12); |
| // Make sure the flags does not name a specific type. |
| ASSERT(Code::ExtractTypeFromFlags(flags) == 0); |
| @@ -193,7 +217,12 @@ |
| 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); |
| @@ -214,11 +243,12 @@ |
| masm, |
| flags, |
| kPrimary, |
| + receiver, |
| name, |
| scratch, |
| - 1, |
| extra, |
| - extra2); |
| + extra2, |
| + extra3); |
| // Primary miss: Compute hash for secondary probe. |
| __ sub(scratch, scratch, Operand(name, LSR, 1)); |
| @@ -231,15 +261,18 @@ |
| masm, |
| flags, |
| kSecondary, |
| + receiver, |
| name, |
| scratch, |
| - 1, |
| extra, |
| - extra2); |
| + 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); |
| } |