Commit 6bc979e8 authored by bak@chromium.org's avatar bak@chromium.org

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
parent c15df352
...@@ -437,7 +437,7 @@ void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { ...@@ -437,7 +437,7 @@ void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
// Probe the stub cache. // Probe the stub cache.
Code::Flags flags = Code::Flags flags =
Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); 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. // If the stub cache probing failed, the receiver might be a value.
// For value objects, we use the map of the prototype objects for // For value objects, we use the map of the prototype objects for
...@@ -474,7 +474,7 @@ void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { ...@@ -474,7 +474,7 @@ void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
// Probe the stub cache for the value object. // Probe the stub cache for the value object.
__ bind(&probe); __ bind(&probe);
StubCache::GenerateProbe(masm, flags, edx, ecx, ebx); StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
// Cache miss: Jump to runtime. // Cache miss: Jump to runtime.
__ bind(&miss); __ bind(&miss);
...@@ -648,7 +648,7 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { ...@@ -648,7 +648,7 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
NOT_IN_LOOP, NOT_IN_LOOP,
MONOMORPHIC); MONOMORPHIC);
StubCache::GenerateProbe(masm, flags, eax, ecx, ebx); StubCache::GenerateProbe(masm, flags, eax, ecx, ebx, edx);
// Cache miss: Jump to runtime. // Cache miss: Jump to runtime.
Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
...@@ -878,7 +878,7 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { ...@@ -878,7 +878,7 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
NOT_IN_LOOP, NOT_IN_LOOP,
MONOMORPHIC); MONOMORPHIC);
StubCache::GenerateProbe(masm, flags, edx, ecx, ebx); StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
// Cache miss: Jump to runtime. // Cache miss: Jump to runtime.
Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));
......
...@@ -41,39 +41,61 @@ static void ProbeTable(MacroAssembler* masm, ...@@ -41,39 +41,61 @@ static void ProbeTable(MacroAssembler* masm,
Code::Flags flags, Code::Flags flags,
StubCache::Table table, StubCache::Table table,
Register name, Register name,
Register offset) { Register offset,
Register extra) {
ExternalReference key_offset(SCTableReference::keyReference(table)); ExternalReference key_offset(SCTableReference::keyReference(table));
ExternalReference value_offset(SCTableReference::valueReference(table)); ExternalReference value_offset(SCTableReference::valueReference(table));
Label miss; Label miss;
// Save the offset on the stack. if (extra.is_valid()) {
__ push(offset); // 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. // Check that the key in the entry matches the name.
__ cmp(name, Operand::StaticArray(offset, times_2, key_offset)); __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
__ j(not_equal, &miss, not_taken); __ j(not_equal, &miss, not_taken);
// Get the code entry from the cache. // Check that the flags match what we're looking for.
__ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); __ 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. // Jump to the first instruction in the code stub.
__ mov(offset, FieldOperand(offset, Code::kFlagsOffset)); __ add(Operand(extra), Immediate(Code::kHeaderSize - kHeapObjectTag));
__ and_(offset, ~Code::kFlagsNotUsedInLookup); __ jmp(Operand(extra));
__ cmp(offset, flags);
__ j(not_equal, &miss);
// Restore offset and re-load code entry from cache. __ bind(&miss);
__ pop(offset); } else {
__ mov(offset, Operand::StaticArray(offset, times_2, value_offset)); // Save the offset on the stack.
__ push(offset);
// Jump to the first instruction in the code stub. // Check that the key in the entry matches the name.
__ add(Operand(offset), Immediate(Code::kHeaderSize - kHeapObjectTag)); __ cmp(name, Operand::StaticArray(offset, times_2, key_offset));
__ jmp(Operand(offset)); __ j(not_equal, &miss, not_taken);
// Miss: Restore offset and fall through. // Get the code entry from the cache.
__ bind(&miss); __ mov(offset, Operand::StaticArray(offset, times_2, value_offset));
__ pop(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, ...@@ -81,7 +103,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm,
Code::Flags flags, Code::Flags flags,
Register receiver, Register receiver,
Register name, Register name,
Register scratch) { Register scratch,
Register extra) {
Label miss; Label miss;
// Make sure that code is valid. The shifting code relies on the // Make sure that code is valid. The shifting code relies on the
...@@ -94,6 +117,9 @@ void StubCache::GenerateProbe(MacroAssembler* masm, ...@@ -94,6 +117,9 @@ void StubCache::GenerateProbe(MacroAssembler* masm,
// Make sure that there are no register conflicts. // Make sure that there are no register conflicts.
ASSERT(!scratch.is(receiver)); ASSERT(!scratch.is(receiver));
ASSERT(!scratch.is(name)); ASSERT(!scratch.is(name));
ASSERT(!extra.is(receiver));
ASSERT(!extra.is(name));
ASSERT(!extra.is(scratch));
// Check that the receiver isn't a smi. // Check that the receiver isn't a smi.
__ test(receiver, Immediate(kSmiTagMask)); __ test(receiver, Immediate(kSmiTagMask));
...@@ -106,15 +132,19 @@ void StubCache::GenerateProbe(MacroAssembler* masm, ...@@ -106,15 +132,19 @@ void StubCache::GenerateProbe(MacroAssembler* masm,
__ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
// Probe the primary table. // Probe the primary table.
ProbeTable(masm, flags, kPrimary, name, scratch); ProbeTable(masm, flags, kPrimary, name, scratch, extra);
// Primary miss: Compute hash for secondary probe. // 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)); __ sub(scratch, Operand(name));
__ add(Operand(scratch), Immediate(flags)); __ add(Operand(scratch), Immediate(flags));
__ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize); __ and_(scratch, (kSecondaryTableSize - 1) << kHeapObjectTagSize);
// Probe the secondary table. // 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 // Cache miss: Fall-through and let caller handle the miss by
// entering the runtime system. // entering the runtime system.
......
...@@ -197,11 +197,13 @@ class StubCache : public AllStatic { ...@@ -197,11 +197,13 @@ class StubCache : public AllStatic {
static void GenerateMiss(MacroAssembler* masm); static void GenerateMiss(MacroAssembler* masm);
// Generate code for probing the stub cache table. // 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, static void GenerateProbe(MacroAssembler* masm,
Code::Flags flags, Code::Flags flags,
Register receiver, Register receiver,
Register name, Register name,
Register scratch); Register scratch,
Register extra);
enum Table { enum Table {
kPrimary, kPrimary,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment