From 6bc979e8794f06b7ba793505e72b696b4c3ea64f Mon Sep 17 00:00:00 2001 From: "bak@chromium.org" Date: Fri, 3 Jul 2009 06:34:59 +0000 Subject: [PATCH] Improved code for megamorphic stub on ia32. Review URL: http://codereview.chromium.org/150225 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2342 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ia32/ic-ia32.cc | 8 ++--- src/ia32/stub-cache-ia32.cc | 80 +++++++++++++++++++++++++++++++-------------- src/stub-cache.h | 4 ++- 3 files changed, 62 insertions(+), 30 deletions(-) diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc index fa76dff..1d899ca 100644 --- a/src/ia32/ic-ia32.cc +++ b/src/ia32/ic-ia32.cc @@ -437,7 +437,7 @@ void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { // Probe the stub cache. Code::Flags flags = Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); - StubCache::GenerateProbe(masm, flags, edx, ecx, ebx); + StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax); // If the stub cache probing failed, the receiver might be a value. // For value objects, we use the map of the prototype objects for @@ -474,7 +474,7 @@ void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { // Probe the stub cache for the value object. __ bind(&probe); - StubCache::GenerateProbe(masm, flags, edx, ecx, ebx); + StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); // Cache miss: Jump to runtime. __ bind(&miss); @@ -648,7 +648,7 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, NOT_IN_LOOP, MONOMORPHIC); - StubCache::GenerateProbe(masm, flags, eax, ecx, ebx); + StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx); // Cache miss: Jump to runtime. Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); @@ -878,7 +878,7 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, NOT_IN_LOOP, MONOMORPHIC); - StubCache::GenerateProbe(masm, flags, edx, ecx, ebx); + StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); // Cache miss: Jump to runtime. Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc index 6f84edc..ce4981d 100644 --- a/src/ia32/stub-cache-ia32.cc +++ b/src/ia32/stub-cache-ia32.cc @@ -41,39 +41,61 @@ static void ProbeTable(MacroAssembler* masm, Code::Flags flags, StubCache::Table table, Register name, - Register offset) { + Register offset, + Register extra) { ExternalReference key_offset(SCTableReference::keyReference(table)); ExternalReference value_offset(SCTableReference::valueReference(table)); Label miss; - // Save the offset on the stack. - __ push(offset); + if (extra.is_valid()) { + // Get the code entry from the cache. + __ mov(extra, Operand::StaticArray(offset, times_2, value_offset)); - // Check that the key in the entry matches the name. - __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); - __ j(not_equal, &miss, not_taken); + // Check that the key in the entry matches the name. + __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); + __ j(not_equal, &miss, not_taken); - // Get the code entry from the cache. - __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); + // Check that the flags match what we're looking for. + __ mov(offset, FieldOperand(extra, Code::kFlagsOffset)); + __ and_(offset, ~Code::kFlagsNotUsedInLookup); + __ cmp(offset, flags); + __ j(not_equal, &miss); - // Check that the flags match what we're looking for. - __ mov(offset, FieldOperand(offset, Code::kFlagsOffset)); - __ and_(offset, ~Code::kFlagsNotUsedInLookup); - __ cmp(offset, flags); - __ j(not_equal, &miss); + // Jump to the first instruction in the code stub. + __ add(Operand(extra), Immediate(Code::kHeaderSize - kHeapObjectTag)); + __ jmp(Operand(extra)); - // Restore offset and re-load code entry from cache. - __ pop(offset); - __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); + __ bind(&miss); + } else { + // Save the offset on the stack. + __ push(offset); - // Jump to the first instruction in the code stub. - __ add(Operand(offset), Immediate(Code::kHeaderSize - kHeapObjectTag)); - __ jmp(Operand(offset)); + // Check that the key in the entry matches the name. + __ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); + __ j(not_equal, &miss, not_taken); - // Miss: Restore offset and fall through. - __ bind(&miss); - __ pop(offset); + // Get the code entry from the cache. + __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); + + // Check that the flags match what we're looking for. + __ mov(offset, FieldOperand(offset, Code::kFlagsOffset)); + __ and_(offset, ~Code::kFlagsNotUsedInLookup); + __ cmp(offset, flags); + __ j(not_equal, &miss); + + // Restore offset and re-load code entry from cache. + __ pop(offset); + __ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); + + // Jump to the first instruction in the code stub. + __ add(Operand(offset), Immediate(Code::kHeaderSize - kHeapObjectTag)); + __ jmp(Operand(offset)); + + // Pop at miss. + __ bind(&miss); + __ pop(offset); + } } @@ -81,7 +103,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags, Register receiver, Register name, - Register scratch) { + Register scratch, + Register extra) { Label miss; // Make sure that code is valid. The shifting code relies on the @@ -94,6 +117,9 @@ void StubCache::GenerateProbe(MacroAssembler* masm, // Make sure that there are no register conflicts. ASSERT(!scratch.is(receiver)); ASSERT(!scratch.is(name)); + ASSERT(!extra.is(receiver)); + ASSERT(!extra.is(name)); + ASSERT(!extra.is(scratch)); // Check that the receiver isn't a smi. __ test(receiver, Immediate(kSmiTagMask)); @@ -106,15 +132,19 @@ void StubCache::GenerateProbe(MacroAssembler* masm, __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); // Probe the primary table. - ProbeTable(masm, flags, kPrimary, name, scratch); + ProbeTable(masm, flags, kPrimary, name, scratch, extra); // Primary miss: Compute hash for secondary probe. + __ mov(scratch, FieldOperand(name, String::kLengthOffset)); + __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); + __ xor_(scratch, flags); + __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); __ sub(scratch, Operand(name)); __ add(Operand(scratch), Immediate(flags)); __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize); // Probe the secondary table. - ProbeTable(masm, flags, kSecondary, name, scratch); + ProbeTable(masm, flags, kSecondary, name, scratch, extra); // Cache miss: Fall-through and let caller handle the miss by // entering the runtime system. diff --git a/src/stub-cache.h b/src/stub-cache.h index fff5613..9abf370 100644 --- a/src/stub-cache.h +++ b/src/stub-cache.h @@ -197,11 +197,13 @@ class StubCache : public AllStatic { static void GenerateMiss(MacroAssembler* masm); // Generate code for probing the stub cache table. + // If extra != no_reg it might be used as am extra scratch register. static void GenerateProbe(MacroAssembler* masm, Code::Flags flags, Register receiver, Register name, - Register scratch); + Register scratch, + Register extra); enum Table { kPrimary, -- 2.7.4