Commit ba7b6413 authored by mvstanton's avatar mvstanton Committed by Commit bot

On a call to Array(), we patched a call ic. This CL makes do with a single...

On a call to Array(), we patched a call ic. This CL makes do with a single dispatcher which inlines the special handling for the Array() call case, loading the allocation site found in the vector and calling the array constructor stub appropriately.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#30649}
parent b37907ff
...@@ -2556,26 +2556,16 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { ...@@ -2556,26 +2556,16 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
} }
void CallIC_ArrayStub::Generate(MacroAssembler* masm) { void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
// r1 - function // r1 - function
// r3 - slot id // r3 - slot id
// r2 - vector // r2 - vector
Label miss; // r4 - allocation site (loaded from vector[slot])
int argc = arg_count(); __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r5);
ParameterCount actual(argc); __ cmp(r1, r5);
__ b(ne, miss);
__ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4);
__ cmp(r1, r4);
__ b(ne, &miss);
__ mov(r0, Operand(arg_count())); __ mov(r0, Operand(arg_count()));
__ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
__ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize));
// Verify that r4 contains an AllocationSite
__ ldr(r5, FieldMemOperand(r4, HeapObject::kMapOffset));
__ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex);
__ b(ne, &miss);
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ add(r2, r2, Operand::PointerOffsetFromSmiKey(r3)); __ add(r2, r2, Operand::PointerOffsetFromSmiKey(r3));
...@@ -2588,13 +2578,6 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) { ...@@ -2588,13 +2578,6 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
__ mov(r3, r1); __ mov(r3, r1);
ArrayConstructorStub stub(masm->isolate(), arg_count()); ArrayConstructorStub stub(masm->isolate(), arg_count());
__ TailCallStub(&stub); __ TailCallStub(&stub);
__ bind(&miss);
GenerateMiss(masm);
// The slow case, we need this no matter what to complete a call after a miss.
__ mov(r0, Operand(arg_count()));
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
} }
...@@ -2669,11 +2652,21 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2669,11 +2652,21 @@ void CallICStub::Generate(MacroAssembler* masm) {
} }
__ bind(&extra_checks_or_miss); __ bind(&extra_checks_or_miss);
Label uninitialized, miss; Label uninitialized, miss, not_allocation_site;
__ CompareRoot(r4, Heap::kmegamorphic_symbolRootIndex); __ CompareRoot(r4, Heap::kmegamorphic_symbolRootIndex);
__ b(eq, &slow_start); __ b(eq, &slow_start);
// Verify that r4 contains an AllocationSite
__ ldr(r5, FieldMemOperand(r4, HeapObject::kMapOffset));
__ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex);
__ b(ne, &not_allocation_site);
// We have an allocation site.
HandleArrayCase(masm, &miss);
__ bind(&not_allocation_site);
// The following cases attempt to handle MISS cases without going to the // The following cases attempt to handle MISS cases without going to the
// runtime. // runtime.
if (FLAG_trace_ic) { if (FLAG_trace_ic) {
...@@ -2764,10 +2757,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) { ...@@ -2764,10 +2757,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
__ Push(r1, r2, r3); __ Push(r1, r2, r3);
// Call the entry. // Call the entry.
Runtime::FunctionId id = GetICState() == DEFAULT __ CallRuntime(Runtime::kCallIC_Miss, 3);
? Runtime::kCallIC_Miss
: Runtime::kCallIC_Customization_Miss;
__ CallRuntime(id, 3);
// Move result to edi and exit the internal frame. // Move result to edi and exit the internal frame.
__ mov(r1, r0); __ mov(r1, r0);
...@@ -4276,13 +4266,6 @@ void CallICTrampolineStub::Generate(MacroAssembler* masm) { ...@@ -4276,13 +4266,6 @@ void CallICTrampolineStub::Generate(MacroAssembler* masm) {
} }
void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) {
EmitLoadTypeFeedbackVector(masm, r2);
CallIC_ArrayStub stub(isolate(), state());
__ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
}
void LoadICStub::Generate(MacroAssembler* masm) { GenerateImpl(masm, false); } void LoadICStub::Generate(MacroAssembler* masm) { GenerateImpl(masm, false); }
......
...@@ -2933,31 +2933,23 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { ...@@ -2933,31 +2933,23 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
} }
void CallIC_ArrayStub::Generate(MacroAssembler* masm) { void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
// x1 - function // x1 - function
// x3 - slot id // x3 - slot id
// x2 - vector // x2 - vector
Label miss; // x4 - allocation site (loaded from vector[slot])
Register function = x1; Register function = x1;
Register feedback_vector = x2; Register feedback_vector = x2;
Register index = x3; Register index = x3;
Register scratch = x4; Register allocation_site = x4;
Register scratch = x5;
__ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, scratch); __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, scratch);
__ Cmp(function, scratch); __ Cmp(function, scratch);
__ B(ne, &miss); __ B(ne, miss);
__ Mov(x0, Operand(arg_count())); __ Mov(x0, Operand(arg_count()));
__ Add(scratch, feedback_vector,
Operand::UntagSmiAndScale(index, kPointerSizeLog2));
__ Ldr(scratch, FieldMemOperand(scratch, FixedArray::kHeaderSize));
// Verify that scratch contains an AllocationSite
Register map = x5;
__ Ldr(map, FieldMemOperand(scratch, HeapObject::kMapOffset));
__ JumpIfNotRoot(map, Heap::kAllocationSiteMapRootIndex, &miss);
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ Add(feedback_vector, feedback_vector, __ Add(feedback_vector, feedback_vector,
Operand::UntagSmiAndScale(index, kPointerSizeLog2)); Operand::UntagSmiAndScale(index, kPointerSizeLog2));
...@@ -2967,19 +2959,13 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) { ...@@ -2967,19 +2959,13 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
__ Add(index, index, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement))); __ Add(index, index, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
__ Str(index, FieldMemOperand(feedback_vector, 0)); __ Str(index, FieldMemOperand(feedback_vector, 0));
Register allocation_site = feedback_vector; // Set up arguments for the array constructor stub.
Register original_constructor = index; Register allocation_site_arg = feedback_vector;
__ Mov(allocation_site, scratch); Register original_constructor_arg = index;
__ Mov(original_constructor, function); __ Mov(allocation_site_arg, allocation_site);
__ Mov(original_constructor_arg, function);
ArrayConstructorStub stub(masm->isolate(), arg_count()); ArrayConstructorStub stub(masm->isolate(), arg_count());
__ TailCallStub(&stub); __ TailCallStub(&stub);
__ bind(&miss);
GenerateMiss(masm);
// The slow case, we need this no matter what to complete a call after a miss.
__ Mov(x0, arg_count());
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
} }
...@@ -3067,10 +3053,17 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -3067,10 +3053,17 @@ void CallICStub::Generate(MacroAssembler* masm) {
} }
__ bind(&extra_checks_or_miss); __ bind(&extra_checks_or_miss);
Label uninitialized, miss; Label uninitialized, miss, not_allocation_site;
__ JumpIfRoot(x4, Heap::kmegamorphic_symbolRootIndex, &slow_start); __ JumpIfRoot(x4, Heap::kmegamorphic_symbolRootIndex, &slow_start);
__ Ldr(x5, FieldMemOperand(x4, HeapObject::kMapOffset));
__ JumpIfNotRoot(x5, Heap::kAllocationSiteMapRootIndex, &not_allocation_site);
HandleArrayCase(masm, &miss);
__ bind(&not_allocation_site);
// The following cases attempt to handle MISS cases without going to the // The following cases attempt to handle MISS cases without going to the
// runtime. // runtime.
if (FLAG_trace_ic) { if (FLAG_trace_ic) {
...@@ -3161,10 +3154,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) { ...@@ -3161,10 +3154,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
__ Push(x1, x2, x3); __ Push(x1, x2, x3);
// Call the entry. // Call the entry.
Runtime::FunctionId id = GetICState() == DEFAULT __ CallRuntime(Runtime::kCallIC_Miss, 3);
? Runtime::kCallIC_Miss
: Runtime::kCallIC_Customization_Miss;
__ CallRuntime(id, 3);
// Move result to edi and exit the internal frame. // Move result to edi and exit the internal frame.
__ Mov(x1, x0); __ Mov(x1, x0);
...@@ -4406,13 +4396,6 @@ void CallICTrampolineStub::Generate(MacroAssembler* masm) { ...@@ -4406,13 +4396,6 @@ void CallICTrampolineStub::Generate(MacroAssembler* masm) {
} }
void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) {
EmitLoadTypeFeedbackVector(masm, x2);
CallIC_ArrayStub stub(isolate(), state());
__ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
}
void LoadICStub::Generate(MacroAssembler* masm) { GenerateImpl(masm, false); } void LoadICStub::Generate(MacroAssembler* masm) { GenerateImpl(masm, false); }
......
...@@ -584,11 +584,6 @@ Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) { ...@@ -584,11 +584,6 @@ Type* CompareNilICStub::GetInputType(Zone* zone, Handle<Map> map) {
} }
void CallIC_ArrayStub::PrintState(std::ostream& os) const { // NOLINT
os << state() << " (Array)";
}
void CallICStub::PrintState(std::ostream& os) const { // NOLINT void CallICStub::PrintState(std::ostream& os) const { // NOLINT
os << state(); os << state();
} }
......
...@@ -29,7 +29,6 @@ namespace internal { ...@@ -29,7 +29,6 @@ namespace internal {
V(CallConstruct) \ V(CallConstruct) \
V(CallFunction) \ V(CallFunction) \
V(CallIC) \ V(CallIC) \
V(CallIC_Array) \
V(CEntry) \ V(CEntry) \
V(CompareIC) \ V(CompareIC) \
V(DoubleToI) \ V(DoubleToI) \
...@@ -40,7 +39,6 @@ namespace internal { ...@@ -40,7 +39,6 @@ namespace internal {
V(KeyedLoadICTrampoline) \ V(KeyedLoadICTrampoline) \
V(LoadICTrampoline) \ V(LoadICTrampoline) \
V(CallICTrampoline) \ V(CallICTrampoline) \
V(CallIC_ArrayTrampoline) \
V(LoadIndexedInterceptor) \ V(LoadIndexedInterceptor) \
V(LoadIndexedString) \ V(LoadIndexedString) \
V(MathPow) \ V(MathPow) \
...@@ -989,6 +987,7 @@ class CallICStub: public PlatformCodeStub { ...@@ -989,6 +987,7 @@ class CallICStub: public PlatformCodeStub {
// Code generation helpers. // Code generation helpers.
void GenerateMiss(MacroAssembler* masm); void GenerateMiss(MacroAssembler* masm);
void HandleArrayCase(MacroAssembler* masm, Label* miss);
private: private:
void PrintState(std::ostream& os) const override; // NOLINT void PrintState(std::ostream& os) const override; // NOLINT
...@@ -998,20 +997,6 @@ class CallICStub: public PlatformCodeStub { ...@@ -998,20 +997,6 @@ class CallICStub: public PlatformCodeStub {
}; };
class CallIC_ArrayStub: public CallICStub {
public:
CallIC_ArrayStub(Isolate* isolate, const CallICState& state_in)
: CallICStub(isolate, state_in) {}
InlineCacheState GetICState() const final { return MONOMORPHIC; }
private:
void PrintState(std::ostream& os) const override; // NOLINT
DEFINE_PLATFORM_CODE_STUB(CallIC_Array, CallICStub);
};
// TODO(verwaest): Translate to hydrogen code stub. // TODO(verwaest): Translate to hydrogen code stub.
class FunctionPrototypeStub : public PlatformCodeStub { class FunctionPrototypeStub : public PlatformCodeStub {
public: public:
...@@ -2339,16 +2324,6 @@ class CallICTrampolineStub : public PlatformCodeStub { ...@@ -2339,16 +2324,6 @@ class CallICTrampolineStub : public PlatformCodeStub {
}; };
class CallIC_ArrayTrampolineStub : public CallICTrampolineStub {
public:
CallIC_ArrayTrampolineStub(Isolate* isolate, const CallICState& state)
: CallICTrampolineStub(isolate, state) {}
private:
DEFINE_PLATFORM_CODE_STUB(CallIC_ArrayTrampoline, CallICTrampolineStub);
};
class LoadICStub : public PlatformCodeStub { class LoadICStub : public PlatformCodeStub {
public: public:
explicit LoadICStub(Isolate* isolate, const LoadICState& state) explicit LoadICStub(Isolate* isolate, const LoadICState& state)
......
...@@ -2209,28 +2209,19 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { ...@@ -2209,28 +2209,19 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
} }
void CallIC_ArrayStub::Generate(MacroAssembler* masm) { void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
// edi - function // edi - function
// edx - slot id // edx - slot id
// ebx - vector // ebx - vector
Label miss;
int argc = arg_count();
ParameterCount actual(argc);
__ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx); __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx);
__ cmp(edi, ecx); __ cmp(edi, ecx);
__ j(not_equal, &miss); __ j(not_equal, miss);
__ mov(eax, arg_count()); __ mov(eax, arg_count());
// Reload ecx.
__ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
FixedArray::kHeaderSize)); FixedArray::kHeaderSize));
// Verify that ecx contains an AllocationSite
Factory* factory = masm->isolate()->factory();
__ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
factory->allocation_site_map());
__ j(not_equal, &miss);
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ add(FieldOperand(ebx, edx, times_half_pointer_size, __ add(FieldOperand(ebx, edx, times_half_pointer_size,
FixedArray::kHeaderSize + kPointerSize), FixedArray::kHeaderSize + kPointerSize),
...@@ -2241,12 +2232,7 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) { ...@@ -2241,12 +2232,7 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
ArrayConstructorStub stub(masm->isolate(), arg_count()); ArrayConstructorStub stub(masm->isolate(), arg_count());
__ TailCallStub(&stub); __ TailCallStub(&stub);
__ bind(&miss); // Unreachable.
GenerateMiss(masm);
// The slow case, we need this no matter what to complete a call after a miss.
__ Set(eax, arg_count());
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
} }
...@@ -2321,11 +2307,21 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2321,11 +2307,21 @@ void CallICStub::Generate(MacroAssembler* masm) {
} }
__ bind(&extra_checks_or_miss); __ bind(&extra_checks_or_miss);
Label uninitialized, miss; Label uninitialized, miss, not_allocation_site;
__ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate))); __ cmp(ecx, Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate)));
__ j(equal, &slow_start); __ j(equal, &slow_start);
// Check if we have an allocation site.
__ CompareRoot(FieldOperand(ecx, HeapObject::kMapOffset),
Heap::kAllocationSiteMapRootIndex);
__ j(not_equal, &not_allocation_site);
// We have an allocation site.
HandleArrayCase(masm, &miss);
__ bind(&not_allocation_site);
// The following cases attempt to handle MISS cases without going to the // The following cases attempt to handle MISS cases without going to the
// runtime. // runtime.
if (FLAG_trace_ic) { if (FLAG_trace_ic) {
...@@ -2415,10 +2411,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) { ...@@ -2415,10 +2411,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
__ push(edx); __ push(edx);
// Call the entry. // Call the entry.
Runtime::FunctionId id = GetICState() == DEFAULT __ CallRuntime(Runtime::kCallIC_Miss, 3);
? Runtime::kCallIC_Miss
: Runtime::kCallIC_Customization_Miss;
__ CallRuntime(id, 3);
// Move result to edi and exit the internal frame. // Move result to edi and exit the internal frame.
__ mov(edi, eax); __ mov(edi, eax);
...@@ -4892,13 +4885,6 @@ void CallICTrampolineStub::Generate(MacroAssembler* masm) { ...@@ -4892,13 +4885,6 @@ void CallICTrampolineStub::Generate(MacroAssembler* masm) {
} }
void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) {
EmitLoadTypeFeedbackVector(masm, ebx);
CallIC_ArrayStub stub(isolate(), state());
__ jmp(stub.GetCode(), RelocInfo::CODE_TARGET);
}
void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
if (masm->isolate()->function_entry_hook() != NULL) { if (masm->isolate()->function_entry_hook() != NULL) {
ProfileEntryHookStub stub(masm->isolate()); ProfileEntryHookStub stub(masm->isolate());
......
...@@ -60,6 +60,7 @@ void IC::SetTargetAtAddress(Address address, Code* target, ...@@ -60,6 +60,7 @@ void IC::SetTargetAtAddress(Address address, Code* target,
DCHECK(!target->is_inline_cache_stub() || DCHECK(!target->is_inline_cache_stub() ||
(target->kind() != Code::LOAD_IC && (target->kind() != Code::LOAD_IC &&
target->kind() != Code::KEYED_LOAD_IC && target->kind() != Code::KEYED_LOAD_IC &&
target->kind() != Code::CALL_IC &&
(!FLAG_vector_stores || (target->kind() != Code::STORE_IC && (!FLAG_vector_stores || (target->kind() != Code::STORE_IC &&
target->kind() != Code::KEYED_STORE_IC)))); target->kind() != Code::KEYED_STORE_IC))));
......
...@@ -2297,73 +2297,7 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, ...@@ -2297,73 +2297,7 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
} }
bool CallIC::DoCustomHandler(Handle<Object> function,
const CallICState& callic_state) {
DCHECK(FLAG_use_ic && function->IsJSFunction());
// Are we the array function?
Handle<JSFunction> array_function =
Handle<JSFunction>(isolate()->native_context()->array_function());
if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) {
// Alter the slot.
CallICNexus* nexus = casted_nexus<CallICNexus>();
nexus->ConfigureMonomorphicArray();
// Vector-based ICs have a different calling convention in optimized code
// than full code so the correct stub has to be chosen.
if (AddressIsOptimizedCode()) {
CallIC_ArrayStub stub(isolate(), callic_state);
set_target(*stub.GetCode());
} else {
CallIC_ArrayTrampolineStub stub(isolate(), callic_state);
set_target(*stub.GetCode());
}
Handle<String> name;
if (array_function->shared()->name()->IsString()) {
name = Handle<String>(String::cast(array_function->shared()->name()),
isolate());
}
TRACE_IC("CallIC", name);
OnTypeFeedbackChanged(isolate(), get_host(), nexus->vector(), state(),
MONOMORPHIC);
return true;
}
return false;
}
void CallIC::PatchMegamorphic(Handle<Object> function) {
CallICState callic_state(target()->extra_ic_state());
// We are going generic.
CallICNexus* nexus = casted_nexus<CallICNexus>();
nexus->ConfigureMegamorphic();
// Vector-based ICs have a different calling convention in optimized code
// than full code so the correct stub has to be chosen.
if (AddressIsOptimizedCode()) {
CallICStub stub(isolate(), callic_state);
set_target(*stub.GetCode());
} else {
CallICTrampolineStub stub(isolate(), callic_state);
set_target(*stub.GetCode());
}
Handle<Object> name = isolate()->factory()->empty_string();
if (function->IsJSFunction()) {
Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
name = handle(js_function->shared()->name(), isolate());
}
TRACE_IC("CallIC", name);
OnTypeFeedbackChanged(isolate(), get_host(), nexus->vector(), state(),
GENERIC);
}
void CallIC::HandleMiss(Handle<Object> function) { void CallIC::HandleMiss(Handle<Object> function) {
CallICState callic_state(target()->extra_ic_state());
Handle<Object> name = isolate()->factory()->empty_string(); Handle<Object> name = isolate()->factory()->empty_string();
CallICNexus* nexus = casted_nexus<CallICNexus>(); CallICNexus* nexus = casted_nexus<CallICNexus>();
Object* feedback = nexus->GetFeedback(); Object* feedback = nexus->GetFeedback();
...@@ -2371,25 +2305,22 @@ void CallIC::HandleMiss(Handle<Object> function) { ...@@ -2371,25 +2305,22 @@ void CallIC::HandleMiss(Handle<Object> function) {
// Hand-coded MISS handling is easier if CallIC slots don't contain smis. // Hand-coded MISS handling is easier if CallIC slots don't contain smis.
DCHECK(!feedback->IsSmi()); DCHECK(!feedback->IsSmi());
if (feedback->IsWeakCell() || !function->IsJSFunction()) { if (feedback->IsWeakCell() || !function->IsJSFunction() ||
feedback->IsAllocationSite()) {
// We are going generic. // We are going generic.
nexus->ConfigureMegamorphic(); nexus->ConfigureMegamorphic();
} else { } else {
// The feedback is either uninitialized or an allocation site. DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate()));
// It might be an allocation site because if we re-compile the full code Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
// to add deoptimization support, we call with the default call-ic, and
// merely need to patch the target to match the feedback.
// TODO(mvstanton): the better approach is to dispense with patching
// altogether, which is in progress.
DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate()) ||
feedback->IsAllocationSite());
// Do we want to install a custom handler?
if (FLAG_use_ic && DoCustomHandler(function, callic_state)) {
return;
}
nexus->ConfigureMonomorphic(Handle<JSFunction>::cast(function)); Handle<JSFunction> array_function =
Handle<JSFunction>(isolate()->native_context()->array_function());
if (array_function.is_identical_to(js_function)) {
// Alter the slot.
nexus->ConfigureMonomorphicArray();
} else {
nexus->ConfigureMonomorphic(js_function);
}
} }
if (function->IsJSFunction()) { if (function->IsJSFunction()) {
...@@ -2426,22 +2357,6 @@ RUNTIME_FUNCTION(Runtime_CallIC_Miss) { ...@@ -2426,22 +2357,6 @@ RUNTIME_FUNCTION(Runtime_CallIC_Miss) {
} }
RUNTIME_FUNCTION(Runtime_CallIC_Customization_Miss) {
TimerEventScope<TimerEventIcMiss> timer(isolate);
HandleScope scope(isolate);
DCHECK(args.length() == 3);
Handle<Object> function = args.at<Object>(0);
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1);
Handle<Smi> slot = args.at<Smi>(2);
FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value());
CallICNexus nexus(vector, vector_slot);
// A miss on a custom call ic always results in going megamorphic.
CallIC ic(isolate, &nexus);
ic.PatchMegamorphic(function);
return *function;
}
// Used from ic-<arch>.cc. // Used from ic-<arch>.cc.
RUNTIME_FUNCTION(Runtime_LoadIC_Miss) { RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
TimerEventScope<TimerEventIcMiss> timer(isolate); TimerEventScope<TimerEventIcMiss> timer(isolate);
......
...@@ -285,14 +285,8 @@ class CallIC : public IC { ...@@ -285,14 +285,8 @@ class CallIC : public IC {
DCHECK(nexus != NULL); DCHECK(nexus != NULL);
} }
void PatchMegamorphic(Handle<Object> function);
void HandleMiss(Handle<Object> function); void HandleMiss(Handle<Object> function);
// Returns true if a custom handler was installed.
bool DoCustomHandler(Handle<Object> function,
const CallICState& callic_state);
// Code generator routines. // Code generator routines.
static Handle<Code> initialize_stub(Isolate* isolate, int argc, static Handle<Code> initialize_stub(Isolate* isolate, int argc,
CallICState::CallType call_type); CallICState::CallType call_type);
......
...@@ -2687,24 +2687,15 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { ...@@ -2687,24 +2687,15 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
} }
void CallIC_ArrayStub::Generate(MacroAssembler* masm) { void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
// a1 - function // a1 - function
// a3 - slot id // a3 - slot id
// a2 - vector // a2 - vector
Label miss; // t0 - loaded from vector[slot]
__ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, at); __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, at);
__ Branch(&miss, ne, a1, Operand(at)); __ Branch(miss, ne, a1, Operand(at));
__ li(a0, Operand(arg_count())); __ li(a0, Operand(arg_count()));
__ sll(at, a3, kPointerSizeLog2 - kSmiTagSize);
__ Addu(at, a2, Operand(at));
__ lw(t0, FieldMemOperand(at, FixedArray::kHeaderSize));
// Verify that t0 contains an AllocationSite
__ lw(t1, FieldMemOperand(t0, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kAllocationSiteMapRootIndex);
__ Branch(&miss, ne, t1, Operand(at));
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ sll(at, a3, kPointerSizeLog2 - kSmiTagSize); __ sll(at, a3, kPointerSizeLog2 - kSmiTagSize);
...@@ -2717,13 +2708,6 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) { ...@@ -2717,13 +2708,6 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
__ mov(a3, a1); __ mov(a3, a1);
ArrayConstructorStub stub(masm->isolate(), arg_count()); ArrayConstructorStub stub(masm->isolate(), arg_count());
__ TailCallStub(&stub); __ TailCallStub(&stub);
__ bind(&miss);
GenerateMiss(masm);
// The slow case, we need this no matter what to complete a call after a miss.
__ li(a0, Operand(arg_count()));
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
} }
...@@ -2798,11 +2782,20 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2798,11 +2782,20 @@ void CallICStub::Generate(MacroAssembler* masm) {
} }
__ bind(&extra_checks_or_miss); __ bind(&extra_checks_or_miss);
Label uninitialized, miss; Label uninitialized, miss, not_allocation_site;
__ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex); __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
__ Branch(&slow_start, eq, t0, Operand(at)); __ Branch(&slow_start, eq, t0, Operand(at));
// Verify that t0 contains an AllocationSite
__ lw(t1, FieldMemOperand(t0, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kAllocationSiteMapRootIndex);
__ Branch(&not_allocation_site, ne, t1, Operand(at));
HandleArrayCase(masm, &miss);
__ bind(&not_allocation_site);
// The following cases attempt to handle MISS cases without going to the // The following cases attempt to handle MISS cases without going to the
// runtime. // runtime.
if (FLAG_trace_ic) { if (FLAG_trace_ic) {
...@@ -2894,10 +2887,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) { ...@@ -2894,10 +2887,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
__ Push(a1, a2, a3); __ Push(a1, a2, a3);
// Call the entry. // Call the entry.
Runtime::FunctionId id = GetICState() == DEFAULT __ CallRuntime(Runtime::kCallIC_Miss, 3);
? Runtime::kCallIC_Miss
: Runtime::kCallIC_Customization_Miss;
__ CallRuntime(id, 3);
// Move result to a1 and exit the internal frame. // Move result to a1 and exit the internal frame.
__ mov(a1, v0); __ mov(a1, v0);
...@@ -4499,13 +4489,6 @@ void CallICTrampolineStub::Generate(MacroAssembler* masm) { ...@@ -4499,13 +4489,6 @@ void CallICTrampolineStub::Generate(MacroAssembler* masm) {
} }
void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) {
EmitLoadTypeFeedbackVector(masm, a2);
CallIC_ArrayStub stub(isolate(), state());
__ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
}
void LoadICStub::Generate(MacroAssembler* masm) { GenerateImpl(masm, false); } void LoadICStub::Generate(MacroAssembler* masm) { GenerateImpl(masm, false); }
......
...@@ -2763,24 +2763,13 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { ...@@ -2763,24 +2763,13 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
} }
void CallIC_ArrayStub::Generate(MacroAssembler* masm) { void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
// a1 - function // a1 - function
// a3 - slot id // a3 - slot id
// a2 - vector // a2 - vector
Label miss; // a4 - allocation site (loaded from vector[slot])
__ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, at); __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, at);
__ Branch(&miss, ne, a1, Operand(at)); __ Branch(miss, ne, a1, Operand(at));
__ li(a0, Operand(arg_count()));
__ dsrl(at, a3, 32 - kPointerSizeLog2);
__ Daddu(at, a2, Operand(at));
__ ld(a4, FieldMemOperand(at, FixedArray::kHeaderSize));
// Verify that a4 contains an AllocationSite
__ ld(a5, FieldMemOperand(a4, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kAllocationSiteMapRootIndex);
__ Branch(&miss, ne, a5, Operand(at));
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
__ dsrl(t0, a3, 32 - kPointerSizeLog2); __ dsrl(t0, a3, 32 - kPointerSizeLog2);
...@@ -2793,13 +2782,6 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) { ...@@ -2793,13 +2782,6 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
__ mov(a3, a1); __ mov(a3, a1);
ArrayConstructorStub stub(masm->isolate(), arg_count()); ArrayConstructorStub stub(masm->isolate(), arg_count());
__ TailCallStub(&stub); __ TailCallStub(&stub);
__ bind(&miss);
GenerateMiss(masm);
// The slow case, we need this no matter what to complete a call after a miss.
__ li(a0, Operand(arg_count()));
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
} }
...@@ -2874,11 +2856,20 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2874,11 +2856,20 @@ void CallICStub::Generate(MacroAssembler* masm) {
} }
__ bind(&extra_checks_or_miss); __ bind(&extra_checks_or_miss);
Label uninitialized, miss; Label uninitialized, miss, not_allocation_site;
__ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex); __ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
__ Branch(&slow_start, eq, a4, Operand(at)); __ Branch(&slow_start, eq, a4, Operand(at));
// Verify that a4 contains an AllocationSite
__ ld(a5, FieldMemOperand(a4, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kAllocationSiteMapRootIndex);
__ Branch(&not_allocation_site, ne, a5, Operand(at));
HandleArrayCase(masm, &miss);
__ bind(&not_allocation_site);
// The following cases attempt to handle MISS cases without going to the // The following cases attempt to handle MISS cases without going to the
// runtime. // runtime.
if (FLAG_trace_ic) { if (FLAG_trace_ic) {
...@@ -2970,10 +2961,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) { ...@@ -2970,10 +2961,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
__ Push(a1, a2, a3); __ Push(a1, a2, a3);
// Call the entry. // Call the entry.
Runtime::FunctionId id = GetICState() == DEFAULT __ CallRuntime(Runtime::kCallIC_Miss, 3);
? Runtime::kCallIC_Miss //
: Runtime::kCallIC_Customization_Miss;
__ CallRuntime(id, 3);
// Move result to a1 and exit the internal frame. // Move result to a1 and exit the internal frame.
__ mov(a1, v0); __ mov(a1, v0);
...@@ -4531,13 +4519,6 @@ void CallICTrampolineStub::Generate(MacroAssembler* masm) { ...@@ -4531,13 +4519,6 @@ void CallICTrampolineStub::Generate(MacroAssembler* masm) {
} }
void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) {
EmitLoadTypeFeedbackVector(masm, a2);
CallIC_ArrayStub stub(isolate(), state());
__ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
}
void LoadICStub::Generate(MacroAssembler* masm) { GenerateImpl(masm, false); } void LoadICStub::Generate(MacroAssembler* masm) { GenerateImpl(masm, false); }
......
...@@ -1022,7 +1022,6 @@ namespace internal { ...@@ -1022,7 +1022,6 @@ namespace internal {
F(LoadIC_Miss, 3, 1) \ F(LoadIC_Miss, 3, 1) \
F(KeyedLoadIC_Miss, 3, 1) \ F(KeyedLoadIC_Miss, 3, 1) \
F(CallIC_Miss, 3, 1) \ F(CallIC_Miss, 3, 1) \
F(CallIC_Customization_Miss, 3, 1) \
F(StoreIC_Miss, 3, 1) \ F(StoreIC_Miss, 3, 1) \
F(StoreIC_Slow, 3, 1) \ F(StoreIC_Slow, 3, 1) \
F(KeyedStoreIC_Miss, 3, 1) \ F(KeyedStoreIC_Miss, 3, 1) \
......
...@@ -2068,30 +2068,18 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { ...@@ -2068,30 +2068,18 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
} }
void CallIC_ArrayStub::Generate(MacroAssembler* masm) { void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
// rdi - function // rdi - function
// rdx - slot id (as integer) // rdx - slot id
// rbx - vector // rbx - vector
Label miss; // rcx - allocation site (loaded from vector[slot]).
int argc = arg_count(); __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r8);
ParameterCount actual(argc); __ cmpp(rdi, r8);
__ j(not_equal, miss);
__ SmiToInteger32(rdx, rdx);
__ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx);
__ cmpp(rdi, rcx);
__ j(not_equal, &miss);
__ movp(rax, Immediate(arg_count())); __ movp(rax, Immediate(arg_count()));
__ movp(rcx, FieldOperand(rbx, rdx, times_pointer_size,
FixedArray::kHeaderSize));
// Verify that ecx contains an AllocationSite
__ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
Heap::kAllocationSiteMapRootIndex);
__ j(not_equal, &miss, Label::kNear);
// Increment the call count for monomorphic function calls. // Increment the call count for monomorphic function calls.
{
__ SmiAddConstant(FieldOperand(rbx, rdx, times_pointer_size, __ SmiAddConstant(FieldOperand(rbx, rdx, times_pointer_size,
FixedArray::kHeaderSize + kPointerSize), FixedArray::kHeaderSize + kPointerSize),
Smi::FromInt(CallICNexus::kCallCountIncrement)); Smi::FromInt(CallICNexus::kCallCountIncrement));
...@@ -2100,14 +2088,6 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) { ...@@ -2100,14 +2088,6 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
__ movp(rdx, rdi); __ movp(rdx, rdi);
ArrayConstructorStub stub(masm->isolate(), arg_count()); ArrayConstructorStub stub(masm->isolate(), arg_count());
__ TailCallStub(&stub); __ TailCallStub(&stub);
}
__ bind(&miss);
GenerateMiss(masm);
// The slow case, we need this no matter what to complete a call after a miss.
__ Set(rax, arg_count());
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
} }
...@@ -2184,11 +2164,21 @@ void CallICStub::Generate(MacroAssembler* masm) { ...@@ -2184,11 +2164,21 @@ void CallICStub::Generate(MacroAssembler* masm) {
} }
__ bind(&extra_checks_or_miss); __ bind(&extra_checks_or_miss);
Label uninitialized, miss; Label uninitialized, miss, not_allocation_site;
__ Cmp(rcx, TypeFeedbackVector::MegamorphicSentinel(isolate)); __ Cmp(rcx, TypeFeedbackVector::MegamorphicSentinel(isolate));
__ j(equal, &slow_start); __ j(equal, &slow_start);
// Check if we have an allocation site.
__ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
Heap::kAllocationSiteMapRootIndex);
__ j(not_equal, &not_allocation_site);
// We have an allocation site.
HandleArrayCase(masm, &miss);
__ bind(&not_allocation_site);
// The following cases attempt to handle MISS cases without going to the // The following cases attempt to handle MISS cases without going to the
// runtime. // runtime.
if (FLAG_trace_ic) { if (FLAG_trace_ic) {
...@@ -2278,10 +2268,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) { ...@@ -2278,10 +2268,7 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
__ Push(rdx); __ Push(rdx);
// Call the entry. // Call the entry.
Runtime::FunctionId id = GetICState() == DEFAULT __ CallRuntime(Runtime::kCallIC_Miss, 3);
? Runtime::kCallIC_Miss
: Runtime::kCallIC_Customization_Miss;
__ CallRuntime(id, 3);
// Move result to edi and exit the internal frame. // Move result to edi and exit the internal frame.
__ movp(rdi, rax); __ movp(rdi, rax);
...@@ -4649,13 +4636,6 @@ void CallICTrampolineStub::Generate(MacroAssembler* masm) { ...@@ -4649,13 +4636,6 @@ void CallICTrampolineStub::Generate(MacroAssembler* masm) {
} }
void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) {
EmitLoadTypeFeedbackVector(masm, rbx);
CallIC_ArrayStub stub(isolate(), state());
__ jmp(stub.GetCode(), RelocInfo::CODE_TARGET);
}
void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
if (masm->isolate()->function_entry_hook() != NULL) { if (masm->isolate()->function_entry_hook() != NULL) {
ProfileEntryHookStub stub(masm->isolate()); ProfileEntryHookStub stub(masm->isolate());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment