Now that vector ics are established for load, keyed load and call ics, let's remove dead code behind the flag.
BUG= Review URL: https://codereview.chromium.org/1129853002 Cr-Commit-Position: refs/heads/master@{#28422}
This commit is contained in:
parent
de3a1ca02e
commit
323ced9e27
@ -1489,8 +1489,7 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
// Ensure that the vector and slot registers won't be clobbered before
|
||||
// calling the miss handler.
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!AreAliased(r4, r5, VectorLoadICDescriptor::VectorRegister(),
|
||||
DCHECK(!AreAliased(r4, r5, VectorLoadICDescriptor::VectorRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister()));
|
||||
|
||||
NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r4,
|
||||
@ -1510,9 +1509,8 @@ void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
|
||||
Register scratch = r5;
|
||||
Register result = r0;
|
||||
DCHECK(!scratch.is(receiver) && !scratch.is(index));
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
(!scratch.is(VectorLoadICDescriptor::VectorRegister()) &&
|
||||
result.is(VectorLoadICDescriptor::SlotRegister())));
|
||||
DCHECK(!scratch.is(VectorLoadICDescriptor::VectorRegister()) &&
|
||||
result.is(VectorLoadICDescriptor::SlotRegister()));
|
||||
|
||||
// StringCharAtGenerator doesn't use the result register until it's passed
|
||||
// the different miss possibilities. If it did, we would have a conflict
|
||||
@ -2953,7 +2951,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
index_not_number_,
|
||||
DONT_DO_SMI_CHECK);
|
||||
call_helper.BeforeCall(masm);
|
||||
if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
|
||||
if (embed_mode == PART_OF_IC_HANDLER) {
|
||||
__ Push(VectorLoadICDescriptor::VectorRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister(), object_, index_);
|
||||
} else {
|
||||
@ -2970,7 +2968,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
// Save the conversion result before the pop instructions below
|
||||
// have a chance to overwrite it.
|
||||
__ Move(index_, r0);
|
||||
if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
|
||||
if (embed_mode == PART_OF_IC_HANDLER) {
|
||||
__ Pop(VectorLoadICDescriptor::VectorRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister(), object_);
|
||||
} else {
|
||||
|
@ -144,10 +144,8 @@ void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for IC load (from ic-arm.cc).
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
RegList regs = receiver.bit() | name.bit();
|
||||
if (FLAG_vector_ics) {
|
||||
regs |= VectorLoadICTrampolineDescriptor::SlotRegister().bit();
|
||||
}
|
||||
RegList regs = receiver.bit() | name.bit() |
|
||||
VectorLoadICTrampolineDescriptor::SlotRegister().bit();
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0);
|
||||
}
|
||||
|
||||
|
@ -1333,13 +1333,9 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
|
||||
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
|
||||
__ Move(LoadDescriptor::NameRegister(), home_object_symbol);
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
|
||||
__ cmp(r0, Operand(isolate()->factory()->undefined_value()));
|
||||
Label done;
|
||||
@ -1412,10 +1408,8 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
||||
|
||||
__ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ mov(LoadDescriptor::NameRegister(), Operand(proxy->var()->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
|
||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? NOT_CONTEXTUAL
|
||||
@ -1502,10 +1496,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
__ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ mov(LoadDescriptor::NameRegister(), Operand(var->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
CallGlobalLoadIC(var->name());
|
||||
context()->Plug(r0);
|
||||
break;
|
||||
@ -2200,10 +2192,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ bind(&l_call);
|
||||
__ ldr(load_receiver, MemOperand(sp, kPointerSize));
|
||||
__ ldr(load_name, MemOperand(sp, 2 * kPointerSize));
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ mov(r1, r0);
|
||||
@ -2220,10 +2210,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
__ push(load_receiver); // save result
|
||||
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->DoneFeedbackSlot())));
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->DoneFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL); // r0=result.done
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(bool_ic);
|
||||
@ -2233,10 +2221,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// result.value
|
||||
__ pop(load_receiver); // result
|
||||
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->ValueFeedbackSlot())));
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->ValueFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL); // r0=result.value
|
||||
context()->DropAndPlug(2, r0); // drop iter and g
|
||||
break;
|
||||
@ -2388,13 +2374,9 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
DCHECK(!prop->IsSuperAccess());
|
||||
|
||||
__ mov(LoadDescriptor::NameRegister(), Operand(key->value()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -2413,13 +2395,9 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallIC(ic);
|
||||
} else {
|
||||
CallIC(ic, prop->PropertyFeedbackId());
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallIC(ic);
|
||||
}
|
||||
|
||||
|
||||
@ -4631,13 +4609,9 @@ void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
|
||||
|
||||
// Load the function from the receiver.
|
||||
__ mov(LoadDescriptor::NameRegister(), Operand(expr->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->CallRuntimeFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->CallRuntimeFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -5070,10 +5044,8 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
__ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ mov(LoadDescriptor::NameRegister(), Operand(proxy->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
|
@ -1105,20 +1105,6 @@ 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(), r1);
|
||||
|
@ -154,7 +154,6 @@ class LCodeGen;
|
||||
V(SubI) \
|
||||
V(RSubI) \
|
||||
V(TaggedToI) \
|
||||
V(TailCallThroughMegamorphicCache) \
|
||||
V(ThisFunction) \
|
||||
V(ToFastProperties) \
|
||||
V(TransitionElementsKind) \
|
||||
@ -475,26 +474,6 @@ class LCallStub final : public LTemplateInstruction<1, 1, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LTailCallThroughMegamorphicCache final
|
||||
: public LTemplateInstruction<0, 3, 0> {
|
||||
public:
|
||||
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:
|
||||
bool HasInterestingComment(LCodeGen* gen) const override { return false; }
|
||||
|
@ -2987,7 +2987,6 @@ void LCodeGen::DoReturn(LReturn* instr) {
|
||||
|
||||
template <class T>
|
||||
void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
|
||||
DCHECK(FLAG_vector_ics);
|
||||
Register vector_register = ToRegister(instr->temp_vector());
|
||||
Register slot_register = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister()));
|
||||
@ -3010,9 +3009,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
DCHECK(ToRegister(instr->result()).is(r0));
|
||||
|
||||
__ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
}
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
|
||||
PREMONOMORPHIC).code();
|
||||
@ -3109,9 +3106,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
|
||||
// Name is always in r2.
|
||||
__ mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
}
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL,
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
@ -3962,29 +3957,6 @@ 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(r1));
|
||||
DCHECK(name.is(r2));
|
||||
Register scratch = r4;
|
||||
Register extra = r5;
|
||||
Register extra2 = r6;
|
||||
Register extra3 = r9;
|
||||
|
||||
// The probe will tail call to a handler if found.
|
||||
isolate()->stub_cache()->GenerateProbe(
|
||||
masm(), Code::LOAD_IC, instr->hydrogen()->flags(), false, receiver, name,
|
||||
scratch, extra, extra2, extra3);
|
||||
|
||||
// Tail call to miss if we ended up here.
|
||||
LoadIC::GenerateMiss(masm());
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
|
||||
DCHECK(ToRegister(instr->result()).is(r0));
|
||||
|
||||
|
@ -1449,8 +1449,7 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
// Ensure that the vector and slot registers won't be clobbered before
|
||||
// calling the miss handler.
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!AreAliased(x10, x11, VectorLoadICDescriptor::VectorRegister(),
|
||||
DCHECK(!AreAliased(x10, x11, VectorLoadICDescriptor::VectorRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister()));
|
||||
|
||||
NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, x10,
|
||||
@ -1471,9 +1470,8 @@ void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
|
||||
Register result = x0;
|
||||
Register scratch = x10;
|
||||
DCHECK(!scratch.is(receiver) && !scratch.is(index));
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
(!scratch.is(VectorLoadICDescriptor::VectorRegister()) &&
|
||||
result.is(VectorLoadICDescriptor::SlotRegister())));
|
||||
DCHECK(!scratch.is(VectorLoadICDescriptor::VectorRegister()) &&
|
||||
result.is(VectorLoadICDescriptor::SlotRegister()));
|
||||
|
||||
// StringCharAtGenerator doesn't use the result register until it's passed
|
||||
// the different miss possibilities. If it did, we would have a conflict
|
||||
@ -3354,7 +3352,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
// If index is a heap number, try converting it to an integer.
|
||||
__ JumpIfNotHeapNumber(index_, index_not_number_);
|
||||
call_helper.BeforeCall(masm);
|
||||
if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
|
||||
if (embed_mode == PART_OF_IC_HANDLER) {
|
||||
__ Push(VectorLoadICDescriptor::VectorRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister(), object_, index_);
|
||||
} else {
|
||||
@ -3371,7 +3369,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
// Save the conversion result before the pop instructions below
|
||||
// have a chance to overwrite it.
|
||||
__ Mov(index_, x0);
|
||||
if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
|
||||
if (embed_mode == PART_OF_IC_HANDLER) {
|
||||
__ Pop(object_, VectorLoadICDescriptor::SlotRegister(),
|
||||
VectorLoadICDescriptor::VectorRegister());
|
||||
} else {
|
||||
|
@ -207,10 +207,8 @@ void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for IC load (from ic-arm.cc).
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
RegList regs = receiver.Bit() | name.Bit();
|
||||
if (FLAG_vector_ics) {
|
||||
regs |= VectorLoadICTrampolineDescriptor::SlotRegister().Bit();
|
||||
}
|
||||
RegList regs = receiver.Bit() | name.Bit() |
|
||||
VectorLoadICTrampolineDescriptor::SlotRegister().Bit();
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0, x10);
|
||||
}
|
||||
|
||||
|
@ -1318,13 +1318,9 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
|
||||
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
|
||||
__ Mov(LoadDescriptor::NameRegister(), Operand(home_object_symbol));
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->HomeObjectFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
|
||||
}
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->HomeObjectFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
|
||||
__ Mov(x10, Operand(isolate()->factory()->undefined_value()));
|
||||
__ cmp(x0, x10);
|
||||
@ -1392,10 +1388,8 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
||||
|
||||
__ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand());
|
||||
__ Mov(LoadDescriptor::NameRegister(), Operand(proxy->var()->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
||||
}
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
||||
|
||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL
|
||||
: CONTEXTUAL;
|
||||
@ -1478,10 +1472,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
Comment cmnt(masm_, "Global variable");
|
||||
__ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand());
|
||||
__ Mov(LoadDescriptor::NameRegister(), Operand(var->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
||||
}
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
||||
CallGlobalLoadIC(var->name());
|
||||
context()->Plug(x0);
|
||||
break;
|
||||
@ -2054,13 +2046,9 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
DCHECK(!prop->IsSuperAccess());
|
||||
|
||||
__ Mov(LoadDescriptor::NameRegister(), Operand(key->value()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(prop->PropertyFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(prop->PropertyFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -2080,13 +2068,9 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
// Call keyed load IC. It has arguments key and receiver in x0 and x1.
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
if (FLAG_vector_ics) {
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(prop->PropertyFeedbackSlot()));
|
||||
CallIC(ic);
|
||||
} else {
|
||||
CallIC(ic, prop->PropertyFeedbackId());
|
||||
}
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(prop->PropertyFeedbackSlot()));
|
||||
CallIC(ic);
|
||||
}
|
||||
|
||||
|
||||
@ -4312,13 +4296,9 @@ void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
|
||||
// Load the function from the receiver.
|
||||
Handle<String> name = expr->name();
|
||||
__ Mov(LoadDescriptor::NameRegister(), Operand(name));
|
||||
if (FLAG_vector_ics) {
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->CallRuntimeFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
|
||||
}
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->CallRuntimeFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -4746,10 +4726,8 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||
Comment cmnt(masm_, "Global variable");
|
||||
__ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand());
|
||||
__ Mov(LoadDescriptor::NameRegister(), Operand(proxy->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
||||
}
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
@ -5103,10 +5081,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ Bind(&l_call);
|
||||
__ Peek(load_receiver, 1 * kPointerSize);
|
||||
__ Peek(load_name, 2 * kPointerSize);
|
||||
if (FLAG_vector_ics) {
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->KeyedLoadFeedbackSlot()));
|
||||
}
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->KeyedLoadFeedbackSlot()));
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ Mov(x1, x0);
|
||||
@ -5123,10 +5099,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
__ Push(load_receiver); // save result
|
||||
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
|
||||
if (FLAG_vector_ics) {
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->DoneFeedbackSlot()));
|
||||
}
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->DoneFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL); // x0=result.done
|
||||
// The ToBooleanStub argument (result.done) is in x0.
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
@ -5136,10 +5110,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// result.value
|
||||
__ Pop(load_receiver); // result
|
||||
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
|
||||
if (FLAG_vector_ics) {
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->ValueFeedbackSlot()));
|
||||
}
|
||||
__ Mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->ValueFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL); // x0=result.value
|
||||
context()->DropAndPlug(2, x0); // drop iter and g
|
||||
break;
|
||||
|
@ -1588,20 +1588,6 @@ LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
// The function is required (by MacroAssembler::InvokeFunction) to be in x1.
|
||||
|
@ -165,7 +165,6 @@ class LCodeGen;
|
||||
V(SubI) \
|
||||
V(SubS) \
|
||||
V(TaggedToI) \
|
||||
V(TailCallThroughMegamorphicCache) \
|
||||
V(ThisFunction) \
|
||||
V(ToFastProperties) \
|
||||
V(TransitionElementsKind) \
|
||||
@ -319,26 +318,6 @@ class LTemplateInstruction : public LTemplateResultInstruction<R> {
|
||||
};
|
||||
|
||||
|
||||
class LTailCallThroughMegamorphicCache final
|
||||
: public LTemplateInstruction<0, 3, 0> {
|
||||
public:
|
||||
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:
|
||||
bool HasInterestingComment(LCodeGen* gen) const override { return false; }
|
||||
|
@ -2022,29 +2022,6 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
||||
}
|
||||
|
||||
|
||||
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(x1));
|
||||
DCHECK(name.is(x2));
|
||||
Register scratch = x4;
|
||||
Register extra = x5;
|
||||
Register extra2 = x6;
|
||||
Register extra3 = x7;
|
||||
|
||||
// The probe will tail call to a handler if found.
|
||||
isolate()->stub_cache()->GenerateProbe(
|
||||
masm(), Code::LOAD_IC, instr->hydrogen()->flags(), false, receiver, name,
|
||||
scratch, extra, extra2, extra3);
|
||||
|
||||
// Tail call to miss if we ended up here.
|
||||
LoadIC::GenerateMiss(masm());
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
|
||||
DCHECK(instr->IsMarkedAsCall());
|
||||
DCHECK(ToRegister(instr->result()).Is(x0));
|
||||
@ -3363,7 +3340,6 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
|
||||
|
||||
template <class T>
|
||||
void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
|
||||
DCHECK(FLAG_vector_ics);
|
||||
Register vector_register = ToRegister(instr->temp_vector());
|
||||
Register slot_register = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister()));
|
||||
@ -3385,9 +3361,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
.is(LoadDescriptor::ReceiverRegister()));
|
||||
DCHECK(ToRegister(instr->result()).Is(x0));
|
||||
__ Mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
}
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
|
||||
PREMONOMORPHIC).code();
|
||||
@ -3714,9 +3688,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
// LoadIC expects name and receiver in registers.
|
||||
DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
|
||||
__ Mov(LoadDescriptor::NameRegister(), Operand(instr->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
}
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL,
|
||||
|
@ -18,7 +18,7 @@ class AstNumberingVisitor final : public AstVisitor {
|
||||
: AstVisitor(),
|
||||
next_id_(BailoutId::FirstUsable().ToInt()),
|
||||
properties_(zone),
|
||||
ic_slot_cache_(FLAG_vector_ics ? 4 : 0),
|
||||
ic_slot_cache_(4),
|
||||
dont_optimize_reason_(kNoReason) {
|
||||
InitializeAstVisitor(isolate, zone);
|
||||
}
|
||||
@ -71,10 +71,8 @@ class AstNumberingVisitor final : public AstVisitor {
|
||||
node->SetFirstFeedbackICSlot(FeedbackVectorICSlot(ic_slots),
|
||||
&ic_slot_cache_);
|
||||
properties_.increase_ic_slots(reqs.ic_slots());
|
||||
if (FLAG_vector_ics) {
|
||||
for (int i = 0; i < reqs.ic_slots(); i++) {
|
||||
properties_.SetKind(ic_slots + i, node->FeedbackICSlotKind(i));
|
||||
}
|
||||
for (int i = 0; i < reqs.ic_slots(); i++) {
|
||||
properties_.SetKind(ic_slots + i, node->FeedbackICSlotKind(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,8 +81,7 @@ class AstNumberingVisitor final : public AstVisitor {
|
||||
|
||||
int next_id_;
|
||||
AstProperties properties_;
|
||||
// The slot cache allows us to reuse certain vector IC slots. It's only used
|
||||
// if FLAG_vector_ics is true.
|
||||
// The slot cache allows us to reuse certain vector IC slots.
|
||||
ICSlotCache ic_slot_cache_;
|
||||
BailoutReason dont_optimize_reason_;
|
||||
|
||||
|
18
src/ast.h
18
src/ast.h
@ -1592,7 +1592,7 @@ class VariableProxy final : public Expression {
|
||||
void BindTo(Variable* var);
|
||||
|
||||
bool UsesVariableFeedbackSlot() const {
|
||||
return FLAG_vector_ics && (var()->IsUnallocated() || var()->IsLookupSlot());
|
||||
return var()->IsUnallocated() || var()->IsLookupSlot();
|
||||
}
|
||||
|
||||
virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
|
||||
@ -1691,7 +1691,7 @@ class Property final : public Expression {
|
||||
|
||||
virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
|
||||
Isolate* isolate, const ICSlotCache* cache) override {
|
||||
return FeedbackVectorRequirements(0, FLAG_vector_ics ? 1 : 0);
|
||||
return FeedbackVectorRequirements(0, 1);
|
||||
}
|
||||
void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
|
||||
ICSlotCache* cache) override {
|
||||
@ -1702,7 +1702,7 @@ class Property final : public Expression {
|
||||
}
|
||||
|
||||
FeedbackVectorICSlot PropertyFeedbackSlot() const {
|
||||
DCHECK(!FLAG_vector_ics || !property_feedback_slot_.IsInvalid());
|
||||
DCHECK(!property_feedback_slot_.IsInvalid());
|
||||
return property_feedback_slot_;
|
||||
}
|
||||
|
||||
@ -1939,9 +1939,7 @@ class CallRuntime final : public Expression {
|
||||
bool is_jsruntime() const { return function_ == NULL; }
|
||||
|
||||
// Type feedback information.
|
||||
bool HasCallRuntimeFeedbackSlot() const {
|
||||
return FLAG_vector_ics && is_jsruntime();
|
||||
}
|
||||
bool HasCallRuntimeFeedbackSlot() const { return is_jsruntime(); }
|
||||
virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
|
||||
Isolate* isolate, const ICSlotCache* cache) override {
|
||||
return FeedbackVectorRequirements(0, HasCallRuntimeFeedbackSlot() ? 1 : 0);
|
||||
@ -2331,9 +2329,7 @@ class Yield final : public Expression {
|
||||
}
|
||||
|
||||
// Type feedback information.
|
||||
bool HasFeedbackSlots() const {
|
||||
return FLAG_vector_ics && (yield_kind() == kDelegating);
|
||||
}
|
||||
bool HasFeedbackSlots() const { return yield_kind() == kDelegating; }
|
||||
virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
|
||||
Isolate* isolate, const ICSlotCache* cache) override {
|
||||
return FeedbackVectorRequirements(0, HasFeedbackSlots() ? 3 : 0);
|
||||
@ -2691,7 +2687,7 @@ class SuperReference final : public Expression {
|
||||
// Type feedback information.
|
||||
virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
|
||||
Isolate* isolate, const ICSlotCache* cache) override {
|
||||
return FeedbackVectorRequirements(0, FLAG_vector_ics ? 1 : 0);
|
||||
return FeedbackVectorRequirements(0, 1);
|
||||
}
|
||||
void SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
|
||||
ICSlotCache* cache) override {
|
||||
@ -2700,7 +2696,7 @@ class SuperReference final : public Expression {
|
||||
Code::Kind FeedbackICSlotKind(int index) override { return Code::LOAD_IC; }
|
||||
|
||||
FeedbackVectorICSlot HomeObjectFeedbackSlot() {
|
||||
DCHECK(!FLAG_vector_ics || !homeobject_feedback_slot_.IsInvalid());
|
||||
DCHECK(!homeobject_feedback_slot_.IsInvalid());
|
||||
return homeobject_feedback_slot_;
|
||||
}
|
||||
|
||||
|
@ -1309,11 +1309,6 @@ static void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
static void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) {
|
||||
KeyedLoadIC::GeneratePreMonomorphic(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_StoreIC_Miss(MacroAssembler* masm) {
|
||||
StoreIC::GenerateMiss(masm);
|
||||
}
|
||||
|
@ -87,8 +87,6 @@ enum BuiltinExtraArguments {
|
||||
V(KeyedStoreIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
||||
V(LoadIC_Getter_ForDeopt, LOAD_IC, MONOMORPHIC, kNoExtraICState) \
|
||||
V(KeyedLoadIC_Initialize, KEYED_LOAD_IC, UNINITIALIZED, kNoExtraICState) \
|
||||
V(KeyedLoadIC_PreMonomorphic, KEYED_LOAD_IC, PREMONOMORPHIC, \
|
||||
kNoExtraICState) \
|
||||
V(KeyedLoadIC_Megamorphic, KEYED_LOAD_IC, MEGAMORPHIC, kNoExtraICState) \
|
||||
\
|
||||
V(StoreIC_Setter_ForDeopt, STORE_IC, MONOMORPHIC, StoreIC::kStrictModeState) \
|
||||
|
@ -11,14 +11,6 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// static
|
||||
Callable CodeFactory::LoadGlobalIC(Isolate* isolate,
|
||||
Handle<GlobalObject> global,
|
||||
Handle<String> name) {
|
||||
return Callable(LoadIC::load_global(isolate, global, name),
|
||||
LoadDescriptor(isolate));
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
Callable CodeFactory::LoadIC(Isolate* isolate, ContextualMode mode) {
|
||||
@ -34,10 +26,7 @@ Callable CodeFactory::LoadICInOptimizedCode(
|
||||
InlineCacheState initialization_state) {
|
||||
auto code = LoadIC::initialize_stub_in_optimized_code(
|
||||
isolate, LoadICState(mode).GetExtraICState(), initialization_state);
|
||||
if (FLAG_vector_ics) {
|
||||
return Callable(code, VectorLoadICDescriptor(isolate));
|
||||
}
|
||||
return Callable(code, LoadDescriptor(isolate));
|
||||
return Callable(code, VectorLoadICDescriptor(isolate));
|
||||
}
|
||||
|
||||
|
||||
@ -53,7 +42,7 @@ Callable CodeFactory::KeyedLoadICInOptimizedCode(
|
||||
Isolate* isolate, InlineCacheState initialization_state) {
|
||||
auto code = KeyedLoadIC::initialize_stub_in_optimized_code(
|
||||
isolate, initialization_state);
|
||||
if (FLAG_vector_ics && initialization_state != MEGAMORPHIC) {
|
||||
if (initialization_state != MEGAMORPHIC) {
|
||||
return Callable(code, VectorLoadICDescriptor(isolate));
|
||||
}
|
||||
return Callable(code, LoadDescriptor(isolate));
|
||||
|
@ -32,8 +32,6 @@ class Callable final BASE_EMBEDDED {
|
||||
class CodeFactory final {
|
||||
public:
|
||||
// Initial states for ICs.
|
||||
static Callable LoadGlobalIC(Isolate* isolate, Handle<GlobalObject> global,
|
||||
Handle<String> name);
|
||||
static Callable LoadIC(Isolate* isolate, ContextualMode mode);
|
||||
static Callable LoadICInOptimizedCode(Isolate* isolate, ContextualMode mode,
|
||||
InlineCacheState initialization_state);
|
||||
|
@ -2205,29 +2205,4 @@ Handle<Code> KeyedLoadGenericStub::GenerateCode() {
|
||||
return DoGenerateCode(this);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> MegamorphicLoadStub::GenerateCode() {
|
||||
return DoGenerateCode(this);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
HValue* CodeStubGraphBuilder<MegamorphicLoadStub>::BuildCodeStub() {
|
||||
HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex);
|
||||
HValue* name = GetParameter(LoadDescriptor::kNameIndex);
|
||||
|
||||
// We shouldn't generate this when FLAG_vector_ics is true because the
|
||||
// megamorphic case is handled as part of the default stub.
|
||||
DCHECK(!FLAG_vector_ics);
|
||||
|
||||
// This stub tail calls, and an erected frame presents complications we don't
|
||||
// need.
|
||||
info()->MarkMustNotHaveEagerFrame();
|
||||
|
||||
// Probe the stub cache.
|
||||
Add<HTailCallThroughMegamorphicCache>(receiver, name);
|
||||
|
||||
// We never continue.
|
||||
return graph()->GetConstant0();
|
||||
}
|
||||
} } // namespace v8::internal
|
||||
|
@ -618,10 +618,7 @@ 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());
|
||||
return VectorLoadICDescriptor(isolate());
|
||||
} else {
|
||||
DCHECK_EQ(Code::STORE_IC, kind());
|
||||
return StoreDescriptor(isolate());
|
||||
@ -646,9 +643,6 @@ CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor() {
|
||||
}
|
||||
|
||||
|
||||
void MegamorphicLoadStub::InitializeDescriptor(CodeStubDescriptor* d) {}
|
||||
|
||||
|
||||
void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
|
||||
descriptor->Initialize(
|
||||
Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry);
|
||||
|
@ -76,7 +76,6 @@ namespace internal {
|
||||
V(KeyedLoadGeneric) \
|
||||
V(LoadScriptContextField) \
|
||||
V(LoadDictionaryElement) \
|
||||
V(MegamorphicLoad) \
|
||||
V(NameDictionaryLookup) \
|
||||
V(NumberToString) \
|
||||
V(Typeof) \
|
||||
@ -987,10 +986,7 @@ class FunctionPrototypeStub : public PlatformCodeStub {
|
||||
// translated to a hydrogen code stub, a new CallInterfaceDescriptor
|
||||
// should be created that just uses that register for more efficient code.
|
||||
CallInterfaceDescriptor GetCallInterfaceDescriptor() override {
|
||||
if (FLAG_vector_ics) {
|
||||
return VectorLoadICDescriptor(isolate());
|
||||
}
|
||||
return LoadDescriptor(isolate());
|
||||
return VectorLoadICDescriptor(isolate());
|
||||
}
|
||||
|
||||
DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
|
||||
@ -2081,10 +2077,7 @@ class LoadDictionaryElementStub : public HydrogenCodeStub {
|
||||
: HydrogenCodeStub(isolate) {}
|
||||
|
||||
CallInterfaceDescriptor GetCallInterfaceDescriptor() override {
|
||||
if (FLAG_vector_ics) {
|
||||
return VectorLoadICDescriptor(isolate());
|
||||
}
|
||||
return LoadDescriptor(isolate());
|
||||
return VectorLoadICDescriptor(isolate());
|
||||
}
|
||||
|
||||
DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
|
||||
@ -2178,32 +2171,6 @@ class CallIC_ArrayTrampolineStub : public CallICTrampolineStub {
|
||||
};
|
||||
|
||||
|
||||
class MegamorphicLoadStub : public HydrogenCodeStub {
|
||||
public:
|
||||
MegamorphicLoadStub(Isolate* isolate, const LoadICState& state)
|
||||
: HydrogenCodeStub(isolate) {
|
||||
set_sub_minor_key(state.GetExtraICState());
|
||||
}
|
||||
|
||||
Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
|
||||
|
||||
InlineCacheState GetICState() const final { return MEGAMORPHIC; }
|
||||
|
||||
ExtraICState GetExtraICState() const final {
|
||||
return static_cast<ExtraICState>(sub_minor_key());
|
||||
}
|
||||
|
||||
CallInterfaceDescriptor GetCallInterfaceDescriptor() override {
|
||||
if (FLAG_vector_ics) {
|
||||
return VectorLoadICDescriptor(isolate());
|
||||
}
|
||||
return LoadDescriptor(isolate());
|
||||
}
|
||||
|
||||
DEFINE_HYDROGEN_CODE_STUB(MegamorphicLoad, HydrogenCodeStub);
|
||||
};
|
||||
|
||||
|
||||
class VectorRawLoadStub : public PlatformCodeStub {
|
||||
public:
|
||||
explicit VectorRawLoadStub(Isolate* isolate, const LoadICState& state)
|
||||
|
@ -343,11 +343,8 @@ void JSGenericLowering::LowerJSLoadProperty(Node* node) {
|
||||
const LoadPropertyParameters& p = LoadPropertyParametersOf(node->op());
|
||||
Callable callable =
|
||||
CodeFactory::KeyedLoadICInOptimizedCode(isolate(), UNINITIALIZED);
|
||||
if (FLAG_vector_ics) {
|
||||
node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
|
||||
node->InsertInput(zone(), 3,
|
||||
jsgraph()->HeapConstant(p.feedback().vector()));
|
||||
}
|
||||
node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
|
||||
node->InsertInput(zone(), 3, jsgraph()->HeapConstant(p.feedback().vector()));
|
||||
ReplaceWithStubCall(node, callable,
|
||||
CallDescriptor::kPatchableCallSite | flags);
|
||||
}
|
||||
@ -362,11 +359,8 @@ void JSGenericLowering::LowerJSLoadNamed(Node* node) {
|
||||
UNINITIALIZED)
|
||||
: CodeFactory::KeyedLoadICInOptimizedCode(isolate(), UNINITIALIZED);
|
||||
node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
|
||||
if (FLAG_vector_ics) {
|
||||
node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
|
||||
node->InsertInput(zone(), 3,
|
||||
jsgraph()->HeapConstant(p.feedback().vector()));
|
||||
}
|
||||
node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
|
||||
node->InsertInput(zone(), 3, jsgraph()->HeapConstant(p.feedback().vector()));
|
||||
ReplaceWithStubCall(node, callable,
|
||||
CallDescriptor::kPatchableCallSite | flags);
|
||||
}
|
||||
|
@ -260,7 +260,6 @@ DEFINE_BOOL(track_field_types, true, "track field types")
|
||||
DEFINE_IMPLICATION(track_field_types, track_fields)
|
||||
DEFINE_IMPLICATION(track_field_types, track_heap_object_fields)
|
||||
DEFINE_BOOL(smi_binop, true, "support smi representation in binary operations")
|
||||
DEFINE_BOOL(vector_ics, true, "support vector-based ics")
|
||||
|
||||
// Flags for optimization types.
|
||||
DEFINE_BOOL(optimize_for_size, false,
|
||||
|
@ -445,13 +445,7 @@ void FullCodeGenerator::CallLoadIC(ContextualMode contextual_mode,
|
||||
|
||||
|
||||
void FullCodeGenerator::CallGlobalLoadIC(Handle<String> name) {
|
||||
if (masm()->serializer_enabled() || FLAG_vector_ics) {
|
||||
// Vector-ICs don't work with LoadGlobalIC.
|
||||
return CallLoadIC(CONTEXTUAL);
|
||||
}
|
||||
Handle<Code> ic = CodeFactory::LoadGlobalIC(
|
||||
isolate(), isolate()->global_object(), name).code();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
return CallLoadIC(CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3135,17 +3135,13 @@ void Heap::CreateInitialObjects() {
|
||||
// Number of queued microtasks stored in Isolate::pending_microtask_count().
|
||||
set_microtask_queue(empty_fixed_array());
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
FeedbackVectorSpec spec(0, Code::KEYED_LOAD_IC);
|
||||
Handle<TypeFeedbackVector> dummy_vector =
|
||||
factory->NewTypeFeedbackVector(&spec);
|
||||
dummy_vector->Set(FeedbackVectorICSlot(0),
|
||||
*TypeFeedbackVector::MegamorphicSentinel(isolate()),
|
||||
SKIP_WRITE_BARRIER);
|
||||
set_keyed_load_dummy_vector(*dummy_vector);
|
||||
} else {
|
||||
set_keyed_load_dummy_vector(empty_fixed_array());
|
||||
}
|
||||
FeedbackVectorSpec spec(0, Code::KEYED_LOAD_IC);
|
||||
Handle<TypeFeedbackVector> dummy_vector =
|
||||
factory->NewTypeFeedbackVector(&spec);
|
||||
dummy_vector->Set(FeedbackVectorICSlot(0),
|
||||
*TypeFeedbackVector::MegamorphicSentinel(isolate()),
|
||||
SKIP_WRITE_BARRIER);
|
||||
set_keyed_load_dummy_vector(*dummy_vector);
|
||||
|
||||
set_detached_contexts(empty_fixed_array());
|
||||
set_retained_maps(ArrayList::cast(empty_fixed_array()));
|
||||
|
@ -837,7 +837,6 @@ bool HInstruction::CanDeoptimize() {
|
||||
case HValue::kStoreNamedGeneric:
|
||||
case HValue::kStringCharCodeAt:
|
||||
case HValue::kStringCharFromCode:
|
||||
case HValue::kTailCallThroughMegamorphicCache:
|
||||
case HValue::kThisFunction:
|
||||
case HValue::kTypeofIsAndBranch:
|
||||
case HValue::kUnknownOSRValue:
|
||||
@ -1717,22 +1716,6 @@ std::ostream& HCallStub::PrintDataTo(std::ostream& os) const { // NOLINT
|
||||
}
|
||||
|
||||
|
||||
Code::Flags HTailCallThroughMegamorphicCache::flags() const {
|
||||
Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags(
|
||||
Code::ComputeHandlerFlags(Code::LOAD_IC));
|
||||
return code_flags;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& HTailCallThroughMegamorphicCache::PrintDataTo(
|
||||
std::ostream& os) const { // NOLINT
|
||||
for (int i = 0; i < OperandCount(); i++) {
|
||||
os << NameOf(OperandAt(i)) << " ";
|
||||
}
|
||||
return os << "flags: " << flags();
|
||||
}
|
||||
|
||||
|
||||
std::ostream& HUnknownOSRValue::PrintDataTo(std::ostream& os) const { // NOLINT
|
||||
const char* type = "expression";
|
||||
if (environment_->is_local_index(index_)) type = "local";
|
||||
|
@ -156,7 +156,6 @@ class LChunkBuilder;
|
||||
V(StringCharFromCode) \
|
||||
V(StringCompareAndBranch) \
|
||||
V(Sub) \
|
||||
V(TailCallThroughMegamorphicCache) \
|
||||
V(ThisFunction) \
|
||||
V(ToFastProperties) \
|
||||
V(TransitionElementsKind) \
|
||||
@ -5353,44 +5352,6 @@ class HCallStub final : public HUnaryCall {
|
||||
};
|
||||
|
||||
|
||||
class HTailCallThroughMegamorphicCache final : public HInstruction {
|
||||
public:
|
||||
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P2(HTailCallThroughMegamorphicCache,
|
||||
HValue*, HValue*);
|
||||
|
||||
Representation RequiredInputRepresentation(int index) override {
|
||||
return Representation::Tagged();
|
||||
}
|
||||
|
||||
virtual int OperandCount() const final override { return 3; }
|
||||
virtual HValue* OperandAt(int i) const final override { return inputs_[i]; }
|
||||
|
||||
HValue* context() const { return OperandAt(0); }
|
||||
HValue* receiver() const { return OperandAt(1); }
|
||||
HValue* name() const { return OperandAt(2); }
|
||||
Code::Flags flags() const;
|
||||
|
||||
std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(TailCallThroughMegamorphicCache)
|
||||
|
||||
protected:
|
||||
virtual void InternalSetOperandAt(int i, HValue* value) final override {
|
||||
inputs_[i] = value;
|
||||
}
|
||||
|
||||
private:
|
||||
HTailCallThroughMegamorphicCache(HValue* context, HValue* receiver,
|
||||
HValue* name) {
|
||||
SetOperandAt(0, context);
|
||||
SetOperandAt(1, receiver);
|
||||
SetOperandAt(2, name);
|
||||
}
|
||||
|
||||
EmbeddedContainer<HValue*, 3> inputs_;
|
||||
};
|
||||
|
||||
|
||||
class HUnknownOSRValue final : public HTemplateInstruction<0> {
|
||||
public:
|
||||
DECLARE_INSTRUCTION_FACTORY_P2(HUnknownOSRValue, HEnvironment*, int);
|
||||
@ -5440,10 +5401,9 @@ class HLoadGlobalGeneric final : public HTemplateInstruction<2> {
|
||||
Handle<TypeFeedbackVector> feedback_vector() const {
|
||||
return feedback_vector_;
|
||||
}
|
||||
bool HasVectorAndSlot() const { return FLAG_vector_ics; }
|
||||
bool HasVectorAndSlot() const { return true; }
|
||||
void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
|
||||
FeedbackVectorICSlot slot) {
|
||||
DCHECK(FLAG_vector_ics);
|
||||
feedback_vector_ = vector;
|
||||
slot_ = slot;
|
||||
}
|
||||
@ -6448,10 +6408,9 @@ class HLoadNamedGeneric final : public HTemplateInstruction<2> {
|
||||
Handle<TypeFeedbackVector> feedback_vector() const {
|
||||
return feedback_vector_;
|
||||
}
|
||||
bool HasVectorAndSlot() const { return FLAG_vector_ics; }
|
||||
bool HasVectorAndSlot() const { return true; }
|
||||
void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
|
||||
FeedbackVectorICSlot slot) {
|
||||
DCHECK(FLAG_vector_ics);
|
||||
feedback_vector_ = vector;
|
||||
slot_ = slot;
|
||||
}
|
||||
@ -6731,13 +6690,11 @@ class HLoadKeyedGeneric final : public HTemplateInstruction<3> {
|
||||
return feedback_vector_;
|
||||
}
|
||||
bool HasVectorAndSlot() const {
|
||||
DCHECK(!FLAG_vector_ics || initialization_state_ == MEGAMORPHIC ||
|
||||
!feedback_vector_.is_null());
|
||||
DCHECK(initialization_state_ == MEGAMORPHIC || !feedback_vector_.is_null());
|
||||
return !feedback_vector_.is_null();
|
||||
}
|
||||
void SetVectorAndSlot(Handle<TypeFeedbackVector> vector,
|
||||
FeedbackVectorICSlot slot) {
|
||||
DCHECK(FLAG_vector_ics);
|
||||
feedback_vector_ = vector;
|
||||
slot_ = slot;
|
||||
}
|
||||
|
@ -5491,10 +5491,8 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
|
||||
New<HLoadGlobalGeneric>(global_object,
|
||||
variable->name(),
|
||||
ast_context()->is_for_typeof());
|
||||
if (FLAG_vector_ics) {
|
||||
instr->SetVectorAndSlot(handle(current_feedback_vector(), isolate()),
|
||||
expr->VariableFeedbackSlot());
|
||||
}
|
||||
instr->SetVectorAndSlot(handle(current_feedback_vector(), isolate()),
|
||||
expr->VariableFeedbackSlot());
|
||||
return ast_context()->ReturnInstruction(instr, expr->id());
|
||||
}
|
||||
}
|
||||
@ -7018,29 +7016,26 @@ HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
|
||||
Deoptimizer::SOFT);
|
||||
}
|
||||
if (access_type == LOAD) {
|
||||
if (FLAG_vector_ics) {
|
||||
Handle<TypeFeedbackVector> vector =
|
||||
handle(current_feedback_vector(), isolate());
|
||||
FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot();
|
||||
Handle<TypeFeedbackVector> vector =
|
||||
handle(current_feedback_vector(), isolate());
|
||||
FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot();
|
||||
|
||||
if (!expr->AsProperty()->key()->IsPropertyName()) {
|
||||
// It's possible that a keyed load of a constant string was converted
|
||||
// to a named load. Here, at the last minute, we need to make sure to
|
||||
// use a generic Keyed Load if we are using the type vector, because
|
||||
// it has to share information with full code.
|
||||
HConstant* key = Add<HConstant>(name);
|
||||
HLoadKeyedGeneric* result =
|
||||
New<HLoadKeyedGeneric>(object, key, PREMONOMORPHIC);
|
||||
result->SetVectorAndSlot(vector, slot);
|
||||
return result;
|
||||
}
|
||||
|
||||
HLoadNamedGeneric* result =
|
||||
New<HLoadNamedGeneric>(object, name, PREMONOMORPHIC);
|
||||
if (!expr->AsProperty()->key()->IsPropertyName()) {
|
||||
// It's possible that a keyed load of a constant string was converted
|
||||
// to a named load. Here, at the last minute, we need to make sure to
|
||||
// use a generic Keyed Load if we are using the type vector, because
|
||||
// it has to share information with full code.
|
||||
HConstant* key = Add<HConstant>(name);
|
||||
HLoadKeyedGeneric* result =
|
||||
New<HLoadKeyedGeneric>(object, key, PREMONOMORPHIC);
|
||||
result->SetVectorAndSlot(vector, slot);
|
||||
return result;
|
||||
}
|
||||
return New<HLoadNamedGeneric>(object, name, PREMONOMORPHIC);
|
||||
|
||||
HLoadNamedGeneric* result =
|
||||
New<HLoadNamedGeneric>(object, name, PREMONOMORPHIC);
|
||||
result->SetVectorAndSlot(vector, slot);
|
||||
return result;
|
||||
} else {
|
||||
return New<HStoreNamedGeneric>(object, name, value,
|
||||
function_language_mode(), PREMONOMORPHIC);
|
||||
@ -7056,14 +7051,12 @@ HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
|
||||
HValue* key,
|
||||
HValue* value) {
|
||||
if (access_type == LOAD) {
|
||||
InlineCacheState initial_state =
|
||||
FLAG_vector_ics ? expr->AsProperty()->GetInlineCacheState()
|
||||
: PREMONOMORPHIC;
|
||||
InlineCacheState initial_state = expr->AsProperty()->GetInlineCacheState();
|
||||
HLoadKeyedGeneric* result =
|
||||
New<HLoadKeyedGeneric>(object, key, initial_state);
|
||||
// HLoadKeyedGeneric with vector ics benefits from being encoded as
|
||||
// MEGAMORPHIC because the vector/slot combo becomes unnecessary.
|
||||
if (FLAG_vector_ics && initial_state != MEGAMORPHIC) {
|
||||
if (initial_state != MEGAMORPHIC) {
|
||||
// We need to pass vector information.
|
||||
Handle<TypeFeedbackVector> vector =
|
||||
handle(current_feedback_vector(), isolate());
|
||||
|
@ -653,19 +653,14 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
||||
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
Label miss;
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
if (FLAG_vector_ics) {
|
||||
// With careful management, we won't have to save slot and vector on
|
||||
// the stack. Simply handle the possibly missing case first.
|
||||
// TODO(mvstanton): this code can be more efficient.
|
||||
__ cmp(FieldOperand(receiver, JSFunction::kPrototypeOrInitialMapOffset),
|
||||
Immediate(isolate()->factory()->the_hole_value()));
|
||||
__ j(equal, &miss);
|
||||
__ TryGetFunctionPrototype(receiver, eax, ebx, &miss);
|
||||
__ ret(0);
|
||||
} else {
|
||||
NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, eax,
|
||||
ebx, &miss);
|
||||
}
|
||||
// With careful management, we won't have to save slot and vector on
|
||||
// the stack. Simply handle the possibly missing case first.
|
||||
// TODO(mvstanton): this code can be more efficient.
|
||||
__ cmp(FieldOperand(receiver, JSFunction::kPrototypeOrInitialMapOffset),
|
||||
Immediate(isolate()->factory()->the_hole_value()));
|
||||
__ j(equal, &miss);
|
||||
__ TryGetFunctionPrototype(receiver, eax, ebx, &miss);
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&miss);
|
||||
PropertyAccessCompiler::TailCallBuiltin(
|
||||
@ -713,9 +708,8 @@ void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
|
||||
DCHECK(!scratch.is(receiver) && !scratch.is(index));
|
||||
Register result = eax;
|
||||
DCHECK(!result.is(scratch));
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
(!scratch.is(VectorLoadICDescriptor::VectorRegister()) &&
|
||||
result.is(VectorLoadICDescriptor::SlotRegister())));
|
||||
DCHECK(!scratch.is(VectorLoadICDescriptor::VectorRegister()) &&
|
||||
result.is(VectorLoadICDescriptor::SlotRegister()));
|
||||
|
||||
// StringCharAtGenerator doesn't use the result register until it's passed
|
||||
// the different miss possibilities. If it did, we would have a conflict
|
||||
@ -2974,7 +2968,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
index_not_number_,
|
||||
DONT_DO_SMI_CHECK);
|
||||
call_helper.BeforeCall(masm);
|
||||
if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
|
||||
if (embed_mode == PART_OF_IC_HANDLER) {
|
||||
__ push(VectorLoadICDescriptor::VectorRegister());
|
||||
__ push(VectorLoadICDescriptor::SlotRegister());
|
||||
}
|
||||
@ -2993,7 +2987,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
__ mov(index_, eax);
|
||||
}
|
||||
__ pop(object_);
|
||||
if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
|
||||
if (embed_mode == PART_OF_IC_HANDLER) {
|
||||
__ pop(VectorLoadICDescriptor::SlotRegister());
|
||||
__ pop(VectorLoadICDescriptor::VectorRegister());
|
||||
}
|
||||
|
@ -183,10 +183,8 @@ void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for IC load call (from ic-ia32.cc).
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
RegList regs = receiver.bit() | name.bit();
|
||||
if (FLAG_vector_ics) {
|
||||
regs |= VectorLoadICTrampolineDescriptor::SlotRegister().bit();
|
||||
}
|
||||
RegList regs = receiver.bit() | name.bit() |
|
||||
VectorLoadICTrampolineDescriptor::SlotRegister().bit();
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0, false);
|
||||
}
|
||||
|
||||
|
@ -1259,13 +1259,9 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
|
||||
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
|
||||
__ mov(LoadDescriptor::NameRegister(), home_object_symbol);
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
|
||||
__ cmp(eax, isolate()->factory()->undefined_value());
|
||||
Label done;
|
||||
@ -1340,10 +1336,8 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
||||
// load IC call.
|
||||
__ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ mov(LoadDescriptor::NameRegister(), proxy->var()->name());
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
|
||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? NOT_CONTEXTUAL
|
||||
@ -1428,10 +1422,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
__ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ mov(LoadDescriptor::NameRegister(), var->name());
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
CallGlobalLoadIC(var->name());
|
||||
context()->Plug(eax);
|
||||
break;
|
||||
@ -2125,10 +2117,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// result = receiver[f](arg);
|
||||
__ bind(&l_call);
|
||||
__ mov(load_receiver, Operand(esp, kPointerSize));
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ mov(edi, eax);
|
||||
@ -2145,10 +2135,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ Move(load_receiver, eax); // result
|
||||
__ mov(load_name,
|
||||
isolate()->factory()->done_string()); // "done"
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(expr->DoneFeedbackSlot())));
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(expr->DoneFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.done in eax
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(bool_ic);
|
||||
@ -2159,10 +2147,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ pop(load_receiver); // result
|
||||
__ mov(load_name,
|
||||
isolate()->factory()->value_string()); // "value"
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(expr->ValueFeedbackSlot())));
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(expr->ValueFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.value in eax
|
||||
context()->DropAndPlug(2, eax); // drop iter and g
|
||||
break;
|
||||
@ -2300,13 +2286,9 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
DCHECK(!prop->IsSuperAccess());
|
||||
|
||||
__ mov(LoadDescriptor::NameRegister(), Immediate(key->value()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -2325,13 +2307,9 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallIC(ic);
|
||||
} else {
|
||||
CallIC(ic, prop->PropertyFeedbackId());
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallIC(ic);
|
||||
}
|
||||
|
||||
|
||||
@ -4553,13 +4531,9 @@ void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
|
||||
// Load the function from the receiver.
|
||||
__ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
|
||||
__ mov(LoadDescriptor::NameRegister(), Immediate(expr->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(expr->CallRuntimeFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(expr->CallRuntimeFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -4998,10 +4972,8 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
__ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ mov(LoadDescriptor::NameRegister(), Immediate(proxy->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
}
|
||||
__ mov(VectorLoadICDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
|
@ -2868,7 +2868,6 @@ void LCodeGen::DoReturn(LReturn* instr) {
|
||||
|
||||
template <class T>
|
||||
void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
|
||||
DCHECK(FLAG_vector_ics);
|
||||
Register vector_register = ToRegister(instr->temp_vector());
|
||||
Register slot_register = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister()));
|
||||
@ -2891,9 +2890,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
DCHECK(ToRegister(instr->result()).is(eax));
|
||||
|
||||
__ mov(LoadDescriptor::NameRegister(), instr->name());
|
||||
if (FLAG_vector_ics) {
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
}
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
|
||||
PREMONOMORPHIC).code();
|
||||
@ -3010,9 +3007,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
DCHECK(ToRegister(instr->result()).is(eax));
|
||||
|
||||
__ mov(LoadDescriptor::NameRegister(), instr->name());
|
||||
if (FLAG_vector_ics) {
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
}
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL,
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
@ -3485,27 +3480,6 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
||||
}
|
||||
|
||||
|
||||
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()));
|
||||
Register scratch = ebx;
|
||||
Register extra = edi;
|
||||
DCHECK(!scratch.is(receiver) && !scratch.is(name));
|
||||
DCHECK(!extra.is(receiver) && !extra.is(name));
|
||||
|
||||
// The probe will tail call to a handler if found.
|
||||
// If --vector-ics is on, then it knows to pop the two args first.
|
||||
isolate()->stub_cache()->GenerateProbe(masm(), Code::LOAD_IC,
|
||||
instr->hydrogen()->flags(), false,
|
||||
receiver, name, scratch, extra);
|
||||
|
||||
LoadIC::GenerateMiss(masm());
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
|
||||
DCHECK(ToRegister(instr->result()).is(eax));
|
||||
|
||||
|
@ -1146,20 +1146,6 @@ LInstruction* LChunkBuilder::DoCallWithDescriptor(
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
|
||||
HTailCallThroughMegamorphicCache* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), esi);
|
||||
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(), esi);
|
||||
LOperand* function = UseFixed(instr->function(), edi);
|
||||
|
@ -155,7 +155,6 @@ class LCodeGen;
|
||||
V(StringCompareAndBranch) \
|
||||
V(SubI) \
|
||||
V(TaggedToI) \
|
||||
V(TailCallThroughMegamorphicCache) \
|
||||
V(ThisFunction) \
|
||||
V(ToFastProperties) \
|
||||
V(TransitionElementsKind) \
|
||||
@ -470,26 +469,6 @@ class LCallStub final : public LTemplateInstruction<1, 1, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LTailCallThroughMegamorphicCache final
|
||||
: public LTemplateInstruction<0, 3, 0> {
|
||||
public:
|
||||
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:
|
||||
bool HasInterestingComment(LCodeGen* gen) const override { return false; }
|
||||
|
@ -55,11 +55,9 @@ class PropertyAccessCompiler BASE_EMBEDDED {
|
||||
Register receiver() const { return registers_[0]; }
|
||||
Register name() const { return registers_[1]; }
|
||||
Register slot() const {
|
||||
DCHECK(FLAG_vector_ics);
|
||||
return VectorLoadICDescriptor::SlotRegister();
|
||||
}
|
||||
Register vector() const {
|
||||
DCHECK(FLAG_vector_ics);
|
||||
return VectorLoadICDescriptor::VectorRegister();
|
||||
}
|
||||
Register scratch1() const { return registers_[2]; }
|
||||
|
@ -289,14 +289,10 @@ static const Register LoadIC_TempRegister() { return r3; }
|
||||
static void LoadIC_PushArgs(MacroAssembler* masm) {
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
if (FLAG_vector_ics) {
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
|
||||
__ Push(receiver, name, slot, vector);
|
||||
} else {
|
||||
__ Push(receiver, name);
|
||||
}
|
||||
__ Push(receiver, name, slot, vector);
|
||||
}
|
||||
|
||||
|
||||
@ -304,8 +300,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// The return address is in lr.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!AreAliased(r4, r5, VectorLoadICDescriptor::SlotRegister(),
|
||||
DCHECK(!AreAliased(r4, r5, VectorLoadICDescriptor::SlotRegister(),
|
||||
VectorLoadICDescriptor::VectorRegister()));
|
||||
__ IncrementCounter(isolate->counters()->load_miss(), 1, r4, r5);
|
||||
|
||||
@ -313,7 +308,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
|
||||
int arg_count = FLAG_vector_ics ? 4 : 2;
|
||||
int arg_count = 4;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
}
|
||||
|
||||
@ -441,8 +436,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// The return address is in lr.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!AreAliased(r4, r5, VectorLoadICDescriptor::SlotRegister(),
|
||||
DCHECK(!AreAliased(r4, r5, VectorLoadICDescriptor::SlotRegister(),
|
||||
VectorLoadICDescriptor::VectorRegister()));
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r4, r5);
|
||||
|
||||
@ -451,7 +445,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate);
|
||||
int arg_count = FLAG_vector_ics ? 4 : 2;
|
||||
int arg_count = 4;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
}
|
||||
|
||||
@ -527,20 +521,16 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
__ cmp(r4, ip);
|
||||
__ b(eq, &probe_dictionary);
|
||||
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
// When vector ics are in use, the handlers in the stub cache expect a
|
||||
// vector and slot. Since we won't change the IC from any downstream
|
||||
// misses, a dummy vector can be used.
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(!AreAliased(vector, slot, r4, r5, r6, r9));
|
||||
Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast(
|
||||
masm->isolate()->factory()->keyed_load_dummy_vector());
|
||||
int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0));
|
||||
__ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex);
|
||||
__ mov(slot, Operand(Smi::FromInt(int_slot)));
|
||||
}
|
||||
// The handlers in the stub cache expect a vector and slot. Since we won't
|
||||
// change the IC from any downstream misses, a dummy vector can be used.
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(!AreAliased(vector, slot, r4, r5, r6, r9));
|
||||
Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast(
|
||||
masm->isolate()->factory()->keyed_load_dummy_vector());
|
||||
int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0));
|
||||
__ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex);
|
||||
__ mov(slot, Operand(Smi::FromInt(int_slot)));
|
||||
|
||||
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
|
||||
Code::ComputeHandlerFlags(Code::LOAD_IC));
|
||||
|
@ -368,22 +368,17 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
Isolate* isolate = masm->isolate();
|
||||
ASM_LOCATION("LoadIC::GenerateMiss");
|
||||
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!AreAliased(x4, x5, VectorLoadICDescriptor::SlotRegister(),
|
||||
DCHECK(!AreAliased(x4, x5, VectorLoadICDescriptor::SlotRegister(),
|
||||
VectorLoadICDescriptor::VectorRegister()));
|
||||
__ IncrementCounter(isolate->counters()->load_miss(), 1, x4, x5);
|
||||
|
||||
// Perform tail call to the entry.
|
||||
if (FLAG_vector_ics) {
|
||||
__ Push(VectorLoadICDescriptor::ReceiverRegister(),
|
||||
VectorLoadICDescriptor::NameRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister(),
|
||||
VectorLoadICDescriptor::VectorRegister());
|
||||
} else {
|
||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
||||
}
|
||||
__ Push(VectorLoadICDescriptor::ReceiverRegister(),
|
||||
VectorLoadICDescriptor::NameRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister(),
|
||||
VectorLoadICDescriptor::VectorRegister());
|
||||
ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
|
||||
int arg_count = FLAG_vector_ics ? 4 : 2;
|
||||
int arg_count = 4;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
}
|
||||
|
||||
@ -445,24 +440,19 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// The return address is in lr.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!AreAliased(x10, x11, VectorLoadICDescriptor::SlotRegister(),
|
||||
DCHECK(!AreAliased(x10, x11, VectorLoadICDescriptor::SlotRegister(),
|
||||
VectorLoadICDescriptor::VectorRegister()));
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, x10, x11);
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
__ Push(VectorLoadICDescriptor::ReceiverRegister(),
|
||||
VectorLoadICDescriptor::NameRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister(),
|
||||
VectorLoadICDescriptor::VectorRegister());
|
||||
} else {
|
||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
||||
}
|
||||
__ Push(VectorLoadICDescriptor::ReceiverRegister(),
|
||||
VectorLoadICDescriptor::NameRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister(),
|
||||
VectorLoadICDescriptor::VectorRegister());
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate);
|
||||
int arg_count = FLAG_vector_ics ? 4 : 2;
|
||||
int arg_count = 4;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
}
|
||||
|
||||
@ -533,19 +523,16 @@ static void GenerateKeyedLoadWithNameKey(MacroAssembler* masm, Register key,
|
||||
__ Ldr(scratch3, FieldMemOperand(scratch2, HeapObject::kMapOffset));
|
||||
__ JumpIfRoot(scratch3, Heap::kHashTableMapRootIndex, &probe_dictionary);
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
// When vector ics are in use, the handlers in the stub cache expect a
|
||||
// vector and slot. Since we won't change the IC from any downstream
|
||||
// misses, a dummy vector can be used.
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(!AreAliased(vector, slot, scratch1, scratch2, scratch3, scratch4));
|
||||
Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast(
|
||||
masm->isolate()->factory()->keyed_load_dummy_vector());
|
||||
int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0));
|
||||
__ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex);
|
||||
__ Mov(slot, Operand(Smi::FromInt(int_slot)));
|
||||
}
|
||||
// The handlers in the stub cache expect a vector and slot. Since we won't
|
||||
// change the IC from any downstream misses, a dummy vector can be used.
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(!AreAliased(vector, slot, scratch1, scratch2, scratch3, scratch4));
|
||||
Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast(
|
||||
masm->isolate()->factory()->keyed_load_dummy_vector());
|
||||
int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0));
|
||||
__ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex);
|
||||
__ Mov(slot, Operand(Smi::FromInt(int_slot)));
|
||||
|
||||
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
|
||||
Code::ComputeHandlerFlags(Code::LOAD_IC));
|
||||
|
@ -130,10 +130,9 @@ void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
|
||||
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
||||
MacroAssembler* masm, Register receiver, Register scratch1,
|
||||
Register scratch2, Label* miss_label) {
|
||||
DCHECK(!FLAG_vector_ics);
|
||||
__ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
|
||||
__ mov(eax, scratch1);
|
||||
__ ret(0);
|
||||
// TODO(mvstanton): This isn't used on ia32. Move all the other
|
||||
// platform implementations into a code stub so this method can be removed.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
|
@ -399,26 +399,21 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
Immediate(isolate->factory()->hash_table_map()));
|
||||
__ j(equal, &probe_dictionary);
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
// When vector ics are in use, the handlers in the stub cache expect a
|
||||
// vector and slot. Since we won't change the IC from any downstream
|
||||
// misses, a dummy vector can be used.
|
||||
Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast(
|
||||
isolate->factory()->keyed_load_dummy_vector());
|
||||
int slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0));
|
||||
__ push(Immediate(Smi::FromInt(slot)));
|
||||
__ push(Immediate(dummy_vector));
|
||||
}
|
||||
// The handlers in the stub cache expect a vector and slot. Since we won't
|
||||
// change the IC from any downstream misses, a dummy vector can be used.
|
||||
Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast(
|
||||
isolate->factory()->keyed_load_dummy_vector());
|
||||
int slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0));
|
||||
__ push(Immediate(Smi::FromInt(slot)));
|
||||
__ push(Immediate(dummy_vector));
|
||||
|
||||
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
|
||||
Code::ComputeHandlerFlags(Code::LOAD_IC));
|
||||
masm->isolate()->stub_cache()->GenerateProbe(masm, Code::KEYED_LOAD_IC, flags,
|
||||
false, receiver, key, ebx, edi);
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
__ pop(VectorLoadICDescriptor::VectorRegister());
|
||||
__ pop(VectorLoadICDescriptor::SlotRegister());
|
||||
}
|
||||
__ pop(VectorLoadICDescriptor::VectorRegister());
|
||||
__ pop(VectorLoadICDescriptor::SlotRegister());
|
||||
|
||||
// Cache miss.
|
||||
GenerateMiss(masm);
|
||||
@ -733,26 +728,18 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
static void LoadIC_PushArgs(MacroAssembler* masm) {
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
if (FLAG_vector_ics) {
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
DCHECK(!edi.is(receiver) && !edi.is(name) && !edi.is(slot) &&
|
||||
!edi.is(vector));
|
||||
|
||||
__ pop(edi);
|
||||
__ push(receiver);
|
||||
__ push(name);
|
||||
__ push(slot);
|
||||
__ push(vector);
|
||||
__ push(edi);
|
||||
} else {
|
||||
DCHECK(!ebx.is(receiver) && !ebx.is(name));
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
DCHECK(!edi.is(receiver) && !edi.is(name) && !edi.is(slot) &&
|
||||
!edi.is(vector));
|
||||
|
||||
__ pop(ebx);
|
||||
__ push(receiver);
|
||||
__ push(name);
|
||||
__ push(ebx);
|
||||
}
|
||||
__ pop(edi);
|
||||
__ push(receiver);
|
||||
__ push(name);
|
||||
__ push(slot);
|
||||
__ push(vector);
|
||||
__ push(edi);
|
||||
}
|
||||
|
||||
|
||||
@ -764,7 +751,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate());
|
||||
int arg_count = FLAG_vector_ics ? 4 : 2;
|
||||
int arg_count = 4;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
}
|
||||
|
||||
@ -794,7 +781,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate());
|
||||
int arg_count = FLAG_vector_ics ? 4 : 2;
|
||||
int arg_count = 4;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
}
|
||||
|
||||
|
@ -87,26 +87,6 @@ Handle<Code> PropertyICCompiler::ComputeMonomorphic(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphic(
|
||||
Handle<Map> receiver_map) {
|
||||
Isolate* isolate = receiver_map->GetIsolate();
|
||||
DCHECK(KeyedLoadIC::GetKeyType(kNoExtraICState) == ELEMENT);
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC);
|
||||
Handle<Name> name = isolate->factory()->KeyedLoadMonomorphic_string();
|
||||
|
||||
Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
||||
Handle<Code> stub = ComputeKeyedLoadMonomorphicHandler(receiver_map);
|
||||
PropertyICCompiler compiler(isolate, Code::KEYED_LOAD_IC);
|
||||
Handle<Code> code = compiler.CompileMonomorphic(
|
||||
receiver_map, stub, isolate->factory()->empty_string(), ELEMENT);
|
||||
|
||||
Map::UpdateCodeCache(receiver_map, name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
|
||||
Handle<Map> receiver_map) {
|
||||
Isolate* isolate = receiver_map->GetIsolate();
|
||||
@ -189,31 +169,6 @@ static void FillCache(Isolate* isolate, Handle<Code> code) {
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::ComputeLoad(Isolate* isolate,
|
||||
InlineCacheState ic_state,
|
||||
ExtraICState extra_state) {
|
||||
Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state);
|
||||
Handle<UnseededNumberDictionary> cache =
|
||||
isolate->factory()->non_monomorphic_cache();
|
||||
int entry = cache->FindEntry(isolate, flags);
|
||||
if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
|
||||
|
||||
PropertyICCompiler compiler(isolate, Code::LOAD_IC);
|
||||
Handle<Code> code;
|
||||
if (ic_state == UNINITIALIZED) {
|
||||
code = compiler.CompileLoadInitialize(flags);
|
||||
} else if (ic_state == PREMONOMORPHIC) {
|
||||
code = compiler.CompileLoadPreMonomorphic(flags);
|
||||
} else if (ic_state == MEGAMORPHIC) {
|
||||
code = compiler.CompileLoadMegamorphic(flags);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
FillCache(isolate, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::ComputeStore(Isolate* isolate,
|
||||
InlineCacheState ic_state,
|
||||
ExtraICState extra_state) {
|
||||
@ -334,23 +289,6 @@ Handle<Code> PropertyICCompiler::CompileLoadInitialize(Code::Flags flags) {
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::CompileLoadPreMonomorphic(Code::Flags flags) {
|
||||
LoadIC::GeneratePreMonomorphic(masm());
|
||||
Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic");
|
||||
PROFILE(isolate(),
|
||||
CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0));
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::CompileLoadMegamorphic(Code::Flags flags) {
|
||||
MegamorphicLoadStub stub(isolate(), LoadICState(extra_ic_state_));
|
||||
auto code = stub.GetCode();
|
||||
PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0));
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> PropertyICCompiler::CompileStoreInitialize(Code::Flags flags) {
|
||||
StoreIC::GenerateInitialize(masm());
|
||||
Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreInitialize");
|
||||
|
@ -18,8 +18,6 @@ class PropertyICCompiler : public PropertyAccessCompiler {
|
||||
ExtraICState extra_ic_state);
|
||||
|
||||
// Named
|
||||
static Handle<Code> ComputeLoad(Isolate* isolate, InlineCacheState ic_state,
|
||||
ExtraICState extra_state);
|
||||
static Handle<Code> ComputeStore(Isolate* isolate, InlineCacheState ic_state,
|
||||
ExtraICState extra_state);
|
||||
|
||||
@ -35,7 +33,6 @@ class PropertyICCompiler : public PropertyAccessCompiler {
|
||||
// Keyed
|
||||
static Handle<Code> ComputeKeyedLoadMonomorphicHandler(
|
||||
Handle<Map> receiver_map);
|
||||
static Handle<Code> ComputeKeyedLoadMonomorphic(Handle<Map> receiver_map);
|
||||
|
||||
static Handle<Code> ComputeKeyedStoreMonomorphic(
|
||||
Handle<Map> receiver_map, LanguageMode language_mode,
|
||||
@ -69,8 +66,6 @@ class PropertyICCompiler : public PropertyAccessCompiler {
|
||||
CacheHolderFlag cache_holder = kCacheOnReceiver);
|
||||
|
||||
Handle<Code> CompileLoadInitialize(Code::Flags flags);
|
||||
Handle<Code> CompileLoadPreMonomorphic(Code::Flags flags);
|
||||
Handle<Code> CompileLoadMegamorphic(Code::Flags flags);
|
||||
Handle<Code> CompileStoreInitialize(Code::Flags flags);
|
||||
Handle<Code> CompileStorePreMonomorphic(Code::Flags flags);
|
||||
Handle<Code> CompileStoreGeneric(Code::Flags flags);
|
||||
|
@ -98,7 +98,7 @@ void IC::SetTargetAtAddress(Address address, Code* target,
|
||||
DCHECK(target->is_inline_cache_stub() || target->is_compare_ic_stub());
|
||||
|
||||
// Don't use this for load_ics when --vector-ics is turned on.
|
||||
DCHECK(!(FLAG_vector_ics && target->is_inline_cache_stub()) ||
|
||||
DCHECK(!target->is_inline_cache_stub() ||
|
||||
(target->kind() != Code::LOAD_IC &&
|
||||
target->kind() != Code::KEYED_LOAD_IC));
|
||||
|
||||
|
283
src/ic/ic.cc
283
src/ic/ic.cc
@ -495,11 +495,8 @@ void IC::Clear(Isolate* isolate, Address address,
|
||||
|
||||
switch (target->kind()) {
|
||||
case Code::LOAD_IC:
|
||||
if (FLAG_vector_ics) return;
|
||||
return LoadIC::Clear(isolate, address, target, constant_pool);
|
||||
case Code::KEYED_LOAD_IC:
|
||||
if (FLAG_vector_ics) return;
|
||||
return KeyedLoadIC::Clear(isolate, address, target, constant_pool);
|
||||
return;
|
||||
case Code::STORE_IC:
|
||||
return StoreIC::Clear(isolate, address, target, constant_pool);
|
||||
case Code::KEYED_STORE_IC:
|
||||
@ -520,18 +517,6 @@ void IC::Clear(Isolate* isolate, Address address,
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target,
|
||||
ConstantPoolArray* constant_pool) {
|
||||
DCHECK(!FLAG_vector_ics);
|
||||
if (IsCleared(target)) return;
|
||||
|
||||
// Make sure to also clear the map used in inline fast cases. If we
|
||||
// do not clear these maps, cached code can keep objects alive
|
||||
// through the embedded maps.
|
||||
SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool);
|
||||
}
|
||||
|
||||
|
||||
void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) {
|
||||
if (IsCleared(nexus)) return;
|
||||
// Make sure to also clear the map used in inline fast cases. If we
|
||||
@ -556,16 +541,6 @@ void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::Clear(Isolate* isolate, Address address, Code* target,
|
||||
ConstantPoolArray* constant_pool) {
|
||||
DCHECK(!FLAG_vector_ics);
|
||||
if (IsCleared(target)) return;
|
||||
Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC,
|
||||
target->extra_ic_state());
|
||||
SetTargetAtAddress(address, code, constant_pool);
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) {
|
||||
if (IsCleared(nexus)) return;
|
||||
State state = nexus->StateFromFeedback();
|
||||
@ -941,78 +916,29 @@ void IC::PatchCache(Handle<Name> name, Handle<Code> code) {
|
||||
|
||||
Handle<Code> LoadIC::initialize_stub(Isolate* isolate,
|
||||
ExtraICState extra_state) {
|
||||
if (FLAG_vector_ics) {
|
||||
return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode();
|
||||
}
|
||||
|
||||
return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> LoadIC::load_global(Isolate* isolate, Handle<GlobalObject> global,
|
||||
Handle<String> name) {
|
||||
// This special IC doesn't work with vector ics.
|
||||
DCHECK(!FLAG_vector_ics);
|
||||
|
||||
Handle<ScriptContextTable> script_contexts(
|
||||
global->native_context()->script_context_table());
|
||||
|
||||
ScriptContextTable::LookupResult lookup_result;
|
||||
if (ScriptContextTable::Lookup(script_contexts, name, &lookup_result)) {
|
||||
return initialize_stub(isolate, LoadICState(CONTEXTUAL).GetExtraICState());
|
||||
}
|
||||
|
||||
Handle<Map> global_map(global->map());
|
||||
Handle<Code> handler = PropertyHandlerCompiler::Find(
|
||||
name, global_map, Code::LOAD_IC, kCacheOnReceiver, Code::NORMAL);
|
||||
if (handler.is_null()) {
|
||||
LookupIterator it(global, name);
|
||||
if (!it.IsFound() || !it.GetHolder<JSObject>().is_identical_to(global) ||
|
||||
it.state() != LookupIterator::DATA) {
|
||||
return initialize_stub(isolate,
|
||||
LoadICState(CONTEXTUAL).GetExtraICState());
|
||||
}
|
||||
NamedLoadHandlerCompiler compiler(isolate, global_map, global,
|
||||
kCacheOnReceiver);
|
||||
Handle<PropertyCell> cell = it.GetPropertyCell();
|
||||
handler = compiler.CompileLoadGlobal(cell, name, it.IsConfigurable());
|
||||
Map::UpdateCodeCache(global_map, name, handler);
|
||||
}
|
||||
return PropertyICCompiler::ComputeMonomorphic(
|
||||
Code::LOAD_IC, name, handle(global->map()), handler,
|
||||
LoadICState(CONTEXTUAL).GetExtraICState());
|
||||
return LoadICTrampolineStub(isolate, LoadICState(extra_state)).GetCode();
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> LoadIC::initialize_stub_in_optimized_code(
|
||||
Isolate* isolate, ExtraICState extra_state, State initialization_state) {
|
||||
if (FLAG_vector_ics) {
|
||||
return VectorRawLoadStub(isolate, LoadICState(extra_state)).GetCode();
|
||||
}
|
||||
return PropertyICCompiler::ComputeLoad(isolate, initialization_state,
|
||||
extra_state);
|
||||
return VectorRawLoadStub(isolate, LoadICState(extra_state)).GetCode();
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadIC::initialize_stub(Isolate* isolate) {
|
||||
if (FLAG_vector_ics) {
|
||||
return KeyedLoadICTrampolineStub(isolate).GetCode();
|
||||
}
|
||||
|
||||
return isolate->builtins()->KeyedLoadIC_Initialize();
|
||||
return KeyedLoadICTrampolineStub(isolate).GetCode();
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code(
|
||||
Isolate* isolate, State initialization_state) {
|
||||
if (FLAG_vector_ics && initialization_state != MEGAMORPHIC) {
|
||||
if (initialization_state != MEGAMORPHIC) {
|
||||
return VectorRawKeyedLoadStub(isolate).GetCode();
|
||||
}
|
||||
switch (initialization_state) {
|
||||
case UNINITIALIZED:
|
||||
return isolate->builtins()->KeyedLoadIC_Initialize();
|
||||
case PREMONOMORPHIC:
|
||||
return isolate->builtins()->KeyedLoadIC_PreMonomorphic();
|
||||
case MEGAMORPHIC:
|
||||
return isolate->builtins()->KeyedLoadIC_Megamorphic();
|
||||
default:
|
||||
@ -1046,35 +972,8 @@ Handle<Code> KeyedStoreIC::initialize_stub(Isolate* isolate,
|
||||
|
||||
|
||||
Handle<Code> LoadIC::megamorphic_stub() {
|
||||
if (kind() == Code::LOAD_IC) {
|
||||
MegamorphicLoadStub stub(isolate(), LoadICState(extra_ic_state()));
|
||||
return stub.GetCode();
|
||||
} else {
|
||||
DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
|
||||
return KeyedLoadIC::ChooseMegamorphicStub(isolate());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate,
|
||||
ExtraICState extra_state) {
|
||||
DCHECK(!FLAG_vector_ics);
|
||||
return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadIC::pre_monomorphic_stub(Isolate* isolate) {
|
||||
return isolate->builtins()->KeyedLoadIC_PreMonomorphic();
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> LoadIC::pre_monomorphic_stub() const {
|
||||
if (kind() == Code::LOAD_IC) {
|
||||
return LoadIC::pre_monomorphic_stub(isolate(), extra_ic_state());
|
||||
} else {
|
||||
DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
|
||||
return KeyedLoadIC::pre_monomorphic_stub(isolate());
|
||||
}
|
||||
DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
|
||||
return KeyedLoadIC::ChooseMegamorphicStub(isolate());
|
||||
}
|
||||
|
||||
|
||||
@ -1088,11 +987,7 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
|
||||
if (state() == UNINITIALIZED) {
|
||||
// This is the first time we execute this inline cache. Set the target to
|
||||
// the pre monomorphic stub to delay setting the monomorphic state.
|
||||
if (UseVector()) {
|
||||
ConfigureVectorState(PREMONOMORPHIC);
|
||||
} else {
|
||||
set_target(*pre_monomorphic_stub());
|
||||
}
|
||||
ConfigureVectorState(PREMONOMORPHIC);
|
||||
TRACE_IC("LoadIC", lookup->name());
|
||||
return;
|
||||
}
|
||||
@ -1360,13 +1255,10 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
|
||||
|
||||
|
||||
if (target_receiver_maps.length() == 0) {
|
||||
if (FLAG_vector_ics) {
|
||||
Handle<Code> handler =
|
||||
PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map);
|
||||
ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
|
||||
return null_handle;
|
||||
}
|
||||
return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map);
|
||||
Handle<Code> handler =
|
||||
PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map);
|
||||
ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
|
||||
return null_handle;
|
||||
}
|
||||
|
||||
// The first time a receiver is seen that is a transitioned version of the
|
||||
@ -1380,13 +1272,10 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
|
||||
IsMoreGeneralElementsKindTransition(
|
||||
target_receiver_maps.at(0)->elements_kind(),
|
||||
Handle<JSObject>::cast(receiver)->GetElementsKind())) {
|
||||
if (FLAG_vector_ics) {
|
||||
Handle<Code> handler =
|
||||
PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map);
|
||||
ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
|
||||
return null_handle;
|
||||
}
|
||||
return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map);
|
||||
Handle<Code> handler =
|
||||
PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(receiver_map);
|
||||
ConfigureVectorState(Handle<Name>::null(), receiver_map, handler);
|
||||
return null_handle;
|
||||
}
|
||||
|
||||
DCHECK(state() != GENERIC);
|
||||
@ -1407,16 +1296,11 @@ Handle<Code> KeyedLoadIC::LoadElementStub(Handle<HeapObject> receiver) {
|
||||
return megamorphic_stub();
|
||||
}
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
CodeHandleList handlers(target_receiver_maps.length());
|
||||
ElementHandlerCompiler compiler(isolate());
|
||||
compiler.CompileElementHandlers(&target_receiver_maps, &handlers);
|
||||
ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps,
|
||||
&handlers);
|
||||
return null_handle;
|
||||
}
|
||||
|
||||
return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps);
|
||||
CodeHandleList handlers(target_receiver_maps.length());
|
||||
ElementHandlerCompiler compiler(isolate());
|
||||
compiler.CompileElementHandlers(&target_receiver_maps, &handlers);
|
||||
ConfigureVectorState(Handle<Name>::null(), &target_receiver_maps, &handlers);
|
||||
return null_handle;
|
||||
}
|
||||
|
||||
|
||||
@ -2369,31 +2253,22 @@ RUNTIME_FUNCTION(LoadIC_Miss) {
|
||||
Handle<Name> key = args.at<Name>(1);
|
||||
Handle<Object> result;
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
DCHECK(args.length() == 4);
|
||||
Handle<Smi> slot = args.at<Smi>(2);
|
||||
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
|
||||
FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
|
||||
// A monomorphic or polymorphic KeyedLoadIC with a string key can call the
|
||||
// LoadIC miss handler if the handler misses. Since the vector Nexus is
|
||||
// set up outside the IC, handle that here.
|
||||
if (vector->GetKind(vector_slot) == Code::LOAD_IC) {
|
||||
LoadICNexus nexus(vector, vector_slot);
|
||||
LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
|
||||
ic.UpdateState(receiver, key);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
||||
ic.Load(receiver, key));
|
||||
} else {
|
||||
DCHECK(vector->GetKind(vector_slot) == Code::KEYED_LOAD_IC);
|
||||
KeyedLoadICNexus nexus(vector, vector_slot);
|
||||
KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
|
||||
ic.UpdateState(receiver, key);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
||||
ic.Load(receiver, key));
|
||||
}
|
||||
DCHECK(args.length() == 4);
|
||||
Handle<Smi> slot = args.at<Smi>(2);
|
||||
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
|
||||
FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
|
||||
// A monomorphic or polymorphic KeyedLoadIC with a string key can call the
|
||||
// LoadIC miss handler if the handler misses. Since the vector Nexus is
|
||||
// set up outside the IC, handle that here.
|
||||
if (vector->GetKind(vector_slot) == Code::LOAD_IC) {
|
||||
LoadICNexus nexus(vector, vector_slot);
|
||||
LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
|
||||
ic.UpdateState(receiver, key);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
|
||||
} else {
|
||||
DCHECK(args.length() == 2);
|
||||
LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
|
||||
DCHECK(vector->GetKind(vector_slot) == Code::KEYED_LOAD_IC);
|
||||
KeyedLoadICNexus nexus(vector, vector_slot);
|
||||
KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
|
||||
ic.UpdateState(receiver, key);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
|
||||
}
|
||||
@ -2409,22 +2284,14 @@ RUNTIME_FUNCTION(KeyedLoadIC_Miss) {
|
||||
Handle<Object> key = args.at<Object>(1);
|
||||
Handle<Object> result;
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
DCHECK(args.length() == 4);
|
||||
Handle<Smi> slot = args.at<Smi>(2);
|
||||
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
|
||||
FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
|
||||
KeyedLoadICNexus nexus(vector, vector_slot);
|
||||
KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
|
||||
ic.UpdateState(receiver, key);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
|
||||
} else {
|
||||
DCHECK(args.length() == 2);
|
||||
KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate);
|
||||
ic.UpdateState(receiver, key);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
|
||||
}
|
||||
|
||||
DCHECK(args.length() == 4);
|
||||
Handle<Smi> slot = args.at<Smi>(2);
|
||||
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
|
||||
FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
|
||||
KeyedLoadICNexus nexus(vector, vector_slot);
|
||||
KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
|
||||
ic.UpdateState(receiver, key);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
|
||||
return *result;
|
||||
}
|
||||
|
||||
@ -2436,21 +2303,14 @@ RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) {
|
||||
Handle<Object> key = args.at<Object>(1);
|
||||
Handle<Object> result;
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
DCHECK(args.length() == 4);
|
||||
Handle<Smi> slot = args.at<Smi>(2);
|
||||
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
|
||||
FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
|
||||
KeyedLoadICNexus nexus(vector, vector_slot);
|
||||
KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
|
||||
ic.UpdateState(receiver, key);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
|
||||
} else {
|
||||
DCHECK(args.length() == 2);
|
||||
KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate);
|
||||
ic.UpdateState(receiver, key);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
|
||||
}
|
||||
DCHECK(args.length() == 4);
|
||||
Handle<Smi> slot = args.at<Smi>(2);
|
||||
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
|
||||
FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
|
||||
KeyedLoadICNexus nexus(vector, vector_slot);
|
||||
KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
|
||||
ic.UpdateState(receiver, key);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
|
||||
|
||||
return *result;
|
||||
}
|
||||
@ -3018,31 +2878,22 @@ RUNTIME_FUNCTION(LoadIC_MissFromStubFailure) {
|
||||
Handle<Name> key = args.at<Name>(1);
|
||||
Handle<Object> result;
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
DCHECK(args.length() == 4);
|
||||
Handle<Smi> slot = args.at<Smi>(2);
|
||||
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
|
||||
FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
|
||||
// A monomorphic or polymorphic KeyedLoadIC with a string key can call the
|
||||
// LoadIC miss handler if the handler misses. Since the vector Nexus is
|
||||
// set up outside the IC, handle that here.
|
||||
if (vector->GetKind(vector_slot) == Code::LOAD_IC) {
|
||||
LoadICNexus nexus(vector, vector_slot);
|
||||
LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
|
||||
ic.UpdateState(receiver, key);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
||||
ic.Load(receiver, key));
|
||||
} else {
|
||||
DCHECK(vector->GetKind(vector_slot) == Code::KEYED_LOAD_IC);
|
||||
KeyedLoadICNexus nexus(vector, vector_slot);
|
||||
KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
|
||||
ic.UpdateState(receiver, key);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
||||
ic.Load(receiver, key));
|
||||
}
|
||||
DCHECK(args.length() == 4);
|
||||
Handle<Smi> slot = args.at<Smi>(2);
|
||||
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
|
||||
FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
|
||||
// A monomorphic or polymorphic KeyedLoadIC with a string key can call the
|
||||
// LoadIC miss handler if the handler misses. Since the vector Nexus is
|
||||
// set up outside the IC, handle that here.
|
||||
if (vector->GetKind(vector_slot) == Code::LOAD_IC) {
|
||||
LoadICNexus nexus(vector, vector_slot);
|
||||
LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
|
||||
ic.UpdateState(receiver, key);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
|
||||
} else {
|
||||
DCHECK(args.length() == 2);
|
||||
LoadIC ic(IC::EXTRA_CALL_FRAME, isolate);
|
||||
DCHECK(vector->GetKind(vector_slot) == Code::KEYED_LOAD_IC);
|
||||
KeyedLoadICNexus nexus(vector, vector_slot);
|
||||
KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
|
||||
ic.UpdateState(receiver, key);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
|
||||
}
|
||||
|
23
src/ic/ic.h
23
src/ic/ic.h
@ -114,8 +114,7 @@ class IC {
|
||||
}
|
||||
|
||||
static bool ICUseVector(Code::Kind kind) {
|
||||
return (FLAG_vector_ics &&
|
||||
(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC)) ||
|
||||
return kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC ||
|
||||
kind == Code::CALL_IC;
|
||||
}
|
||||
|
||||
@ -362,7 +361,7 @@ class LoadIC : public IC {
|
||||
|
||||
LoadIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL)
|
||||
: IC(depth, isolate, nexus) {
|
||||
DCHECK(!FLAG_vector_ics || nexus != NULL);
|
||||
DCHECK(nexus != NULL);
|
||||
DCHECK(IsLoadStub());
|
||||
}
|
||||
|
||||
@ -388,9 +387,6 @@ class LoadIC : public IC {
|
||||
|
||||
// Code generator routines.
|
||||
static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
|
||||
static void GeneratePreMonomorphic(MacroAssembler* masm) {
|
||||
GenerateMiss(masm);
|
||||
}
|
||||
static void GenerateMiss(MacroAssembler* masm);
|
||||
static void GenerateNormal(MacroAssembler* masm);
|
||||
static void GenerateRuntimeGetProperty(MacroAssembler* masm);
|
||||
@ -399,8 +395,6 @@ class LoadIC : public IC {
|
||||
ExtraICState extra_state);
|
||||
static Handle<Code> initialize_stub_in_optimized_code(
|
||||
Isolate* isolate, ExtraICState extra_state, State initialization_state);
|
||||
static Handle<Code> load_global(Isolate* isolate, Handle<GlobalObject> global,
|
||||
Handle<String> name);
|
||||
|
||||
MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
|
||||
Handle<Name> name);
|
||||
@ -430,10 +424,6 @@ class LoadIC : public IC {
|
||||
CacheHolderFlag cache_holder) override;
|
||||
|
||||
private:
|
||||
virtual Handle<Code> pre_monomorphic_stub() const;
|
||||
static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
|
||||
ExtraICState extra_state);
|
||||
|
||||
Handle<Code> SimpleFieldLoad(FieldIndex index);
|
||||
|
||||
static void Clear(Isolate* isolate, Address address, Code* target,
|
||||
@ -461,7 +451,7 @@ class KeyedLoadIC : public LoadIC {
|
||||
KeyedLoadIC(FrameDepth depth, Isolate* isolate,
|
||||
KeyedLoadICNexus* nexus = NULL)
|
||||
: LoadIC(depth, isolate, nexus) {
|
||||
DCHECK(!FLAG_vector_ics || nexus != NULL);
|
||||
DCHECK(nexus != NULL);
|
||||
DCHECK(target()->is_keyed_load_stub());
|
||||
}
|
||||
|
||||
@ -472,9 +462,6 @@ class KeyedLoadIC : public LoadIC {
|
||||
static void GenerateMiss(MacroAssembler* masm);
|
||||
static void GenerateRuntimeGetProperty(MacroAssembler* masm);
|
||||
static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
|
||||
static void GeneratePreMonomorphic(MacroAssembler* masm) {
|
||||
GenerateMiss(masm);
|
||||
}
|
||||
static void GenerateMegamorphic(MacroAssembler* masm);
|
||||
|
||||
// Bit mask to be tested against bit field for the cases when
|
||||
@ -488,16 +475,12 @@ class KeyedLoadIC : public LoadIC {
|
||||
static Handle<Code> initialize_stub_in_optimized_code(
|
||||
Isolate* isolate, State initialization_state);
|
||||
static Handle<Code> ChooseMegamorphicStub(Isolate* isolate);
|
||||
static Handle<Code> pre_monomorphic_stub(Isolate* isolate);
|
||||
|
||||
static void Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus);
|
||||
|
||||
protected:
|
||||
// receiver is HeapObject because it could be a String or a JSObject
|
||||
Handle<Code> LoadElementStub(Handle<HeapObject> receiver);
|
||||
virtual Handle<Code> pre_monomorphic_stub() const {
|
||||
return pre_monomorphic_stub(isolate());
|
||||
}
|
||||
|
||||
private:
|
||||
static void Clear(Isolate* isolate, Address address, Code* target,
|
||||
|
@ -296,14 +296,10 @@ static const Register LoadIC_TempRegister() { return a3; }
|
||||
static void LoadIC_PushArgs(MacroAssembler* masm) {
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
if (FLAG_vector_ics) {
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
|
||||
__ Push(receiver, name, slot, vector);
|
||||
} else {
|
||||
__ Push(receiver, name);
|
||||
}
|
||||
__ Push(receiver, name, slot, vector);
|
||||
}
|
||||
|
||||
|
||||
@ -311,8 +307,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// The return address is in ra.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!AreAliased(t0, t1, VectorLoadICDescriptor::SlotRegister(),
|
||||
DCHECK(!AreAliased(t0, t1, VectorLoadICDescriptor::SlotRegister(),
|
||||
VectorLoadICDescriptor::VectorRegister()));
|
||||
__ IncrementCounter(isolate->counters()->load_miss(), 1, t0, t1);
|
||||
|
||||
@ -320,7 +315,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
|
||||
int arg_count = FLAG_vector_ics ? 4 : 2;
|
||||
int arg_count = 4;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
}
|
||||
|
||||
@ -450,8 +445,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// The return address is in ra.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!AreAliased(t0, t1, VectorLoadICDescriptor::SlotRegister(),
|
||||
DCHECK(!AreAliased(t0, t1, VectorLoadICDescriptor::SlotRegister(),
|
||||
VectorLoadICDescriptor::VectorRegister()));
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, t0, t1);
|
||||
|
||||
@ -461,7 +455,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate);
|
||||
|
||||
int arg_count = FLAG_vector_ics ? 4 : 2;
|
||||
int arg_count = 4;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
}
|
||||
|
||||
@ -536,19 +530,16 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
__ LoadRoot(at, Heap::kHashTableMapRootIndex);
|
||||
__ Branch(&probe_dictionary, eq, t0, Operand(at));
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
// When vector ics are in use, the handlers in the stub cache expect a
|
||||
// vector and slot. Since we won't change the IC from any downstream
|
||||
// misses, a dummy vector can be used.
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(!AreAliased(vector, slot, t0, t1, t2, t5));
|
||||
Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast(
|
||||
masm->isolate()->factory()->keyed_load_dummy_vector());
|
||||
int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0));
|
||||
__ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex);
|
||||
__ li(slot, Operand(Smi::FromInt(int_slot)));
|
||||
}
|
||||
// The handlers in the stub cache expect a vector and slot. Since we won't
|
||||
// change the IC from any downstream misses, a dummy vector can be used.
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(!AreAliased(vector, slot, t0, t1, t2, t5));
|
||||
Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast(
|
||||
masm->isolate()->factory()->keyed_load_dummy_vector());
|
||||
int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0));
|
||||
__ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex);
|
||||
__ li(slot, Operand(Smi::FromInt(int_slot)));
|
||||
|
||||
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
|
||||
Code::ComputeHandlerFlags(Code::LOAD_IC));
|
||||
|
@ -294,14 +294,10 @@ static const Register LoadIC_TempRegister() { return a3; }
|
||||
static void LoadIC_PushArgs(MacroAssembler* masm) {
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
if (FLAG_vector_ics) {
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
|
||||
__ Push(receiver, name, slot, vector);
|
||||
} else {
|
||||
__ Push(receiver, name);
|
||||
}
|
||||
__ Push(receiver, name, slot, vector);
|
||||
}
|
||||
|
||||
|
||||
@ -309,8 +305,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// The return address is on the stack.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!AreAliased(a4, a5, VectorLoadICDescriptor::SlotRegister(),
|
||||
DCHECK(!AreAliased(a4, a5, VectorLoadICDescriptor::SlotRegister(),
|
||||
VectorLoadICDescriptor::VectorRegister()));
|
||||
__ IncrementCounter(isolate->counters()->load_miss(), 1, a4, a5);
|
||||
|
||||
@ -318,7 +313,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
|
||||
int arg_count = FLAG_vector_ics ? 4 : 2;
|
||||
int arg_count = 4;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
}
|
||||
|
||||
@ -448,8 +443,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// The return address is in ra.
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!AreAliased(a4, a5, VectorLoadICDescriptor::SlotRegister(),
|
||||
DCHECK(!AreAliased(a4, a5, VectorLoadICDescriptor::SlotRegister(),
|
||||
VectorLoadICDescriptor::VectorRegister()));
|
||||
__ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, a4, a5);
|
||||
|
||||
@ -459,7 +453,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate);
|
||||
|
||||
int arg_count = FLAG_vector_ics ? 4 : 2;
|
||||
int arg_count = 4;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
}
|
||||
|
||||
@ -534,19 +528,16 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
__ LoadRoot(at, Heap::kHashTableMapRootIndex);
|
||||
__ Branch(&probe_dictionary, eq, a4, Operand(at));
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
// When vector ics are in use, the handlers in the stub cache expect a
|
||||
// vector and slot. Since we won't change the IC from any downstream
|
||||
// misses, a dummy vector can be used.
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(!AreAliased(vector, slot, a4, a5, a6, t1));
|
||||
Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast(
|
||||
masm->isolate()->factory()->keyed_load_dummy_vector());
|
||||
int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0));
|
||||
__ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex);
|
||||
__ li(slot, Operand(Smi::FromInt(int_slot)));
|
||||
}
|
||||
// The handlers in the stub cache expect a vector and slot. Since we won't
|
||||
// change the IC from any downstream misses, a dummy vector can be used.
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(!AreAliased(vector, slot, a4, a5, a6, t1));
|
||||
Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast(
|
||||
masm->isolate()->factory()->keyed_load_dummy_vector());
|
||||
int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0));
|
||||
__ LoadRoot(vector, Heap::kKeyedLoadDummyVectorRootIndex);
|
||||
__ li(slot, Operand(Smi::FromInt(int_slot)));
|
||||
|
||||
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
|
||||
Code::ComputeHandlerFlags(Code::LOAD_IC));
|
||||
|
@ -333,19 +333,16 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
__ j(equal, &probe_dictionary);
|
||||
|
||||
Register megamorphic_scratch = rdi;
|
||||
if (FLAG_vector_ics) {
|
||||
// When vector ics are in use, the handlers in the stub cache expect a
|
||||
// vector and slot. Since we won't change the IC from any downstream
|
||||
// misses, a dummy vector can be used.
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(!AreAliased(megamorphic_scratch, vector, slot));
|
||||
Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast(
|
||||
masm->isolate()->factory()->keyed_load_dummy_vector());
|
||||
int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0));
|
||||
__ Move(vector, dummy_vector);
|
||||
__ Move(slot, Smi::FromInt(int_slot));
|
||||
}
|
||||
// The handlers in the stub cache expect a vector and slot. Since we won't
|
||||
// change the IC from any downstream misses, a dummy vector can be used.
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(!AreAliased(megamorphic_scratch, vector, slot));
|
||||
Handle<TypeFeedbackVector> dummy_vector = Handle<TypeFeedbackVector>::cast(
|
||||
masm->isolate()->factory()->keyed_load_dummy_vector());
|
||||
int int_slot = dummy_vector->GetIndex(FeedbackVectorICSlot(0));
|
||||
__ Move(vector, dummy_vector);
|
||||
__ Move(slot, Smi::FromInt(int_slot));
|
||||
|
||||
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
|
||||
Code::ComputeHandlerFlags(Code::LOAD_IC));
|
||||
@ -737,26 +734,17 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
||||
static void LoadIC_PushArgs(MacroAssembler* masm) {
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
if (FLAG_vector_ics) {
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
DCHECK(!rdi.is(receiver) && !rdi.is(name) && !rdi.is(slot) &&
|
||||
!rdi.is(vector));
|
||||
Register slot = VectorLoadICDescriptor::SlotRegister();
|
||||
Register vector = VectorLoadICDescriptor::VectorRegister();
|
||||
DCHECK(!rdi.is(receiver) && !rdi.is(name) && !rdi.is(slot) &&
|
||||
!rdi.is(vector));
|
||||
|
||||
__ PopReturnAddressTo(rdi);
|
||||
__ Push(receiver);
|
||||
__ Push(name);
|
||||
__ Push(slot);
|
||||
__ Push(vector);
|
||||
__ PushReturnAddressFrom(rdi);
|
||||
} else {
|
||||
DCHECK(!rbx.is(receiver) && !rbx.is(name));
|
||||
|
||||
__ PopReturnAddressTo(rbx);
|
||||
__ Push(receiver);
|
||||
__ Push(name);
|
||||
__ PushReturnAddressFrom(rbx);
|
||||
}
|
||||
__ PopReturnAddressTo(rdi);
|
||||
__ Push(receiver);
|
||||
__ Push(name);
|
||||
__ Push(slot);
|
||||
__ Push(vector);
|
||||
__ PushReturnAddressFrom(rdi);
|
||||
}
|
||||
|
||||
|
||||
@ -771,7 +759,7 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate());
|
||||
int arg_count = FLAG_vector_ics ? 4 : 2;
|
||||
int arg_count = 4;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
}
|
||||
|
||||
@ -802,7 +790,7 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
||||
// Perform tail call to the entry.
|
||||
ExternalReference ref =
|
||||
ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate());
|
||||
int arg_count = FLAG_vector_ics ? 4 : 2;
|
||||
int arg_count = 4;
|
||||
__ TailCallExternalReference(ref, arg_count, 1);
|
||||
}
|
||||
|
||||
|
@ -1386,8 +1386,7 @@ void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
|
||||
Register scratch = t1;
|
||||
Register result = v0;
|
||||
DCHECK(!scratch.is(receiver) && !scratch.is(index));
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!scratch.is(VectorLoadICDescriptor::VectorRegister()));
|
||||
DCHECK(!scratch.is(VectorLoadICDescriptor::VectorRegister()));
|
||||
|
||||
StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
|
||||
&miss, // When not a string.
|
||||
@ -1611,8 +1610,7 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
// Ensure that the vector and slot registers won't be clobbered before
|
||||
// calling the miss handler.
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!AreAliased(t0, t1, VectorLoadICDescriptor::VectorRegister(),
|
||||
DCHECK(!AreAliased(t0, t1, VectorLoadICDescriptor::VectorRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister()));
|
||||
|
||||
NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, t0,
|
||||
@ -3092,7 +3090,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
DONT_DO_SMI_CHECK);
|
||||
call_helper.BeforeCall(masm);
|
||||
// Consumed by runtime conversion function:
|
||||
if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
|
||||
if (embed_mode == PART_OF_IC_HANDLER) {
|
||||
__ Push(VectorLoadICDescriptor::VectorRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister(), object_, index_);
|
||||
} else {
|
||||
@ -3109,7 +3107,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
// Save the conversion result before the pop instructions below
|
||||
// have a chance to overwrite it.
|
||||
__ Move(index_, v0);
|
||||
if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
|
||||
if (embed_mode == PART_OF_IC_HANDLER) {
|
||||
__ Pop(VectorLoadICDescriptor::VectorRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister(), object_);
|
||||
} else {
|
||||
|
@ -153,10 +153,8 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
|
||||
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
RegList regs = receiver.bit() | name.bit();
|
||||
if (FLAG_vector_ics) {
|
||||
regs |= VectorLoadICTrampolineDescriptor::SlotRegister().bit();
|
||||
}
|
||||
RegList regs = receiver.bit() | name.bit() |
|
||||
VectorLoadICTrampolineDescriptor::SlotRegister().bit();
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0);
|
||||
}
|
||||
|
||||
|
@ -1321,13 +1321,9 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
|
||||
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
|
||||
__ li(LoadDescriptor::NameRegister(), home_object_symbol);
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
|
||||
Label done;
|
||||
__ Branch(&done, ne, v0, Operand(isolate()->factory()->undefined_value()));
|
||||
@ -1396,10 +1392,8 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
||||
|
||||
__ lw(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ li(LoadDescriptor::NameRegister(), Operand(proxy->var()->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
|
||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? NOT_CONTEXTUAL
|
||||
@ -1486,10 +1480,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
__ lw(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ li(LoadDescriptor::NameRegister(), Operand(var->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
CallGlobalLoadIC(var->name());
|
||||
context()->Plug(v0);
|
||||
break;
|
||||
@ -2186,10 +2178,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ bind(&l_call);
|
||||
__ lw(load_receiver, MemOperand(sp, kPointerSize));
|
||||
__ lw(load_name, MemOperand(sp, 2 * kPointerSize));
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ mov(a0, v0);
|
||||
@ -2206,10 +2196,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
__ push(load_receiver); // save result
|
||||
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->DoneFeedbackSlot())));
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->DoneFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL); // v0=result.done
|
||||
__ mov(a0, v0);
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
@ -2219,10 +2207,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// result.value
|
||||
__ pop(load_receiver); // result
|
||||
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->ValueFeedbackSlot())));
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->ValueFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL); // v0=result.value
|
||||
context()->DropAndPlug(2, v0); // drop iter and g
|
||||
break;
|
||||
@ -2363,13 +2349,9 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
DCHECK(!prop->IsSuperAccess());
|
||||
|
||||
__ li(LoadDescriptor::NameRegister(), Operand(key->value()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -2388,13 +2370,9 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallIC(ic);
|
||||
} else {
|
||||
CallIC(ic, prop->PropertyFeedbackId());
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallIC(ic);
|
||||
}
|
||||
|
||||
|
||||
@ -4634,13 +4612,9 @@ void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
|
||||
|
||||
// Load the function from the receiver.
|
||||
__ li(LoadDescriptor::NameRegister(), Operand(expr->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->CallRuntimeFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->CallRuntimeFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -5075,10 +5049,8 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
__ lw(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ li(LoadDescriptor::NameRegister(), Operand(proxy->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
|
@ -2907,7 +2907,6 @@ void LCodeGen::DoReturn(LReturn* instr) {
|
||||
|
||||
template <class T>
|
||||
void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
|
||||
DCHECK(FLAG_vector_ics);
|
||||
Register vector_register = ToRegister(instr->temp_vector());
|
||||
Register slot_register = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister()));
|
||||
@ -2930,9 +2929,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
DCHECK(ToRegister(instr->result()).is(v0));
|
||||
|
||||
__ li(LoadDescriptor::NameRegister(), Operand(instr->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
}
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
|
||||
PREMONOMORPHIC).code();
|
||||
@ -3033,9 +3030,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
|
||||
// Name is always in a2.
|
||||
__ li(LoadDescriptor::NameRegister(), Operand(instr->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
}
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL,
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
@ -3952,30 +3947,6 @@ 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 = t0;
|
||||
Register extra = t1;
|
||||
Register extra2 = t2;
|
||||
Register extra3 = t5;
|
||||
|
||||
// The probe will tail call to a handler if found.
|
||||
isolate()->stub_cache()->GenerateProbe(
|
||||
masm(), Code::LOAD_IC, instr->hydrogen()->flags(), false, receiver, name,
|
||||
scratch, extra, extra2, extra3);
|
||||
|
||||
// Tail call to miss if we ended up here.
|
||||
LoadIC::GenerateMiss(masm());
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
|
||||
DCHECK(ToRegister(instr->result()).is(v0));
|
||||
|
||||
|
@ -1110,20 +1110,6 @@ 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,7 +152,6 @@ class LCodeGen;
|
||||
V(StringCompareAndBranch) \
|
||||
V(SubI) \
|
||||
V(TaggedToI) \
|
||||
V(TailCallThroughMegamorphicCache) \
|
||||
V(ThisFunction) \
|
||||
V(ToFastProperties) \
|
||||
V(TransitionElementsKind) \
|
||||
@ -472,26 +471,6 @@ class LCallStub final : public LTemplateInstruction<1, 1, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LTailCallThroughMegamorphicCache final
|
||||
: public LTemplateInstruction<0, 3, 0> {
|
||||
public:
|
||||
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:
|
||||
bool HasInterestingComment(LCodeGen* gen) const override { return false; }
|
||||
|
@ -1386,8 +1386,7 @@ void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
|
||||
Register scratch = a5;
|
||||
Register result = v0;
|
||||
DCHECK(!scratch.is(receiver) && !scratch.is(index));
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!scratch.is(VectorLoadICDescriptor::VectorRegister()));
|
||||
DCHECK(!scratch.is(VectorLoadICDescriptor::VectorRegister()));
|
||||
|
||||
StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
|
||||
&miss, // When not a string.
|
||||
@ -1611,8 +1610,7 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
// Ensure that the vector and slot registers won't be clobbered before
|
||||
// calling the miss handler.
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!AreAliased(a4, a5, VectorLoadICDescriptor::VectorRegister(),
|
||||
DCHECK(!AreAliased(a4, a5, VectorLoadICDescriptor::VectorRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister()));
|
||||
|
||||
NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, a4,
|
||||
@ -3131,7 +3129,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
DONT_DO_SMI_CHECK);
|
||||
call_helper.BeforeCall(masm);
|
||||
// Consumed by runtime conversion function:
|
||||
if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
|
||||
if (embed_mode == PART_OF_IC_HANDLER) {
|
||||
__ Push(VectorLoadICDescriptor::VectorRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister(), object_, index_);
|
||||
} else {
|
||||
@ -3149,7 +3147,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
// have a chance to overwrite it.
|
||||
|
||||
__ Move(index_, v0);
|
||||
if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
|
||||
if (embed_mode == PART_OF_IC_HANDLER) {
|
||||
__ Pop(VectorLoadICDescriptor::VectorRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister(), object_);
|
||||
} else {
|
||||
|
@ -156,10 +156,8 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
|
||||
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
RegList regs = receiver.bit() | name.bit();
|
||||
if (FLAG_vector_ics) {
|
||||
regs |= VectorLoadICTrampolineDescriptor::SlotRegister().bit();
|
||||
}
|
||||
RegList regs = receiver.bit() | name.bit() |
|
||||
VectorLoadICTrampolineDescriptor::SlotRegister().bit();
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0);
|
||||
}
|
||||
|
||||
|
@ -1318,13 +1318,9 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
|
||||
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
|
||||
__ li(LoadDescriptor::NameRegister(), home_object_symbol);
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->HomeObjectFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
|
||||
Label done;
|
||||
__ Branch(&done, ne, v0, Operand(isolate()->factory()->undefined_value()));
|
||||
@ -1393,10 +1389,8 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
||||
|
||||
__ ld(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ li(LoadDescriptor::NameRegister(), Operand(proxy->var()->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
|
||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? NOT_CONTEXTUAL
|
||||
@ -1485,10 +1479,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
// object (receiver) in a0.
|
||||
__ ld(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ li(LoadDescriptor::NameRegister(), Operand(var->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
CallGlobalLoadIC(var->name());
|
||||
context()->Plug(v0);
|
||||
break;
|
||||
@ -2183,10 +2175,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ bind(&l_call);
|
||||
__ ld(load_receiver, MemOperand(sp, kPointerSize));
|
||||
__ ld(load_name, MemOperand(sp, 2 * kPointerSize));
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->KeyedLoadFeedbackSlot())));
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ mov(a0, v0);
|
||||
@ -2203,10 +2193,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
|
||||
__ push(load_receiver); // save result
|
||||
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->DoneFeedbackSlot())));
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->DoneFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL); // v0=result.done
|
||||
__ mov(a0, v0);
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
@ -2216,10 +2204,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// result.value
|
||||
__ pop(load_receiver); // result
|
||||
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->ValueFeedbackSlot())));
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->ValueFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL); // v0=result.value
|
||||
context()->DropAndPlug(2, v0); // drop iter and g
|
||||
break;
|
||||
@ -2362,13 +2348,9 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
DCHECK(!prop->IsSuperAccess());
|
||||
|
||||
__ li(LoadDescriptor::NameRegister(), Operand(key->value()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -2388,13 +2370,9 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
// Call keyed load IC. It has register arguments receiver and key.
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallIC(ic);
|
||||
} else {
|
||||
CallIC(ic, prop->PropertyFeedbackId());
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
CallIC(ic);
|
||||
}
|
||||
|
||||
|
||||
@ -4638,13 +4616,9 @@ void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
|
||||
|
||||
// Load the function from the receiver.
|
||||
__ li(LoadDescriptor::NameRegister(), Operand(expr->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->CallRuntimeFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(expr->CallRuntimeFeedbackSlot())));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -5078,10 +5052,8 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
__ ld(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ li(LoadDescriptor::NameRegister(), Operand(proxy->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
}
|
||||
__ li(VectorLoadICDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
|
@ -2906,7 +2906,6 @@ void LCodeGen::DoReturn(LReturn* instr) {
|
||||
|
||||
template <class T>
|
||||
void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
|
||||
DCHECK(FLAG_vector_ics);
|
||||
Register vector_register = ToRegister(instr->temp_vector());
|
||||
Register slot_register = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister()));
|
||||
@ -2929,9 +2928,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
DCHECK(ToRegister(instr->result()).is(v0));
|
||||
|
||||
__ li(LoadDescriptor::NameRegister(), Operand(instr->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
}
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
|
||||
PREMONOMORPHIC).code();
|
||||
@ -3047,9 +3044,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
|
||||
// Name is always in a2.
|
||||
__ li(LoadDescriptor::NameRegister(), Operand(instr->name()));
|
||||
if (FLAG_vector_ics) {
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
}
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL,
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
@ -4015,30 +4010,6 @@ 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 = a4;
|
||||
Register extra = a5;
|
||||
Register extra2 = a6;
|
||||
Register extra3 = t1;
|
||||
|
||||
// The probe will tail call to a handler if found.
|
||||
isolate()->stub_cache()->GenerateProbe(
|
||||
masm(), Code::LOAD_IC, instr->hydrogen()->flags(), false, receiver, name,
|
||||
scratch, extra, extra2, extra3);
|
||||
|
||||
// Tail call to miss if we ended up here.
|
||||
LoadIC::GenerateMiss(masm());
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
|
||||
DCHECK(ToRegister(instr->result()).is(v0));
|
||||
|
||||
|
@ -1110,20 +1110,6 @@ 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,7 +151,6 @@ class LCodeGen;
|
||||
V(StringCompareAndBranch) \
|
||||
V(SubI) \
|
||||
V(TaggedToI) \
|
||||
V(TailCallThroughMegamorphicCache) \
|
||||
V(ThisFunction) \
|
||||
V(ToFastProperties) \
|
||||
V(TransitionElementsKind) \
|
||||
@ -471,26 +470,6 @@ class LCallStub final : public LTemplateInstruction<1, 1, 0> {
|
||||
};
|
||||
|
||||
|
||||
class LTailCallThroughMegamorphicCache final
|
||||
: public LTemplateInstruction<0, 3, 0> {
|
||||
public:
|
||||
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:
|
||||
bool HasInterestingComment(LCodeGen* gen) const override { return false; }
|
||||
|
@ -11,7 +11,7 @@ namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
int TypeFeedbackVector::ic_metadata_length() const {
|
||||
return FLAG_vector_ics ? VectorICComputer::word_count(ICSlots()) : 0;
|
||||
return VectorICComputer::word_count(ICSlots());
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,11 +50,6 @@ Code::Kind TypeFeedbackVector::FromVectorICKind(VectorICKind kind) {
|
||||
|
||||
|
||||
Code::Kind TypeFeedbackVector::GetKind(FeedbackVectorICSlot slot) const {
|
||||
if (!FLAG_vector_ics) {
|
||||
// We only have CALL_ICs
|
||||
return Code::CALL_IC;
|
||||
}
|
||||
|
||||
int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
|
||||
int data = Smi::cast(get(index))->value();
|
||||
VectorICKind b = VectorICComputer::decode(data, slot.ToInt());
|
||||
@ -63,11 +58,6 @@ Code::Kind TypeFeedbackVector::GetKind(FeedbackVectorICSlot slot) const {
|
||||
|
||||
|
||||
void TypeFeedbackVector::SetKind(FeedbackVectorICSlot slot, Code::Kind kind) {
|
||||
if (!FLAG_vector_ics) {
|
||||
// Nothing to do if we only have CALL_ICs
|
||||
return;
|
||||
}
|
||||
|
||||
VectorICKind b = FromCodeKind(kind);
|
||||
int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
|
||||
int data = Smi::cast(get(index))->value();
|
||||
@ -88,8 +78,7 @@ Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(Isolate* isolate,
|
||||
const Spec* spec) {
|
||||
const int slot_count = spec->slots();
|
||||
const int ic_slot_count = spec->ic_slots();
|
||||
const int index_count =
|
||||
FLAG_vector_ics ? VectorICComputer::word_count(ic_slot_count) : 0;
|
||||
const int index_count = VectorICComputer::word_count(ic_slot_count);
|
||||
const int length = slot_count + (ic_slot_count * elements_per_ic_slot()) +
|
||||
index_count + kReservedIndexCount;
|
||||
if (length == kReservedIndexCount) {
|
||||
@ -119,10 +108,8 @@ Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(Isolate* isolate,
|
||||
}
|
||||
|
||||
Handle<TypeFeedbackVector> vector = Handle<TypeFeedbackVector>::cast(array);
|
||||
if (FLAG_vector_ics) {
|
||||
for (int i = 0; i < ic_slot_count; i++) {
|
||||
vector->SetKind(FeedbackVectorICSlot(i), spec->GetKind(i));
|
||||
}
|
||||
for (int i = 0; i < ic_slot_count; i++) {
|
||||
vector->SetKind(FeedbackVectorICSlot(i), spec->GetKind(i));
|
||||
}
|
||||
return vector;
|
||||
}
|
||||
@ -140,8 +127,6 @@ Handle<TypeFeedbackVector> TypeFeedbackVector::Copy(
|
||||
|
||||
bool TypeFeedbackVector::SpecDiffersFrom(
|
||||
const ZoneFeedbackVectorSpec* other_spec) const {
|
||||
if (!FLAG_vector_ics) return false;
|
||||
|
||||
if (other_spec->slots() != Slots() || other_spec->ic_slots() != ICSlots()) {
|
||||
return true;
|
||||
}
|
||||
@ -312,8 +297,7 @@ InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
|
||||
InlineCacheState CallICNexus::StateFromFeedback() const {
|
||||
Isolate* isolate = GetIsolate();
|
||||
Object* feedback = GetFeedback();
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
GetFeedbackExtra() == *vector()->UninitializedSentinel(isolate) ||
|
||||
DCHECK(GetFeedbackExtra() == *vector()->UninitializedSentinel(isolate) ||
|
||||
GetFeedbackExtra() == Smi::FromInt(kHasReturnedMinusZeroSentinel));
|
||||
|
||||
if (feedback == *vector()->MegamorphicSentinel(isolate)) {
|
||||
|
@ -29,7 +29,7 @@ class FeedbackVectorSpec {
|
||||
int ic_slots() const { return has_ic_slot_ ? 1 : 0; }
|
||||
|
||||
Code::Kind GetKind(int ic_slot) const {
|
||||
DCHECK(FLAG_vector_ics && has_ic_slot_ && ic_slot == 0);
|
||||
DCHECK(has_ic_slot_ && ic_slot == 0);
|
||||
return ic_kind_;
|
||||
}
|
||||
|
||||
@ -46,9 +46,7 @@ class ZoneFeedbackVectorSpec {
|
||||
: slots_(0), ic_slots_(0), ic_slot_kinds_(zone) {}
|
||||
|
||||
ZoneFeedbackVectorSpec(Zone* zone, int slots, int ic_slots)
|
||||
: slots_(slots),
|
||||
ic_slots_(ic_slots),
|
||||
ic_slot_kinds_(FLAG_vector_ics ? ic_slots : 0, zone) {}
|
||||
: slots_(slots), ic_slots_(ic_slots), ic_slot_kinds_(ic_slots, zone) {}
|
||||
|
||||
int slots() const { return slots_; }
|
||||
void increase_slots(int count) { slots_ += count; }
|
||||
@ -56,16 +54,14 @@ class ZoneFeedbackVectorSpec {
|
||||
int ic_slots() const { return ic_slots_; }
|
||||
void increase_ic_slots(int count) {
|
||||
ic_slots_ += count;
|
||||
if (FLAG_vector_ics) ic_slot_kinds_.resize(ic_slots_);
|
||||
ic_slot_kinds_.resize(ic_slots_);
|
||||
}
|
||||
|
||||
void SetKind(int ic_slot, Code::Kind kind) {
|
||||
DCHECK(FLAG_vector_ics);
|
||||
ic_slot_kinds_[ic_slot] = kind;
|
||||
}
|
||||
|
||||
Code::Kind GetKind(int ic_slot) const {
|
||||
DCHECK(FLAG_vector_ics);
|
||||
return static_cast<Code::Kind>(ic_slot_kinds_.at(ic_slot));
|
||||
}
|
||||
|
||||
@ -100,7 +96,7 @@ class TypeFeedbackVector : public FixedArray {
|
||||
static const int kWithTypesIndex = 1;
|
||||
static const int kGenericCountIndex = 2;
|
||||
|
||||
static int elements_per_ic_slot() { return FLAG_vector_ics ? 2 : 1; }
|
||||
static int elements_per_ic_slot() { return 2; }
|
||||
|
||||
int first_ic_slot_index() const {
|
||||
DCHECK(length() >= kReservedIndexCount);
|
||||
|
@ -492,35 +492,20 @@ void AstTyper::VisitThrow(Throw* expr) {
|
||||
void AstTyper::VisitProperty(Property* expr) {
|
||||
// Collect type feedback.
|
||||
FeedbackVectorICSlot slot(FeedbackVectorICSlot::Invalid());
|
||||
TypeFeedbackId id(TypeFeedbackId::None());
|
||||
if (FLAG_vector_ics) {
|
||||
slot = expr->PropertyFeedbackSlot();
|
||||
expr->set_inline_cache_state(oracle()->LoadInlineCacheState(slot));
|
||||
} else {
|
||||
id = expr->PropertyFeedbackId();
|
||||
expr->set_inline_cache_state(oracle()->LoadInlineCacheState(id));
|
||||
}
|
||||
slot = expr->PropertyFeedbackSlot();
|
||||
expr->set_inline_cache_state(oracle()->LoadInlineCacheState(slot));
|
||||
|
||||
if (!expr->IsUninitialized()) {
|
||||
if (expr->key()->IsPropertyName()) {
|
||||
Literal* lit_key = expr->key()->AsLiteral();
|
||||
DCHECK(lit_key != NULL && lit_key->value()->IsString());
|
||||
Handle<String> name = Handle<String>::cast(lit_key->value());
|
||||
if (FLAG_vector_ics) {
|
||||
oracle()->PropertyReceiverTypes(slot, name, expr->GetReceiverTypes());
|
||||
} else {
|
||||
oracle()->PropertyReceiverTypes(id, name, expr->GetReceiverTypes());
|
||||
}
|
||||
oracle()->PropertyReceiverTypes(slot, name, expr->GetReceiverTypes());
|
||||
} else {
|
||||
bool is_string;
|
||||
IcCheckType key_type;
|
||||
if (FLAG_vector_ics) {
|
||||
oracle()->KeyedPropertyReceiverTypes(slot, expr->GetReceiverTypes(),
|
||||
&is_string, &key_type);
|
||||
} else {
|
||||
oracle()->KeyedPropertyReceiverTypes(id, expr->GetReceiverTypes(),
|
||||
&is_string, &key_type);
|
||||
}
|
||||
oracle()->KeyedPropertyReceiverTypes(slot, expr->GetReceiverTypes(),
|
||||
&is_string, &key_type);
|
||||
expr->set_is_string_access(is_string);
|
||||
expr->set_key_type(key_type);
|
||||
}
|
||||
|
@ -527,8 +527,7 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
// Ensure that the vector and slot registers won't be clobbered before
|
||||
// calling the miss handler.
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
!AreAliased(r8, r9, VectorLoadICDescriptor::VectorRegister(),
|
||||
DCHECK(!AreAliased(r8, r9, VectorLoadICDescriptor::VectorRegister(),
|
||||
VectorLoadICDescriptor::SlotRegister()));
|
||||
|
||||
NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r8,
|
||||
@ -913,9 +912,8 @@ void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
|
||||
Register scratch = rdi;
|
||||
Register result = rax;
|
||||
DCHECK(!scratch.is(receiver) && !scratch.is(index));
|
||||
DCHECK(!FLAG_vector_ics ||
|
||||
(!scratch.is(VectorLoadICDescriptor::VectorRegister()) &&
|
||||
result.is(VectorLoadICDescriptor::SlotRegister())));
|
||||
DCHECK(!scratch.is(VectorLoadICDescriptor::VectorRegister()) &&
|
||||
result.is(VectorLoadICDescriptor::SlotRegister()));
|
||||
|
||||
// StringCharAtGenerator doesn't use the result register until it's passed
|
||||
// the different miss possibilities. If it did, we would have a conflict
|
||||
@ -2941,7 +2939,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
index_not_number_,
|
||||
DONT_DO_SMI_CHECK);
|
||||
call_helper.BeforeCall(masm);
|
||||
if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
|
||||
if (embed_mode == PART_OF_IC_HANDLER) {
|
||||
__ Push(VectorLoadICDescriptor::VectorRegister());
|
||||
__ Push(VectorLoadICDescriptor::SlotRegister());
|
||||
}
|
||||
@ -2960,7 +2958,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
__ movp(index_, rax);
|
||||
}
|
||||
__ Pop(object_);
|
||||
if (FLAG_vector_ics && embed_mode == PART_OF_IC_HANDLER) {
|
||||
if (embed_mode == PART_OF_IC_HANDLER) {
|
||||
__ Pop(VectorLoadICDescriptor::SlotRegister());
|
||||
__ Pop(VectorLoadICDescriptor::VectorRegister());
|
||||
}
|
||||
|
@ -163,10 +163,8 @@ void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for IC load call (from ic-x64.cc).
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
RegList regs = receiver.bit() | name.bit();
|
||||
if (FLAG_vector_ics) {
|
||||
regs |= VectorLoadICTrampolineDescriptor::SlotRegister().bit();
|
||||
}
|
||||
RegList regs = receiver.bit() | name.bit() |
|
||||
VectorLoadICTrampolineDescriptor::SlotRegister().bit();
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0, false);
|
||||
}
|
||||
|
||||
|
@ -1293,14 +1293,9 @@ void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
|
||||
Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
|
||||
__ Move(LoadDescriptor::NameRegister(), home_object_symbol);
|
||||
|
||||
if (FLAG_vector_ics) {
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->HomeObjectFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
|
||||
}
|
||||
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->HomeObjectFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
|
||||
__ Cmp(rax, isolate()->factory()->undefined_value());
|
||||
Label done;
|
||||
@ -1376,10 +1371,8 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
||||
// load IC call.
|
||||
__ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
__ Move(LoadDescriptor::NameRegister(), proxy->var()->name());
|
||||
if (FLAG_vector_ics) {
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
||||
}
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
||||
|
||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
||||
? NOT_CONTEXTUAL
|
||||
@ -1463,10 +1456,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
__ Move(LoadDescriptor::NameRegister(), var->name());
|
||||
__ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
if (FLAG_vector_ics) {
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
||||
}
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
||||
CallGlobalLoadIC(var->name());
|
||||
context()->Plug(rax);
|
||||
break;
|
||||
@ -2158,10 +2149,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// result = receiver[f](arg);
|
||||
__ bind(&l_call);
|
||||
__ movp(load_receiver, Operand(rsp, kPointerSize));
|
||||
if (FLAG_vector_ics) {
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->KeyedLoadFeedbackSlot()));
|
||||
}
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->KeyedLoadFeedbackSlot()));
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
CallIC(ic, TypeFeedbackId::None());
|
||||
__ movp(rdi, rax);
|
||||
@ -2177,10 +2166,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
__ Move(load_receiver, rax);
|
||||
__ Push(load_receiver); // save result
|
||||
__ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
|
||||
if (FLAG_vector_ics) {
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->DoneFeedbackSlot()));
|
||||
}
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->DoneFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL); // rax=result.done
|
||||
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
|
||||
CallIC(bool_ic);
|
||||
@ -2190,10 +2177,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
// result.value
|
||||
__ Pop(load_receiver); // result
|
||||
__ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
|
||||
if (FLAG_vector_ics) {
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->ValueFeedbackSlot()));
|
||||
}
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->ValueFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL); // result.value in rax
|
||||
context()->DropAndPlug(2, rax); // drop iter and g
|
||||
break;
|
||||
@ -2332,13 +2317,9 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
DCHECK(!prop->IsSuperAccess());
|
||||
|
||||
__ Move(LoadDescriptor::NameRegister(), key->value());
|
||||
if (FLAG_vector_ics) {
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(prop->PropertyFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
|
||||
}
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(prop->PropertyFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -2357,13 +2338,9 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
|
||||
if (FLAG_vector_ics) {
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(prop->PropertyFeedbackSlot()));
|
||||
CallIC(ic);
|
||||
} else {
|
||||
CallIC(ic, prop->PropertyFeedbackId());
|
||||
}
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(prop->PropertyFeedbackSlot()));
|
||||
CallIC(ic);
|
||||
}
|
||||
|
||||
|
||||
@ -4575,13 +4552,9 @@ void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
|
||||
// Load the function from the receiver.
|
||||
__ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
|
||||
__ Move(LoadDescriptor::NameRegister(), expr->name());
|
||||
if (FLAG_vector_ics) {
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->CallRuntimeFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
} else {
|
||||
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
|
||||
}
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(expr->CallRuntimeFeedbackSlot()));
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
}
|
||||
|
||||
|
||||
@ -5016,10 +4989,8 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||
Comment cmnt(masm_, "[ Global variable");
|
||||
__ Move(LoadDescriptor::NameRegister(), proxy->name());
|
||||
__ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||
if (FLAG_vector_ics) {
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
||||
}
|
||||
__ Move(VectorLoadICDescriptor::SlotRegister(),
|
||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
||||
// Use a regular load, not a contextual load, to avoid a reference
|
||||
// error.
|
||||
CallLoadIC(NOT_CONTEXTUAL);
|
||||
|
@ -2889,7 +2889,6 @@ void LCodeGen::DoReturn(LReturn* instr) {
|
||||
|
||||
template <class T>
|
||||
void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
|
||||
DCHECK(FLAG_vector_ics);
|
||||
Register vector_register = ToRegister(instr->temp_vector());
|
||||
Register slot_register = VectorLoadICDescriptor::SlotRegister();
|
||||
DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister()));
|
||||
@ -2912,9 +2911,7 @@ void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
|
||||
DCHECK(ToRegister(instr->result()).is(rax));
|
||||
|
||||
__ Move(LoadDescriptor::NameRegister(), instr->name());
|
||||
if (FLAG_vector_ics) {
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
}
|
||||
EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
|
||||
ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode,
|
||||
PREMONOMORPHIC).code();
|
||||
@ -3031,9 +3028,7 @@ void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
|
||||
DCHECK(ToRegister(instr->result()).is(rax));
|
||||
|
||||
__ Move(LoadDescriptor::NameRegister(), instr->name());
|
||||
if (FLAG_vector_ics) {
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
}
|
||||
EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
|
||||
Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(
|
||||
isolate(), NOT_CONTEXTUAL,
|
||||
instr->hydrogen()->initialization_state()).code();
|
||||
@ -3563,24 +3558,6 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
||||
}
|
||||
|
||||
|
||||
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()));
|
||||
Register scratch = rdi;
|
||||
DCHECK(!scratch.is(receiver) && !scratch.is(name));
|
||||
|
||||
// The probe will tail call to a handler if found.
|
||||
isolate()->stub_cache()->GenerateProbe(masm(), Code::LOAD_IC,
|
||||
instr->hydrogen()->flags(), false,
|
||||
receiver, name, scratch, no_reg);
|
||||
|
||||
LoadIC::GenerateMiss(masm());
|
||||
}
|
||||
|
||||
|
||||
void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
|
||||
DCHECK(ToRegister(instr->result()).is(rax));
|
||||
|
||||
|
@ -1126,20 +1126,6 @@ LInstruction* LChunkBuilder::DoCallWithDescriptor(
|
||||
}
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
|
||||
HTailCallThroughMegamorphicCache* instr) {
|
||||
LOperand* context = UseFixed(instr->context(), rsi);
|
||||
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(), rsi);
|
||||
LOperand* function = UseFixed(instr->function(), rdi);
|
||||
|
@ -151,7 +151,6 @@ class LCodeGen;
|
||||
V(StringCompareAndBranch) \
|
||||
V(SubI) \
|
||||
V(TaggedToI) \
|
||||
V(TailCallThroughMegamorphicCache) \
|
||||
V(ThisFunction) \
|
||||
V(ToFastProperties) \
|
||||
V(TransitionElementsKind) \
|
||||
@ -479,27 +478,6 @@ 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:
|
||||
bool HasInterestingComment(LCodeGen* gen) const override { return false; }
|
||||
|
@ -15332,9 +15332,6 @@ TEST(ExternalInternalizedStringCollectedAtTearDown) {
|
||||
|
||||
|
||||
TEST(ExternalInternalizedStringCollectedAtGC) {
|
||||
// TODO(mvstanton): vector ics need weak support.
|
||||
if (i::FLAG_vector_ics) return;
|
||||
|
||||
int destroyed = 0;
|
||||
{ LocalContext env;
|
||||
v8::HandleScope handle_scope(env->GetIsolate());
|
||||
|
@ -362,7 +362,7 @@ TEST(FeedbackVectorUnaffectedByScopeChanges) {
|
||||
// Now a feedback vector is allocated.
|
||||
CHECK(f->shared()->is_compiled());
|
||||
int expected_slots = 0;
|
||||
int expected_ic_slots = FLAG_vector_ics ? 2 : 1;
|
||||
int expected_ic_slots = 2;
|
||||
CHECK_EQ(expected_slots, f->shared()->feedback_vector()->Slots());
|
||||
CHECK_EQ(expected_ic_slots, f->shared()->feedback_vector()->ICSlots());
|
||||
}
|
||||
|
@ -46,19 +46,13 @@ TEST(VectorStructure) {
|
||||
CHECK_EQ(1, vector->ICSlots());
|
||||
|
||||
ZoneFeedbackVectorSpec spec(zone, 3, 5);
|
||||
if (FLAG_vector_ics) {
|
||||
for (int i = 0; i < 5; i++) spec.SetKind(i, Code::CALL_IC);
|
||||
}
|
||||
for (int i = 0; i < 5; i++) spec.SetKind(i, Code::CALL_IC);
|
||||
vector = factory->NewTypeFeedbackVector(&spec);
|
||||
CHECK_EQ(3, vector->Slots());
|
||||
CHECK_EQ(5, vector->ICSlots());
|
||||
|
||||
int metadata_length = vector->ic_metadata_length();
|
||||
if (!FLAG_vector_ics) {
|
||||
CHECK_EQ(0, metadata_length);
|
||||
} else {
|
||||
CHECK(metadata_length > 0);
|
||||
}
|
||||
CHECK(metadata_length > 0);
|
||||
|
||||
int index = vector->GetIndex(FeedbackVectorSlot(0));
|
||||
|
||||
@ -79,11 +73,6 @@ TEST(VectorStructure) {
|
||||
TEST(VectorICMetadata) {
|
||||
LocalContext context;
|
||||
v8::HandleScope scope(context->GetIsolate());
|
||||
if (!FLAG_vector_ics) {
|
||||
// If FLAG_vector_ics is false, we only store CALL_ICs in the vector, so
|
||||
// there is no need for metadata to describe the slots.
|
||||
return;
|
||||
}
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
Factory* factory = isolate->factory();
|
||||
Zone* zone = isolate->runtime_zone();
|
||||
@ -259,7 +248,7 @@ TEST(VectorCallICStates) {
|
||||
|
||||
|
||||
TEST(VectorLoadICStates) {
|
||||
if (i::FLAG_always_opt || !i::FLAG_vector_ics) return;
|
||||
if (i::FLAG_always_opt) return;
|
||||
CcTest::InitializeVM();
|
||||
LocalContext context;
|
||||
v8::HandleScope scope(context->GetIsolate());
|
||||
@ -313,7 +302,7 @@ TEST(VectorLoadICStates) {
|
||||
|
||||
|
||||
TEST(VectorLoadICSlotSharing) {
|
||||
if (i::FLAG_always_opt || !i::FLAG_vector_ics) return;
|
||||
if (i::FLAG_always_opt) return;
|
||||
CcTest::InitializeVM();
|
||||
LocalContext context;
|
||||
v8::HandleScope scope(context->GetIsolate());
|
||||
@ -341,7 +330,7 @@ TEST(VectorLoadICSlotSharing) {
|
||||
|
||||
|
||||
TEST(VectorLoadICOnSmi) {
|
||||
if (i::FLAG_always_opt || !i::FLAG_vector_ics) return;
|
||||
if (i::FLAG_always_opt) return;
|
||||
CcTest::InitializeVM();
|
||||
LocalContext context;
|
||||
v8::HandleScope scope(context->GetIsolate());
|
||||
|
@ -3472,23 +3472,15 @@ TEST(IncrementalMarkingPreservesMonomorphicIC) {
|
||||
CcTest::global()->Get(v8_str("f"))));
|
||||
|
||||
Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
|
||||
if (FLAG_vector_ics) {
|
||||
CheckVectorIC(f, 0, MONOMORPHIC);
|
||||
CHECK(ic_before->ic_state() == DEFAULT);
|
||||
} else {
|
||||
CHECK(ic_before->ic_state() == MONOMORPHIC);
|
||||
}
|
||||
CheckVectorIC(f, 0, MONOMORPHIC);
|
||||
CHECK(ic_before->ic_state() == DEFAULT);
|
||||
|
||||
SimulateIncrementalMarking(CcTest::heap());
|
||||
CcTest::heap()->CollectAllGarbage();
|
||||
|
||||
Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
|
||||
if (FLAG_vector_ics) {
|
||||
CheckVectorIC(f, 0, MONOMORPHIC);
|
||||
CHECK(ic_after->ic_state() == DEFAULT);
|
||||
} else {
|
||||
CHECK(ic_after->ic_state() == MONOMORPHIC);
|
||||
}
|
||||
CheckVectorIC(f, 0, MONOMORPHIC);
|
||||
CHECK(ic_after->ic_state() == DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
@ -3512,12 +3504,8 @@ TEST(IncrementalMarkingClearsMonomorphicIC) {
|
||||
*v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
|
||||
|
||||
Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
|
||||
if (FLAG_vector_ics) {
|
||||
CheckVectorIC(f, 0, MONOMORPHIC);
|
||||
CHECK(ic_before->ic_state() == DEFAULT);
|
||||
} else {
|
||||
CHECK(ic_before->ic_state() == MONOMORPHIC);
|
||||
}
|
||||
CheckVectorIC(f, 0, MONOMORPHIC);
|
||||
CHECK(ic_before->ic_state() == DEFAULT);
|
||||
|
||||
// Fire context dispose notification.
|
||||
CcTest::isolate()->ContextDisposedNotification();
|
||||
@ -3525,12 +3513,8 @@ TEST(IncrementalMarkingClearsMonomorphicIC) {
|
||||
CcTest::heap()->CollectAllGarbage();
|
||||
|
||||
Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
|
||||
if (FLAG_vector_ics) {
|
||||
CheckVectorICCleared(f, 0);
|
||||
CHECK(ic_after->ic_state() == DEFAULT);
|
||||
} else {
|
||||
CHECK(IC::IsCleared(ic_after));
|
||||
}
|
||||
CheckVectorICCleared(f, 0);
|
||||
CHECK(ic_after->ic_state() == DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
@ -3561,24 +3545,16 @@ TEST(IncrementalMarkingPreservesPolymorphicIC) {
|
||||
*v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
|
||||
|
||||
Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
|
||||
if (FLAG_vector_ics) {
|
||||
CheckVectorIC(f, 0, POLYMORPHIC);
|
||||
CHECK(ic_before->ic_state() == DEFAULT);
|
||||
} else {
|
||||
CHECK(ic_before->ic_state() == POLYMORPHIC);
|
||||
}
|
||||
CheckVectorIC(f, 0, POLYMORPHIC);
|
||||
CHECK(ic_before->ic_state() == DEFAULT);
|
||||
|
||||
// Fire context dispose notification.
|
||||
SimulateIncrementalMarking(CcTest::heap());
|
||||
CcTest::heap()->CollectAllGarbage();
|
||||
|
||||
Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
|
||||
if (FLAG_vector_ics) {
|
||||
CheckVectorIC(f, 0, POLYMORPHIC);
|
||||
CHECK(ic_after->ic_state() == DEFAULT);
|
||||
} else {
|
||||
CHECK(ic_after->ic_state() == POLYMORPHIC);
|
||||
}
|
||||
CheckVectorIC(f, 0, POLYMORPHIC);
|
||||
CHECK(ic_after->ic_state() == DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
@ -3609,25 +3585,16 @@ TEST(IncrementalMarkingClearsPolymorphicIC) {
|
||||
*v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
|
||||
|
||||
Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
|
||||
if (FLAG_vector_ics) {
|
||||
CheckVectorIC(f, 0, POLYMORPHIC);
|
||||
CHECK(ic_before->ic_state() == DEFAULT);
|
||||
} else {
|
||||
CHECK(ic_before->ic_state() == POLYMORPHIC);
|
||||
}
|
||||
CheckVectorIC(f, 0, POLYMORPHIC);
|
||||
CHECK(ic_before->ic_state() == DEFAULT);
|
||||
|
||||
// Fire context dispose notification.
|
||||
CcTest::isolate()->ContextDisposedNotification();
|
||||
SimulateIncrementalMarking(CcTest::heap());
|
||||
CcTest::heap()->CollectAllGarbage();
|
||||
|
||||
Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC);
|
||||
if (FLAG_vector_ics) {
|
||||
CheckVectorICCleared(f, 0);
|
||||
CHECK(ic_before->ic_state() == DEFAULT);
|
||||
} else {
|
||||
CHECK(IC::IsCleared(ic_after));
|
||||
}
|
||||
CheckVectorICCleared(f, 0);
|
||||
CHECK(ic_before->ic_state() == DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
@ -4730,9 +4697,8 @@ Handle<JSFunction> GetFunctionByName(Isolate* isolate, const char* name) {
|
||||
|
||||
void CheckIC(Code* code, Code::Kind kind, SharedFunctionInfo* shared,
|
||||
int ic_slot, InlineCacheState state) {
|
||||
if (FLAG_vector_ics &&
|
||||
(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC ||
|
||||
kind == Code::CALL_IC)) {
|
||||
if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC ||
|
||||
kind == Code::CALL_IC) {
|
||||
TypeFeedbackVector* vector = shared->feedback_vector();
|
||||
FeedbackVectorICSlot slot(ic_slot);
|
||||
if (kind == Code::LOAD_IC) {
|
||||
|
Loading…
Reference in New Issue
Block a user