MIPS: To aid vector-based load ic work, we need to be able to handle the...

MIPS: To aid vector-based load ic work, we need to be able to handle the megamorphic load case in hydrogen.

Port r23772 (d6d07c5)

Original commit message:
Encapsulate megamorphic load/tail-call in hydrogen.

A simple approach is to wrap the probe activity in a hydrogen instruction.

The instruction is novel in that it always tail-calls away.

BUG=
R=paul.lind@imgtec.com

Review URL: https://codereview.chromium.org/546733003

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23781 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ea42ffe4
......@@ -249,24 +249,6 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
}
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
// The return address is in lr.
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
DCHECK(receiver.is(a1));
DCHECK(name.is(a2));
// Probe the stub cache.
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
Code::ComputeHandlerFlags(Code::LOAD_IC));
masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, a3,
t0, t1, t2);
// Cache miss: Jump to runtime.
GenerateMiss(masm);
}
void LoadIC::GenerateNormal(MacroAssembler* masm) {
Register dictionary = a0;
DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister()));
......@@ -966,8 +948,8 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
// Get the receiver from the stack and probe the stub cache.
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
Code::ComputeHandlerFlags(Code::STORE_IC));
masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, a3,
t0, t1, t2);
masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false, receiver,
name, a3, t0, t1, t2);
// Cache miss: Jump to runtime.
GenerateMiss(masm);
......
......@@ -16,8 +16,8 @@ namespace internal {
static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
Code::Flags flags, StubCache::Table table,
Register receiver, Register name,
Code::Flags flags, bool leave_frame,
StubCache::Table table, Register receiver, Register name,
// Number of the cache entry, not scaled.
Register offset, Register scratch, Register scratch2,
Register offset_scratch) {
......@@ -79,6 +79,8 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
}
#endif
if (leave_frame) __ LeaveFrame(StackFrame::INTERNAL);
// Jump to the first instruction in the code stub.
__ Addu(at, code, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(at);
......@@ -89,9 +91,9 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
Register receiver, Register name,
Register scratch, Register extra, Register extra2,
Register extra3) {
bool leave_frame, Register receiver,
Register name, Register scratch, Register extra,
Register extra2, Register extra3) {
Isolate* isolate = masm->isolate();
Label miss;
......@@ -138,8 +140,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
__ And(scratch, scratch, Operand(mask));
// Probe the primary table.
ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch, extra,
extra2, extra3);
ProbeTable(isolate, masm, flags, leave_frame, kPrimary, receiver, name,
scratch, extra, extra2, extra3);
// Primary miss: Compute hash for secondary probe.
__ srl(at, name, kCacheIndexShift);
......@@ -149,8 +151,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
__ And(scratch, scratch, Operand(mask2));
// Probe the secondary table.
ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch, extra,
extra2, extra3);
ProbeTable(isolate, masm, flags, leave_frame, kSecondary, receiver, name,
scratch, extra, extra2, extra3);
// Cache miss: Fall-through and let caller handle the miss by
// entering the runtime system.
......
......@@ -248,24 +248,6 @@ static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
}
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
// The return address is in lr.
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
DCHECK(receiver.is(a1));
DCHECK(name.is(a2));
// Probe the stub cache.
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
Code::ComputeHandlerFlags(Code::LOAD_IC));
masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, a3,
a4, a5, a6);
// Cache miss: Jump to runtime.
GenerateMiss(masm);
}
void LoadIC::GenerateNormal(MacroAssembler* masm) {
Register dictionary = a0;
DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister()));
......@@ -975,8 +957,8 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
// Get the receiver from the stack and probe the stub cache.
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
Code::ComputeHandlerFlags(Code::STORE_IC));
masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, a3,
a4, a5, a6);
masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false, receiver,
name, a3, a4, a5, a6);
// Cache miss: Jump to runtime.
GenerateMiss(masm);
......
......@@ -16,8 +16,8 @@ namespace internal {
static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
Code::Flags flags, StubCache::Table table,
Register receiver, Register name,
Code::Flags flags, bool leave_frame,
StubCache::Table table, Register receiver, Register name,
// Number of the cache entry, not scaled.
Register offset, Register scratch, Register scratch2,
Register offset_scratch) {
......@@ -79,6 +79,8 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
}
#endif
if (leave_frame) __ LeaveFrame(StackFrame::INTERNAL);
// Jump to the first instruction in the code stub.
__ Daddu(at, code, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(at);
......@@ -89,9 +91,9 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
Register receiver, Register name,
Register scratch, Register extra, Register extra2,
Register extra3) {
bool leave_frame, Register receiver,
Register name, Register scratch, Register extra,
Register extra2, Register extra3) {
Isolate* isolate = masm->isolate();
Label miss;
......@@ -139,8 +141,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
__ And(scratch, scratch, Operand(mask));
// Probe the primary table.
ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch, extra,
extra2, extra3);
ProbeTable(isolate, masm, flags, leave_frame, kPrimary, receiver, name,
scratch, extra, extra2, extra3);
// Primary miss: Compute hash for secondary probe.
__ dsrl(at, name, kCacheIndexShift);
......@@ -150,8 +152,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
__ And(scratch, scratch, Operand(mask2));
// Probe the secondary table.
ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch, extra,
extra2, extra3);
ProbeTable(isolate, masm, flags, leave_frame, kSecondary, receiver, name,
scratch, extra, extra2, extra3);
// Cache miss: Fall-through and let caller handle the miss by
// entering the runtime system.
......
......@@ -30,6 +30,7 @@
#include "src/base/bits.h"
#include "src/code-stubs.h"
#include "src/hydrogen-osr.h"
#include "src/ic/stub-cache.h"
#include "src/mips/lithium-codegen-mips.h"
#include "src/mips/lithium-gap-resolver-mips.h"
......@@ -3934,6 +3935,34 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
}
void LCodeGen::DoTailCallThroughMegamorphicCache(
LTailCallThroughMegamorphicCache* instr) {
Register receiver = ToRegister(instr->receiver());
Register name = ToRegister(instr->name());
DCHECK(receiver.is(LoadDescriptor::ReceiverRegister()));
DCHECK(name.is(LoadDescriptor::NameRegister()));
DCHECK(receiver.is(a1));
DCHECK(name.is(a2));
Register scratch = a3;
Register extra = t0;
Register extra2 = t1;
Register extra3 = t2;
// Important for the tail-call.
bool must_teardown_frame = NeedsEagerFrame();
// The probe will tail call to a handler if found.
isolate()->stub_cache()->GenerateProbe(masm(), instr->hydrogen()->flags(),
must_teardown_frame, receiver, name,
scratch, extra, extra2, extra3);
// Tail call to miss if we ended up here.
if (must_teardown_frame) __ LeaveFrame(StackFrame::INTERNAL);
LoadIC::GenerateMiss(masm());
}
void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
DCHECK(ToRegister(instr->result()).is(v0));
......
......@@ -1104,6 +1104,19 @@ LInstruction* LChunkBuilder::DoCallWithDescriptor(
}
LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
HTailCallThroughMegamorphicCache* instr) {
LOperand* context = UseFixed(instr->context(), cp);
LOperand* receiver_register =
UseFixed(instr->receiver(), LoadDescriptor::ReceiverRegister());
LOperand* name_register =
UseFixed(instr->name(), LoadDescriptor::NameRegister());
// Not marked as call. It can't deoptimize, and it never returns.
return new (zone()) LTailCallThroughMegamorphicCache(
context, receiver_register, name_register);
}
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
LOperand* context = UseFixed(instr->context(), cp);
LOperand* function = UseFixed(instr->function(), a1);
......
......@@ -152,6 +152,7 @@ class LCodeGen;
V(StringCompareAndBranch) \
V(SubI) \
V(TaggedToI) \
V(TailCallThroughMegamorphicCache) \
V(ThisFunction) \
V(ToFastProperties) \
V(TransitionElementsKind) \
......@@ -481,6 +482,27 @@ class LCallStub FINAL : public LTemplateInstruction<1, 1, 0> {
};
class LTailCallThroughMegamorphicCache FINAL
: public LTemplateInstruction<0, 3, 0> {
public:
explicit LTailCallThroughMegamorphicCache(LOperand* context,
LOperand* receiver,
LOperand* name) {
inputs_[0] = context;
inputs_[1] = receiver;
inputs_[2] = name;
}
LOperand* context() { return inputs_[0]; }
LOperand* receiver() { return inputs_[1]; }
LOperand* name() { return inputs_[2]; }
DECLARE_CONCRETE_INSTRUCTION(TailCallThroughMegamorphicCache,
"tail-call-through-megamorphic-cache")
DECLARE_HYDROGEN_ACCESSOR(TailCallThroughMegamorphicCache)
};
class LUnknownOSRValue FINAL : public LTemplateInstruction<1, 0, 0> {
public:
virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
......
......@@ -6,6 +6,7 @@
#include "src/code-stubs.h"
#include "src/hydrogen-osr.h"
#include "src/ic/stub-cache.h"
#include "src/mips64/lithium-codegen-mips64.h"
#include "src/mips64/lithium-gap-resolver-mips64.h"
......@@ -3973,6 +3974,34 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
}
void LCodeGen::DoTailCallThroughMegamorphicCache(
LTailCallThroughMegamorphicCache* instr) {
Register receiver = ToRegister(instr->receiver());
Register name = ToRegister(instr->name());
DCHECK(receiver.is(LoadDescriptor::ReceiverRegister()));
DCHECK(name.is(LoadDescriptor::NameRegister()));
DCHECK(receiver.is(a1));
DCHECK(name.is(a2));
Register scratch = a3;
Register extra = a4;
Register extra2 = a5;
Register extra3 = a6;
// Important for the tail-call.
bool must_teardown_frame = NeedsEagerFrame();
// The probe will tail call to a handler if found.
isolate()->stub_cache()->GenerateProbe(masm(), instr->hydrogen()->flags(),
must_teardown_frame, receiver, name,
scratch, extra, extra2, extra3);
// Tail call to miss if we ended up here.
if (must_teardown_frame) __ LeaveFrame(StackFrame::INTERNAL);
LoadIC::GenerateMiss(masm());
}
void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
DCHECK(ToRegister(instr->result()).is(v0));
......
......@@ -1104,6 +1104,19 @@ LInstruction* LChunkBuilder::DoCallWithDescriptor(
}
LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
HTailCallThroughMegamorphicCache* instr) {
LOperand* context = UseFixed(instr->context(), cp);
LOperand* receiver_register =
UseFixed(instr->receiver(), LoadDescriptor::ReceiverRegister());
LOperand* name_register =
UseFixed(instr->name(), LoadDescriptor::NameRegister());
// Not marked as call. It can't deoptimize, and it never returns.
return new (zone()) LTailCallThroughMegamorphicCache(
context, receiver_register, name_register);
}
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
LOperand* context = UseFixed(instr->context(), cp);
LOperand* function = UseFixed(instr->function(), a1);
......
......@@ -151,6 +151,7 @@ class LCodeGen;
V(StringCompareAndBranch) \
V(SubI) \
V(TaggedToI) \
V(TailCallThroughMegamorphicCache) \
V(ThisFunction) \
V(ToFastProperties) \
V(TransitionElementsKind) \
......@@ -480,6 +481,27 @@ class LCallStub FINAL : public LTemplateInstruction<1, 1, 0> {
};
class LTailCallThroughMegamorphicCache FINAL
: public LTemplateInstruction<0, 3, 0> {
public:
explicit LTailCallThroughMegamorphicCache(LOperand* context,
LOperand* receiver,
LOperand* name) {
inputs_[0] = context;
inputs_[1] = receiver;
inputs_[2] = name;
}
LOperand* context() { return inputs_[0]; }
LOperand* receiver() { return inputs_[1]; }
LOperand* name() { return inputs_[2]; }
DECLARE_CONCRETE_INSTRUCTION(TailCallThroughMegamorphicCache,
"tail-call-through-megamorphic-cache")
DECLARE_HYDROGEN_ACCESSOR(TailCallThroughMegamorphicCache)
};
class LUnknownOSRValue FINAL : public LTemplateInstruction<1, 0, 0> {
public:
virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
......
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