Fix keyed lookup cache to have 2 entried per bucket instead

of one in order to reduce collisions.
Review URL: https://chromiumcodereview.appspot.com/9269004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10458 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
erik.corry@gmail.com 2012-01-20 13:43:21 +00:00
parent 1f4ec772f7
commit 9672a04de2
6 changed files with 115 additions and 13 deletions

View File

@ -1031,14 +1031,25 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift));
__ ldr(r4, FieldMemOperand(r0, String::kHashFieldOffset));
__ eor(r3, r3, Operand(r4, ASR, String::kHashShift));
__ And(r3, r3, Operand(KeyedLookupCache::kCapacityMask));
int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
__ And(r3, r3, Operand(mask));
// Load the key (consisting of map and symbol) from the cache and
// check for match.
Label try_second_entry, hit_on_first_entry, load_in_object_property;
ExternalReference cache_keys =
ExternalReference::keyed_lookup_cache_keys(isolate);
__ mov(r4, Operand(cache_keys));
__ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1));
// Move r4 to second entry.
__ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex));
__ cmp(r2, r5);
__ b(ne, &try_second_entry);
__ ldr(r5, MemOperand(r4, -kPointerSize)); // Load symbol
__ cmp(r0, r5);
__ b(eq, &hit_on_first_entry);
__ bind(&try_second_entry);
__ ldr(r5, MemOperand(r4, kPointerSize, PostIndex)); // Move r4 to symbol.
__ cmp(r2, r5);
__ b(ne, &slow);
@ -1053,6 +1064,18 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// r3 : lookup cache index
ExternalReference cache_field_offsets =
ExternalReference::keyed_lookup_cache_field_offsets(isolate);
// Hit on second entry.
__ mov(r4, Operand(cache_field_offsets));
__ add(r3, r3, Operand(1));
__ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2));
__ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset));
__ sub(r5, r5, r6, SetCC);
__ b(ge, &property_array_property);
__ jmp(&load_in_object_property);
// Hit on first entry.
__ bind(&hit_on_first_entry);
__ mov(r4, Operand(cache_field_offsets));
__ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2));
__ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset));
@ -1060,6 +1083,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ b(ge, &property_array_property);
// Load in-object property.
__ bind(&load_in_object_property);
__ ldrb(r6, FieldMemOperand(r2, Map::kInstanceSizeOffset));
__ add(r6, r6, r5); // Index from start of object.
__ sub(r1, r1, Operand(kHeapObjectTag)); // Remove the heap tag.

View File

@ -6515,11 +6515,17 @@ int KeyedLookupCache::Hash(Map* map, String* name) {
int KeyedLookupCache::Lookup(Map* map, String* name) {
int index = Hash(map, name);
int index = (Hash(map, name) & kHashMask);
Key& key = keys_[index];
if ((key.map == map) && key.name->Equals(name)) {
return field_offsets_[index];
}
ASSERT(kEntriesPerBucket == 2); // There are two entries to check.
// First entry in the bucket missed, check the second.
Key& key2 = keys_[index + 1];
if ((key2.map == map) && key2.name->Equals(name)) {
return field_offsets_[index + 1];
}
return kNotFound;
}
@ -6527,8 +6533,14 @@ int KeyedLookupCache::Lookup(Map* map, String* name) {
void KeyedLookupCache::Update(Map* map, String* name, int field_offset) {
String* symbol;
if (HEAP->LookupSymbolIfExists(name, &symbol)) {
int index = Hash(map, symbol);
int index = (Hash(map, symbol) & kHashMask);
Key& key = keys_[index];
Key& key2 = keys_[index + 1]; // Second entry in the bucket.
// Demote the first entry to the second in the bucket.
key2.map = key.map;
key2.name = key.name;
field_offsets_[index + 1] = field_offsets_[index];
// Write the new first entry.
key.map = map;
key.name = symbol;
field_offsets_[index] = field_offset;

View File

@ -2135,9 +2135,11 @@ class KeyedLookupCache {
// Clear the cache.
void Clear();
static const int kLength = 64;
static const int kLength = 128;
static const int kCapacityMask = kLength - 1;
static const int kMapHashShift = 2;
static const int kMapHashShift = 5;
static const int kHashMask = -2; // Zero the last bit.
static const int kEntriesPerBucket = 2;
static const int kNotFound = -1;
private:

View File

@ -473,7 +473,6 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
Counters* counters = isolate->counters();
__ IncrementCounter(counters->keyed_load_generic_smi(), 1);
__ ret(0);
__ bind(&check_number_dictionary);
__ mov(ebx, eax);
__ SmiUntag(ebx);
@ -535,15 +534,25 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ mov(edi, FieldOperand(eax, String::kHashFieldOffset));
__ shr(edi, String::kHashShift);
__ xor_(ecx, edi);
__ and_(ecx, KeyedLookupCache::kCapacityMask);
__ and_(ecx, KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
// Load the key (consisting of map and symbol) from the cache and
// check for match.
Label try_second_entry, hit_on_first_entry, load_in_object_property;
ExternalReference cache_keys =
ExternalReference::keyed_lookup_cache_keys(masm->isolate());
__ mov(edi, ecx);
__ shl(edi, kPointerSizeLog2 + 1);
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
__ j(not_equal, &try_second_entry);
__ add(edi, Immediate(kPointerSize));
__ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys));
__ j(equal, &hit_on_first_entry);
__ bind(&try_second_entry);
__ lea(edi, Operand(ecx, 1));
__ shl(edi, kPointerSizeLog2 + 1);
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
__ j(not_equal, &slow);
__ add(edi, Immediate(kPointerSize));
__ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys));
@ -556,6 +565,18 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// ecx : lookup cache index
ExternalReference cache_field_offsets =
ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
// Hit on second entry.
__ add(ecx, Immediate(1));
__ mov(edi,
Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
__ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
__ sub(edi, ecx);
__ j(above_equal, &property_array_property);
__ jmp(&load_in_object_property);
// Hit on first entry.
__ bind(&hit_on_first_entry);
__ mov(edi,
Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
__ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
@ -563,6 +584,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ j(above_equal, &property_array_property);
// Load in-object property.
__ bind(&load_in_object_property);
__ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset));
__ add(ecx, edi);
__ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0));

View File

@ -1033,19 +1033,26 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ lw(t0, FieldMemOperand(a0, String::kHashFieldOffset));
__ sra(at, t0, String::kHashShift);
__ xor_(a3, a3, at);
__ And(a3, a3, Operand(KeyedLookupCache::kCapacityMask));
int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
__ And(a3, a3, Operand(mask));
// Load the key (consisting of map and symbol) from the cache and
// check for match.
Label try_second_entry, hit_on_first_entry, load_in_object_property;
ExternalReference cache_keys =
ExternalReference::keyed_lookup_cache_keys(isolate);
__ li(t0, Operand(cache_keys));
__ sll(at, a3, kPointerSizeLog2 + 1);
__ addu(t0, t0, at);
__ lw(t1, MemOperand(t0)); // Move t0 to symbol.
__ Addu(t0, t0, Operand(kPointerSize));
__ Branch(&slow, ne, a2, Operand(t1));
__ lw(t1, MemOperand(t0));
__ Branch(&try_second_entry, ne, a2, Operand(t1));
__ lw(t1, MemOperand(t0, kPointerSize));
__ Branch(&hit_on_first_entry, eq, a0, Operand(t1));
__ bind(&try_second_entry);
__ lw(t1, MemOperand(t0, kPointerSize * 2));
__ Branch(&slow, ne, a2, Operand(t1));
__ lw(t1, MemOperand(t0, kPointerSize * 3));
__ Branch(&slow, ne, a0, Operand(t1));
// Get field offset.
@ -1055,6 +1062,19 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// a3 : lookup cache index
ExternalReference cache_field_offsets =
ExternalReference::keyed_lookup_cache_field_offsets(isolate);
// Hit on second entry.
__ li(t0, Operand(cache_field_offsets));
__ sll(at, a3, kPointerSizeLog2);
__ addu(at, t0, at);
__ lw(t1, MemOperand(at, kPointerSize));
__ lbu(t2, FieldMemOperand(a2, Map::kInObjectPropertiesOffset));
__ Subu(t1, t1, t2);
__ Branch(&property_array_property, ge, t1, Operand(zero_reg));
__ Branch(&load_in_object_property);
// Hit on first entry.
__ bind(&hit_on_first_entry);
__ li(t0, Operand(cache_field_offsets));
__ sll(at, a3, kPointerSizeLog2);
__ addu(at, t0, at);
@ -1064,6 +1084,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ Branch(&property_array_property, ge, t1, Operand(zero_reg));
// Load in-object property.
__ bind(&load_in_object_property);
__ lbu(t2, FieldMemOperand(a2, Map::kInstanceSizeOffset));
__ addu(t2, t2, t1); // Index from start of object.
__ Subu(a1, a1, Operand(kHeapObjectTag)); // Remove the heap tag.

View File

@ -462,23 +462,43 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ movl(rdi, FieldOperand(rax, String::kHashFieldOffset));
__ shr(rdi, Immediate(String::kHashShift));
__ xor_(rcx, rdi);
__ and_(rcx, Immediate(KeyedLookupCache::kCapacityMask));
int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
__ and_(rcx, Immediate(mask));
// Load the key (consisting of map and symbol) from the cache and
// check for match.
Label try_second_entry, hit_on_first_entry, load_in_object_property;
ExternalReference cache_keys
= ExternalReference::keyed_lookup_cache_keys(masm->isolate());
__ movq(rdi, rcx);
__ shl(rdi, Immediate(kPointerSizeLog2 + 1));
__ LoadAddress(kScratchRegister, cache_keys);
__ cmpq(rbx, Operand(kScratchRegister, rdi, times_1, 0));
__ j(not_equal, &slow);
__ j(not_equal, &try_second_entry);
__ cmpq(rax, Operand(kScratchRegister, rdi, times_1, kPointerSize));
__ j(equal, &hit_on_first_entry);
__ bind(&try_second_entry);
__ cmpq(rbx, Operand(kScratchRegister, rdi, times_1, kPointerSize * 2));
__ j(not_equal, &slow);
__ cmpq(rax, Operand(kScratchRegister, rdi, times_1, kPointerSize * 3));
__ j(not_equal, &slow);
// Get field offset, which is a 32-bit integer.
ExternalReference cache_field_offsets
= ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
// Hit on second entry.
__ LoadAddress(kScratchRegister, cache_field_offsets);
__ addl(rcx, Immediate(1));
__ movl(rdi, Operand(kScratchRegister, rcx, times_4, 0));
__ movzxbq(rcx, FieldOperand(rbx, Map::kInObjectPropertiesOffset));
__ subq(rdi, rcx);
__ j(above_equal, &property_array_property);
__ jmp(&load_in_object_property);
// Hit on first entry.
__ bind(&hit_on_first_entry);
__ LoadAddress(kScratchRegister, cache_field_offsets);
__ movl(rdi, Operand(kScratchRegister, rcx, times_4, 0));
__ movzxbq(rcx, FieldOperand(rbx, Map::kInObjectPropertiesOffset));
@ -486,6 +506,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ j(above_equal, &property_array_property);
// Load in-object property.
__ bind(&load_in_object_property);
__ movzxbq(rcx, FieldOperand(rbx, Map::kInstanceSizeOffset));
__ addq(rcx, rdi);
__ movq(rax, FieldOperand(rdx, rcx, times_pointer_size, 0));