Updates to maintain flag --vector-ics

Experimental feature vector-ics needs some maintenance.

R=yangguo@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24458 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mvstanton@chromium.org 2014-10-08 09:15:09 +00:00
parent 3d7bd81ea3
commit 8faca47ef2
18 changed files with 164 additions and 53 deletions

View File

@ -178,7 +178,11 @@ void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC load (from ic-arm.cc).
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0);
RegList regs = receiver.bit() | name.bit();
if (FLAG_vector_ics) {
regs |= VectorLoadICTrampolineDescriptor::SlotRegister().bit();
}
Generate_DebugBreakCallHelper(masm, regs, 0);
}

View File

@ -1364,7 +1364,13 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ Move(LoadDescriptor::NameRegister(), home_object_symbol);
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
if (FLAG_vector_ics) {
__ mov(VectorLoadICDescriptor::SlotRegister(),
Operand(Smi::FromInt(expr->HomeObjectFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
} else {
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
}
__ cmp(r0, Operand(isolate()->factory()->undefined_value()));
Label done;

View File

@ -238,7 +238,11 @@ void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC load (from ic-arm.cc).
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
Generate_DebugBreakCallHelper(masm, receiver.Bit() | name.Bit(), 0, x10);
RegList regs = receiver.Bit() | name.Bit();
if (FLAG_vector_ics) {
regs |= VectorLoadICTrampolineDescriptor::SlotRegister().Bit();
}
Generate_DebugBreakCallHelper(masm, regs, 0, x10);
}

View File

@ -1350,7 +1350,13 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ Mov(LoadDescriptor::NameRegister(), Operand(home_object_symbol));
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
if (FLAG_vector_ics) {
__ Mov(VectorLoadICDescriptor::SlotRegister(),
Smi::FromInt(expr->HomeObjectFeedbackSlot()));
CallLoadIC(NOT_CONTEXTUAL);
} else {
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
}
__ Mov(x10, Operand(isolate()->factory()->undefined_value()));
__ cmp(x0, x10);

View File

@ -1026,6 +1026,14 @@ CaseClause::CaseClause(Zone* zone, Expression* label,
set_dont_turbofan_reason(k##NodeType); \
add_flag(kDontSelfOptimize); \
}
#define DONT_TURBOFAN_NODE_WITH_FEEDBACK_SLOTS(NodeType) \
void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
increase_node_count(); \
add_slot_node(node); \
set_dont_crankshaft_reason(k##NodeType); \
set_dont_turbofan_reason(k##NodeType); \
add_flag(kDontSelfOptimize); \
}
#define DONT_SELFOPTIMIZE_NODE(NodeType) \
void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
increase_node_count(); \
@ -1100,7 +1108,8 @@ DONT_TURBOFAN_NODE(ForOfStatement)
DONT_TURBOFAN_NODE(TryCatchStatement)
DONT_TURBOFAN_NODE(TryFinallyStatement)
DONT_TURBOFAN_NODE(ClassLiteral)
DONT_TURBOFAN_NODE(SuperReference)
DONT_TURBOFAN_NODE_WITH_FEEDBACK_SLOTS(SuperReference)
DONT_SELFOPTIMIZE_NODE(DoWhileStatement)
DONT_SELFOPTIMIZE_NODE(WhileStatement)

View File

@ -2591,13 +2591,28 @@ class SuperReference FINAL : public Expression {
TypeFeedbackId HomeObjectFeedbackId() { return reuse(id()); }
// Type feedback information.
virtual int ComputeFeedbackSlotCount() { return FLAG_vector_ics ? 1 : 0; }
virtual void SetFirstFeedbackSlot(int slot) {
homeobject_feedback_slot_ = slot;
}
int HomeObjectFeedbackSlot() {
DCHECK(!FLAG_vector_ics ||
homeobject_feedback_slot_ != kInvalidFeedbackSlot);
return homeobject_feedback_slot_;
}
protected:
SuperReference(Zone* zone, VariableProxy* this_var, int pos, IdGen* id_gen)
: Expression(zone, pos, id_gen), this_var_(this_var) {
: Expression(zone, pos, id_gen),
this_var_(this_var),
homeobject_feedback_slot_(kInvalidFeedbackSlot) {
DCHECK(this_var->is_this());
}
VariableProxy* this_var_;
int homeobject_feedback_slot_;
};

View File

@ -592,6 +592,9 @@ void HandlerStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() {
if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
if (FLAG_vector_ics) {
return VectorLoadICDescriptor(isolate());
}
return LoadDescriptor(isolate());
} else {
DCHECK_EQ(Code::STORE_IC, kind());
@ -627,14 +630,13 @@ static void InitializeVectorLoadStub(Isolate* isolate,
void VectorLoadStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
InitializeVectorLoadStub(isolate(), descriptor,
FUNCTION_ADDR(VectorLoadIC_MissFromStubFailure));
FUNCTION_ADDR(LoadIC_MissFromStubFailure));
}
void VectorKeyedLoadStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
InitializeVectorLoadStub(
isolate(), descriptor,
FUNCTION_ADDR(VectorKeyedLoadIC_MissFromStubFailure));
InitializeVectorLoadStub(isolate(), descriptor,
FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
}

View File

@ -857,7 +857,13 @@ class FunctionPrototypeStub : public PlatformCodeStub {
// TODO(mvstanton): only the receiver register is accessed. When this is
// translated to a hydrogen code stub, a new CallInterfaceDescriptor
// should be created that just uses that register for more efficient code.
DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
if (FLAG_vector_ics) {
return VectorLoadICDescriptor(isolate());
}
return LoadDescriptor(isolate());
}
DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
};
@ -1819,7 +1825,13 @@ class LoadDictionaryElementStub : public HydrogenCodeStub {
explicit LoadDictionaryElementStub(Isolate* isolate)
: HydrogenCodeStub(isolate) {}
DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
if (FLAG_vector_ics) {
return VectorLoadICDescriptor(isolate());
}
return LoadDescriptor(isolate());
}
DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
};
@ -1831,7 +1843,11 @@ class KeyedLoadGenericStub : public HydrogenCodeStub {
virtual Code::Kind GetCodeKind() const { return Code::KEYED_LOAD_IC; }
virtual InlineCacheState GetICState() const { return GENERIC; }
// Since KeyedLoadGeneric stub doesn't miss (simply calls runtime), it
// doesn't need to use the VectorLoadICDescriptor for the case when
// flag --vector-ics is true.
DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
};
@ -1845,9 +1861,7 @@ class LoadICTrampolineStub : public PlatformCodeStub {
virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
virtual InlineCacheState GetICState() const FINAL OVERRIDE {
return GENERIC;
}
virtual InlineCacheState GetICState() const FINAL OVERRIDE { return DEFAULT; }
virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
return static_cast<ExtraICState>(minor_key_);
@ -1893,7 +1907,13 @@ class MegamorphicLoadStub : public HydrogenCodeStub {
return static_cast<ExtraICState>(sub_minor_key());
}
DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
if (FLAG_vector_ics) {
return VectorLoadICDescriptor(isolate());
}
return LoadDescriptor(isolate());
}
DEFINE_HYDROGEN_CODE_STUB(MegamorphicLoad, HydrogenCodeStub);
};
@ -1907,9 +1927,7 @@ class VectorLoadStub : public HydrogenCodeStub {
virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
virtual InlineCacheState GetICState() const FINAL OVERRIDE {
return GENERIC;
}
virtual InlineCacheState GetICState() const FINAL OVERRIDE { return DEFAULT; }
virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
return static_cast<ExtraICState>(sub_minor_key());
@ -2003,7 +2021,13 @@ class LoadFastElementStub : public HydrogenCodeStub {
class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
class IsJSArrayBits: public BitField<bool, 8, 1> {};
DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
if (FLAG_vector_ics) {
return VectorLoadICDescriptor(isolate());
}
return LoadDescriptor(isolate());
}
DEFINE_HYDROGEN_CODE_STUB(LoadFastElement, HydrogenCodeStub);
};

View File

@ -1002,17 +1002,21 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
__ bind(&loop);
__ mov(receiver, Operand(ebp, kArgumentsOffset)); // load arguments
// Use inline caching to speed up access to arguments.
if (FLAG_vector_ics) {
__ mov(VectorLoadICDescriptor::SlotRegister(),
Immediate(Smi::FromInt(0)));
// TODO(mvstanton): Vector-based ics need additional infrastructure to
// be embedded here. For now, just call the runtime.
__ push(receiver);
__ push(key);
__ CallRuntime(Runtime::kGetProperty, 2);
} else {
// Use inline caching to speed up access to arguments.
Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code();
__ call(ic, RelocInfo::CODE_TARGET);
// It is important that we do not have a test instruction after the
// call. A test instruction after the call is used to indicate that
// we have generated an inline version of the keyed load. In this
// case, we know that we are not generating a test instruction next.
}
Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code();
__ call(ic, RelocInfo::CODE_TARGET);
// It is important that we do not have a test instruction after the
// call. A test instruction after the call is used to indicate that
// we have generated an inline version of the keyed load. In this
// case, we know that we are not generating a test instruction next.
// Push the nth argument.
__ push(eax);

View File

@ -182,7 +182,11 @@ void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
// Register state for IC load call (from ic-ia32.cc).
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
RegList regs = receiver.bit() | name.bit();
if (FLAG_vector_ics) {
regs |= VectorLoadICTrampolineDescriptor::SlotRegister().bit();
}
Generate_DebugBreakCallHelper(masm, regs, 0, false);
}

View File

@ -1287,7 +1287,13 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ mov(LoadDescriptor::NameRegister(), home_object_symbol);
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
if (FLAG_vector_ics) {
__ mov(VectorLoadICDescriptor::SlotRegister(),
Immediate(Smi::FromInt(expr->HomeObjectFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
} else {
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
}
__ cmp(eax, isolate()->factory()->undefined_value());
Label done;

View File

@ -2647,15 +2647,17 @@ RUNTIME_FUNCTION(LoadElementWithInterceptor) {
}
RUNTIME_FUNCTION(VectorLoadIC_MissFromStubFailure) {
// TODO(mvstanton): To be enabled when ICs can accept a vector and slot
return NULL;
}
RUNTIME_FUNCTION(VectorKeyedLoadIC_MissFromStubFailure) {
// TODO(mvstanton): To be enabled when ICs can accept a vector and slot
return NULL;
RUNTIME_FUNCTION(LoadIC_MissFromStubFailure) {
TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK(args.length() == 2);
LoadIC ic(IC::EXTRA_CALL_FRAME, isolate);
Handle<Object> receiver = args.at<Object>(0);
Handle<Name> key = args.at<Name>(1);
ic.UpdateState(receiver, key);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
return *result;
}

View File

@ -680,8 +680,7 @@ DECLARE_RUNTIME_FUNCTION(BinaryOpIC_Miss);
DECLARE_RUNTIME_FUNCTION(BinaryOpIC_MissWithAllocationSite);
DECLARE_RUNTIME_FUNCTION(CompareNilIC_Miss);
DECLARE_RUNTIME_FUNCTION(ToBooleanIC_Miss);
DECLARE_RUNTIME_FUNCTION(VectorLoadIC_MissFromStubFailure);
DECLARE_RUNTIME_FUNCTION(VectorKeyedLoadIC_MissFromStubFailure);
DECLARE_RUNTIME_FUNCTION(LoadIC_MissFromStubFailure);
// Support functions for callbacks handlers.
DECLARE_RUNTIME_FUNCTION(StoreCallbackProperty);

View File

@ -187,7 +187,11 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0);
RegList regs = receiver.bit() | name.bit();
if (FLAG_vector_ics) {
regs |= VectorLoadICTrampolineDescriptor::SlotRegister().bit();
}
Generate_DebugBreakCallHelper(masm, regs, 0);
}

View File

@ -1351,7 +1351,13 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ li(LoadDescriptor::NameRegister(), home_object_symbol);
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
if (FLAG_vector_ics) {
__ li(VectorLoadICDescriptor::SlotRegister(),
Operand(Smi::FromInt(expr->HomeObjectFeedbackSlot())));
CallLoadIC(NOT_CONTEXTUAL);
} else {
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
}
Label done;
__ Branch(&done, ne, v0, Operand(isolate()->factory()->undefined_value()));

View File

@ -1075,14 +1075,19 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
// Use inline caching to speed up access to arguments.
if (FLAG_vector_ics) {
__ Move(VectorLoadICDescriptor::SlotRegister(), Smi::FromInt(0));
// TODO(mvstanton): Vector-based ics need additional infrastructure to
// be embedded here. For now, just call the runtime.
__ Push(receiver);
__ Push(key);
__ CallRuntime(Runtime::kGetProperty, 2);
} else {
Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code();
__ Call(ic, RelocInfo::CODE_TARGET);
// It is important that we do not have a test instruction after the
// call. A test instruction after the call is used to indicate that
// we have generated an inline version of the keyed load. In this
// case, we know that we are not generating a test instruction next.
}
Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code();
__ Call(ic, RelocInfo::CODE_TARGET);
// It is important that we do not have a test instruction after the
// call. A test instruction after the call is used to indicate that
// we have generated an inline version of the keyed load. In this
// case, we know that we are not generating a test instruction next.
// Push the nth argument.
__ Push(rax);

View File

@ -164,7 +164,11 @@ void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
// Register state for IC load call (from ic-x64.cc).
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0, false);
RegList regs = receiver.bit() | name.bit();
if (FLAG_vector_ics) {
regs |= VectorLoadICTrampolineDescriptor::SlotRegister().bit();
}
Generate_DebugBreakCallHelper(masm, regs, 0, false);
}

View File

@ -1321,7 +1321,14 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
__ Move(LoadDescriptor::NameRegister(), home_object_symbol);
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
if (FLAG_vector_ics) {
__ Move(VectorLoadICDescriptor::SlotRegister(),
Smi::FromInt(expr->HomeObjectFeedbackSlot()));
CallLoadIC(NOT_CONTEXTUAL);
} else {
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
}
__ Cmp(rax, isolate()->factory()->undefined_value());
Label done;