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
This commit is contained in:
parent
c15df35204
commit
6bc979e879
@ -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)));
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user