Type Feedback Vector: Calculate profiler counts on the fly.
It's cumbersome to maintain IC profiler statistics all the time. Let's just do it as needed. BUG= Review URL: https://codereview.chromium.org/1507903004 Cr-Commit-Position: refs/heads/master@{#32693}
This commit is contained in:
parent
175c90f8f2
commit
2b63d6b079
@ -2448,10 +2448,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
// r1 - function
|
||||
// r3 - slot id (Smi)
|
||||
// r2 - vector
|
||||
const int with_types_offset =
|
||||
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
|
||||
const int generic_offset =
|
||||
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
|
||||
Label extra_checks_or_miss, call, call_function;
|
||||
int argc = arg_count();
|
||||
ParameterCount actual(argc);
|
||||
@ -2527,13 +2523,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
|
||||
__ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex);
|
||||
__ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize));
|
||||
// We have to update statistics for runtime profiling.
|
||||
__ ldr(r4, FieldMemOperand(r2, with_types_offset));
|
||||
__ sub(r4, r4, Operand(Smi::FromInt(1)));
|
||||
__ str(r4, FieldMemOperand(r2, with_types_offset));
|
||||
__ ldr(r4, FieldMemOperand(r2, generic_offset));
|
||||
__ add(r4, r4, Operand(Smi::FromInt(1)));
|
||||
__ str(r4, FieldMemOperand(r2, generic_offset));
|
||||
|
||||
__ bind(&call);
|
||||
__ mov(r0, Operand(argc));
|
||||
@ -2562,11 +2551,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ cmp(r4, ip);
|
||||
__ b(ne, &miss);
|
||||
|
||||
// Update stats.
|
||||
__ ldr(r4, FieldMemOperand(r2, with_types_offset));
|
||||
__ add(r4, r4, Operand(Smi::FromInt(1)));
|
||||
__ str(r4, FieldMemOperand(r2, with_types_offset));
|
||||
|
||||
// Initialize the call counter.
|
||||
__ Move(r5, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
|
||||
__ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
|
||||
|
@ -2827,10 +2827,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
// x1 - function
|
||||
// x3 - slot id (Smi)
|
||||
// x2 - vector
|
||||
const int with_types_offset =
|
||||
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
|
||||
const int generic_offset =
|
||||
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
|
||||
Label extra_checks_or_miss, call, call_function;
|
||||
int argc = arg_count();
|
||||
ParameterCount actual(argc);
|
||||
@ -2908,13 +2904,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
Operand::UntagSmiAndScale(index, kPointerSizeLog2));
|
||||
__ LoadRoot(x5, Heap::kmegamorphic_symbolRootIndex);
|
||||
__ Str(x5, FieldMemOperand(x4, FixedArray::kHeaderSize));
|
||||
// We have to update statistics for runtime profiling.
|
||||
__ Ldr(x4, FieldMemOperand(feedback_vector, with_types_offset));
|
||||
__ Subs(x4, x4, Operand(Smi::FromInt(1)));
|
||||
__ Str(x4, FieldMemOperand(feedback_vector, with_types_offset));
|
||||
__ Ldr(x4, FieldMemOperand(feedback_vector, generic_offset));
|
||||
__ Adds(x4, x4, Operand(Smi::FromInt(1)));
|
||||
__ Str(x4, FieldMemOperand(feedback_vector, generic_offset));
|
||||
|
||||
__ Bind(&call);
|
||||
__ Mov(x0, argc);
|
||||
@ -2942,11 +2931,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ Cmp(x4, x5);
|
||||
__ B(ne, &miss);
|
||||
|
||||
// Update stats.
|
||||
__ Ldr(x4, FieldMemOperand(feedback_vector, with_types_offset));
|
||||
__ Adds(x4, x4, Operand(Smi::FromInt(1)));
|
||||
__ Str(x4, FieldMemOperand(feedback_vector, with_types_offset));
|
||||
|
||||
// Initialize the call counter.
|
||||
__ Mov(x5, Smi::FromInt(CallICNexus::kCallCountIncrement));
|
||||
__ Adds(x4, feedback_vector,
|
||||
|
@ -2085,10 +2085,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
// edx - slot id
|
||||
// ebx - vector
|
||||
Isolate* isolate = masm->isolate();
|
||||
const int with_types_offset =
|
||||
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
|
||||
const int generic_offset =
|
||||
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
|
||||
Label extra_checks_or_miss, call, call_function;
|
||||
int argc = arg_count();
|
||||
ParameterCount actual(argc);
|
||||
@ -2161,9 +2157,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ mov(
|
||||
FieldOperand(ebx, edx, times_half_pointer_size, FixedArray::kHeaderSize),
|
||||
Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate)));
|
||||
// We have to update statistics for runtime profiling.
|
||||
__ sub(FieldOperand(ebx, with_types_offset), Immediate(Smi::FromInt(1)));
|
||||
__ add(FieldOperand(ebx, generic_offset), Immediate(Smi::FromInt(1)));
|
||||
|
||||
__ bind(&call);
|
||||
__ Set(eax, argc);
|
||||
@ -2191,9 +2184,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ cmp(ecx, NativeContextOperand());
|
||||
__ j(not_equal, &miss);
|
||||
|
||||
// Update stats.
|
||||
__ add(FieldOperand(ebx, with_types_offset), Immediate(Smi::FromInt(1)));
|
||||
|
||||
// Initialize the call counter.
|
||||
__ mov(FieldOperand(ebx, edx, times_half_pointer_size,
|
||||
FixedArray::kHeaderSize + kPointerSize),
|
||||
|
41
src/ic/ic.cc
41
src/ic/ic.cc
@ -415,19 +415,9 @@ void IC::OnTypeFeedbackChanged(Isolate* isolate, Address address,
|
||||
|
||||
|
||||
// static
|
||||
void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host,
|
||||
TypeFeedbackVector* vector, State old_state,
|
||||
State new_state) {
|
||||
void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host) {
|
||||
if (host->kind() != Code::FUNCTION) return;
|
||||
|
||||
if (FLAG_type_info_threshold > 0) {
|
||||
int polymorphic_delta = 0; // "Polymorphic" here includes monomorphic.
|
||||
int generic_delta = 0; // "Generic" here includes megamorphic.
|
||||
ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta,
|
||||
&generic_delta);
|
||||
vector->change_ic_with_type_info_count(polymorphic_delta);
|
||||
vector->change_ic_generic_count(generic_delta);
|
||||
}
|
||||
TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
|
||||
info->change_own_type_change_checksum();
|
||||
host->set_profiler_ticks(0);
|
||||
@ -491,9 +481,8 @@ void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) {
|
||||
// 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.
|
||||
State state = nexus->StateFromFeedback();
|
||||
nexus->ConfigurePremonomorphic();
|
||||
OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC);
|
||||
OnTypeFeedbackChanged(isolate, host);
|
||||
}
|
||||
|
||||
|
||||
@ -505,16 +494,15 @@ void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) {
|
||||
if (state != UNINITIALIZED && !feedback->IsAllocationSite()) {
|
||||
nexus->ConfigureUninitialized();
|
||||
// The change in state must be processed.
|
||||
OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, UNINITIALIZED);
|
||||
OnTypeFeedbackChanged(isolate, host);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) {
|
||||
if (IsCleared(nexus)) return;
|
||||
State state = nexus->StateFromFeedback();
|
||||
nexus->ConfigurePremonomorphic();
|
||||
OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC);
|
||||
OnTypeFeedbackChanged(isolate, host);
|
||||
}
|
||||
|
||||
|
||||
@ -529,9 +517,8 @@ void StoreIC::Clear(Isolate* isolate, Address address, Code* target,
|
||||
|
||||
void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) {
|
||||
if (IsCleared(nexus)) return;
|
||||
State state = nexus->StateFromFeedback();
|
||||
nexus->ConfigurePremonomorphic();
|
||||
OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC);
|
||||
OnTypeFeedbackChanged(isolate, host);
|
||||
}
|
||||
|
||||
|
||||
@ -547,9 +534,8 @@ void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target,
|
||||
void KeyedStoreIC::Clear(Isolate* isolate, Code* host,
|
||||
KeyedStoreICNexus* nexus) {
|
||||
if (IsCleared(nexus)) return;
|
||||
State state = nexus->StateFromFeedback();
|
||||
nexus->ConfigurePremonomorphic();
|
||||
OnTypeFeedbackChanged(isolate, host, nexus->vector(), state, PREMONOMORPHIC);
|
||||
OnTypeFeedbackChanged(isolate, host);
|
||||
}
|
||||
|
||||
|
||||
@ -599,8 +585,7 @@ void IC::ConfigureVectorState(IC::State new_state) {
|
||||
}
|
||||
|
||||
vector_set_ = true;
|
||||
OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(),
|
||||
new_state);
|
||||
OnTypeFeedbackChanged(isolate(), get_host());
|
||||
}
|
||||
|
||||
|
||||
@ -623,8 +608,7 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
|
||||
}
|
||||
|
||||
vector_set_ = true;
|
||||
OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(),
|
||||
MONOMORPHIC);
|
||||
OnTypeFeedbackChanged(isolate(), get_host());
|
||||
}
|
||||
|
||||
|
||||
@ -647,8 +631,7 @@ void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
|
||||
}
|
||||
|
||||
vector_set_ = true;
|
||||
OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(),
|
||||
POLYMORPHIC);
|
||||
OnTypeFeedbackChanged(isolate(), get_host());
|
||||
}
|
||||
|
||||
|
||||
@ -661,8 +644,7 @@ void IC::ConfigureVectorState(MapHandleList* maps,
|
||||
nexus->ConfigurePolymorphic(maps, transitioned_maps, handlers);
|
||||
|
||||
vector_set_ = true;
|
||||
OnTypeFeedbackChanged(isolate(), get_host(), *vector(), saved_state(),
|
||||
POLYMORPHIC);
|
||||
OnTypeFeedbackChanged(isolate(), get_host());
|
||||
}
|
||||
|
||||
|
||||
@ -2205,8 +2187,7 @@ void CallIC::HandleMiss(Handle<Object> function) {
|
||||
name = handle(js_function->shared()->name(), isolate());
|
||||
}
|
||||
|
||||
IC::State new_state = nexus->StateFromFeedback();
|
||||
OnTypeFeedbackChanged(isolate(), get_host(), *vector(), state(), new_state);
|
||||
OnTypeFeedbackChanged(isolate(), get_host());
|
||||
TRACE_IC("CallIC", name);
|
||||
}
|
||||
|
||||
|
@ -143,9 +143,7 @@ class IC {
|
||||
State old_state, State new_state,
|
||||
bool target_remains_ic_stub);
|
||||
// As a vector-based IC, type feedback must be updated differently.
|
||||
static void OnTypeFeedbackChanged(Isolate* isolate, Code* host,
|
||||
TypeFeedbackVector* vector, State old_state,
|
||||
State new_state);
|
||||
static void OnTypeFeedbackChanged(Isolate* isolate, Code* host);
|
||||
static void PostPatching(Address address, Code* target, Code* old_target);
|
||||
|
||||
// Compute the handler either by compiling or by retrieving a cached version.
|
||||
|
@ -2577,10 +2577,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
// a1 - function
|
||||
// a3 - slot id (Smi)
|
||||
// a2 - vector
|
||||
const int with_types_offset =
|
||||
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
|
||||
const int generic_offset =
|
||||
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
|
||||
Label extra_checks_or_miss, call, call_function;
|
||||
int argc = arg_count();
|
||||
ParameterCount actual(argc);
|
||||
@ -2657,13 +2653,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ Addu(t0, a2, Operand(t0));
|
||||
__ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
|
||||
__ sw(at, FieldMemOperand(t0, FixedArray::kHeaderSize));
|
||||
// We have to update statistics for runtime profiling.
|
||||
__ lw(t0, FieldMemOperand(a2, with_types_offset));
|
||||
__ Subu(t0, t0, Operand(Smi::FromInt(1)));
|
||||
__ sw(t0, FieldMemOperand(a2, with_types_offset));
|
||||
__ lw(t0, FieldMemOperand(a2, generic_offset));
|
||||
__ Addu(t0, t0, Operand(Smi::FromInt(1)));
|
||||
__ sw(t0, FieldMemOperand(a2, generic_offset));
|
||||
|
||||
__ bind(&call);
|
||||
__ Jump(masm->isolate()->builtins()->Call(convert_mode()),
|
||||
@ -2691,11 +2680,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ lw(t1, NativeContextMemOperand());
|
||||
__ Branch(&miss, ne, t0, Operand(t1));
|
||||
|
||||
// Update stats.
|
||||
__ lw(t0, FieldMemOperand(a2, with_types_offset));
|
||||
__ Addu(t0, t0, Operand(Smi::FromInt(1)));
|
||||
__ sw(t0, FieldMemOperand(a2, with_types_offset));
|
||||
|
||||
// Initialize the call counter.
|
||||
__ sll(at, a3, kPointerSizeLog2 - kSmiTagSize);
|
||||
__ Addu(at, a2, Operand(at));
|
||||
|
@ -2653,10 +2653,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
// a1 - function
|
||||
// a3 - slot id (Smi)
|
||||
// a2 - vector
|
||||
const int with_types_offset =
|
||||
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
|
||||
const int generic_offset =
|
||||
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
|
||||
Label extra_checks_or_miss, call, call_function;
|
||||
int argc = arg_count();
|
||||
ParameterCount actual(argc);
|
||||
@ -2733,13 +2729,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ Daddu(a4, a2, Operand(a4));
|
||||
__ LoadRoot(at, Heap::kmegamorphic_symbolRootIndex);
|
||||
__ sd(at, FieldMemOperand(a4, FixedArray::kHeaderSize));
|
||||
// We have to update statistics for runtime profiling.
|
||||
__ ld(a4, FieldMemOperand(a2, with_types_offset));
|
||||
__ Dsubu(a4, a4, Operand(Smi::FromInt(1)));
|
||||
__ sd(a4, FieldMemOperand(a2, with_types_offset));
|
||||
__ ld(a4, FieldMemOperand(a2, generic_offset));
|
||||
__ Daddu(a4, a4, Operand(Smi::FromInt(1)));
|
||||
__ sd(a4, FieldMemOperand(a2, generic_offset));
|
||||
|
||||
__ bind(&call);
|
||||
__ Jump(masm->isolate()->builtins()->Call(convert_mode()),
|
||||
@ -2767,11 +2756,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ ld(t1, NativeContextMemOperand());
|
||||
__ Branch(&miss, ne, t0, Operand(t1));
|
||||
|
||||
// Update stats.
|
||||
__ ld(a4, FieldMemOperand(a2, with_types_offset));
|
||||
__ Daddu(a4, a4, Operand(Smi::FromInt(1)));
|
||||
__ sd(a4, FieldMemOperand(a2, with_types_offset));
|
||||
|
||||
// Initialize the call counter.
|
||||
__ dsrl(at, a3, 32 - kPointerSizeLog2);
|
||||
__ Daddu(at, a2, Operand(at));
|
||||
|
@ -597,9 +597,6 @@ void TypeFeedbackVector::TypeFeedbackVectorPrint(std::ostream& os) { // NOLINT
|
||||
return;
|
||||
}
|
||||
|
||||
os << "\n - ics with type info: " << ic_with_type_info_count();
|
||||
os << "\n - generic ics: " << ic_generic_count();
|
||||
|
||||
TypeFeedbackMetadataIterator iter(metadata());
|
||||
while (iter.HasNext()) {
|
||||
FeedbackVectorSlot slot = iter.Next();
|
||||
|
@ -72,8 +72,10 @@ static void GetICCounts(SharedFunctionInfo* shared,
|
||||
|
||||
// Harvest vector-ics as well
|
||||
TypeFeedbackVector* vector = shared->feedback_vector();
|
||||
*ic_with_type_info_count += vector->ic_with_type_info_count();
|
||||
*ic_generic_count += vector->ic_generic_count();
|
||||
int with = 0, gen = 0;
|
||||
vector->ComputeCounts(&with, &gen);
|
||||
*ic_with_type_info_count += with;
|
||||
*ic_generic_count += gen;
|
||||
|
||||
if (*ic_total_count > 0) {
|
||||
*type_info_percentage = 100 * *ic_with_type_info_count / *ic_total_count;
|
||||
|
@ -81,35 +81,6 @@ FeedbackVectorSlotKind TypeFeedbackVector::GetKind(
|
||||
}
|
||||
|
||||
|
||||
int TypeFeedbackVector::ic_with_type_info_count() {
|
||||
return length() > 0 ? Smi::cast(get(kWithTypesIndex))->value() : 0;
|
||||
}
|
||||
|
||||
|
||||
void TypeFeedbackVector::change_ic_with_type_info_count(int delta) {
|
||||
if (delta == 0) return;
|
||||
int value = ic_with_type_info_count() + delta;
|
||||
// Could go negative because of the debugger.
|
||||
if (value >= 0) {
|
||||
set(kWithTypesIndex, Smi::FromInt(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int TypeFeedbackVector::ic_generic_count() {
|
||||
return length() > 0 ? Smi::cast(get(kGenericCountIndex))->value() : 0;
|
||||
}
|
||||
|
||||
|
||||
void TypeFeedbackVector::change_ic_generic_count(int delta) {
|
||||
if (delta == 0) return;
|
||||
int value = ic_generic_count() + delta;
|
||||
if (value >= 0) {
|
||||
set(kGenericCountIndex, Smi::FromInt(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int TypeFeedbackVector::GetIndex(FeedbackVectorSlot slot) const {
|
||||
DCHECK(slot.ToInt() < slot_count());
|
||||
return kReservedIndexCount + slot.ToInt();
|
||||
@ -135,6 +106,34 @@ void TypeFeedbackVector::Set(FeedbackVectorSlot slot, Object* value,
|
||||
}
|
||||
|
||||
|
||||
void TypeFeedbackVector::ComputeCounts(int* with_type_info, int* generic) {
|
||||
Object* uninitialized_sentinel =
|
||||
TypeFeedbackVector::RawUninitializedSentinel(GetIsolate());
|
||||
Object* megamorphic_sentinel =
|
||||
*TypeFeedbackVector::MegamorphicSentinel(GetIsolate());
|
||||
int with = 0;
|
||||
int gen = 0;
|
||||
TypeFeedbackMetadataIterator iter(metadata());
|
||||
while (iter.HasNext()) {
|
||||
FeedbackVectorSlot slot = iter.Next();
|
||||
FeedbackVectorSlotKind kind = iter.kind();
|
||||
|
||||
Object* obj = Get(slot);
|
||||
if (obj != uninitialized_sentinel &&
|
||||
kind != FeedbackVectorSlotKind::GENERAL) {
|
||||
if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) {
|
||||
with++;
|
||||
} else if (obj == megamorphic_sentinel) {
|
||||
gen++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*with_type_info = with;
|
||||
*generic = gen;
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> TypeFeedbackVector::UninitializedSentinel(Isolate* isolate) {
|
||||
return isolate->factory()->uninitialized_symbol();
|
||||
}
|
||||
|
@ -140,8 +140,6 @@ Handle<TypeFeedbackVector> TypeFeedbackVector::New(
|
||||
|
||||
Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
|
||||
array->set(kMetadataIndex, *metadata);
|
||||
array->set(kWithTypesIndex, Smi::FromInt(0));
|
||||
array->set(kGenericCountIndex, Smi::FromInt(0));
|
||||
|
||||
// Ensure we can skip the write barrier
|
||||
Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
|
||||
|
@ -182,14 +182,9 @@ class TypeFeedbackVector : public FixedArray {
|
||||
static inline TypeFeedbackVector* cast(Object* obj);
|
||||
|
||||
static const int kMetadataIndex = 0;
|
||||
static const int kWithTypesIndex = 1;
|
||||
static const int kGenericCountIndex = 2;
|
||||
static const int kReservedIndexCount = 3;
|
||||
static const int kReservedIndexCount = 1;
|
||||
|
||||
inline int ic_with_type_info_count();
|
||||
inline void change_ic_with_type_info_count(int delta);
|
||||
inline int ic_generic_count();
|
||||
inline void change_ic_generic_count(int delta);
|
||||
inline void ComputeCounts(int* with_type_info, int* generic);
|
||||
|
||||
inline bool is_empty() const;
|
||||
|
||||
|
@ -1936,10 +1936,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
// -- rbx - vector
|
||||
// -----------------------------------
|
||||
Isolate* isolate = masm->isolate();
|
||||
const int with_types_offset =
|
||||
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
|
||||
const int generic_offset =
|
||||
FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
|
||||
Label extra_checks_or_miss, call, call_function;
|
||||
int argc = arg_count();
|
||||
StackArgumentsAccessor args(rsp, argc);
|
||||
@ -2013,9 +2009,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ j(not_equal, &miss);
|
||||
__ Move(FieldOperand(rbx, rdx, times_pointer_size, FixedArray::kHeaderSize),
|
||||
TypeFeedbackVector::MegamorphicSentinel(isolate));
|
||||
// We have to update statistics for runtime profiling.
|
||||
__ SmiAddConstant(FieldOperand(rbx, with_types_offset), Smi::FromInt(-1));
|
||||
__ SmiAddConstant(FieldOperand(rbx, generic_offset), Smi::FromInt(1));
|
||||
|
||||
__ bind(&call);
|
||||
__ Set(rax, argc);
|
||||
@ -2043,9 +2036,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ cmpp(rcx, NativeContextOperand());
|
||||
__ j(not_equal, &miss);
|
||||
|
||||
// Update stats.
|
||||
__ SmiAddConstant(FieldOperand(rbx, with_types_offset), Smi::FromInt(1));
|
||||
|
||||
// Initialize the call counter.
|
||||
__ Move(FieldOperand(rbx, rdx, times_pointer_size,
|
||||
FixedArray::kHeaderSize + kPointerSize),
|
||||
|
@ -912,91 +912,87 @@ TEST(PropertyLoads) {
|
||||
},
|
||||
1,
|
||||
{"name"}},
|
||||
{
|
||||
"function f(a, b) { \"use strict\"; return a[b]; }\n"
|
||||
"f({arg : \"test\"}, \"arg\")",
|
||||
0,
|
||||
3,
|
||||
6,
|
||||
{
|
||||
B(Ldar), A(2, 3), //
|
||||
B(KeyedLoadICStrict), A(1, 3), U8(vector->GetIndex(slot1)), //
|
||||
B(Return), //
|
||||
},
|
||||
0},
|
||||
{
|
||||
"function f(a) {\n"
|
||||
" var b;\n"
|
||||
REPEAT_127(SPACE, " b = a.name; ")
|
||||
" return a.name; }\n"
|
||||
"f({name : \"test\"})\n",
|
||||
1 * kPointerSize,
|
||||
2,
|
||||
769,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(LoadICSloppy), A(1, 2), U8(0), U8((wide_idx_1 += 2)), //
|
||||
B(Star), R(0)), //
|
||||
B(LoadICSloppyWide), A(1, 2), U16(0), U16(wide_idx_1 + 2), //
|
||||
B(Return), //
|
||||
},
|
||||
1,
|
||||
{"name"}},
|
||||
{
|
||||
"function f(a) {\n"
|
||||
" 'use strict'; var b;\n"
|
||||
REPEAT_127(SPACE, " b = a.name; ")
|
||||
" return a.name; }\n"
|
||||
"f({name : \"test\"})\n",
|
||||
1 * kPointerSize,
|
||||
2,
|
||||
769,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(LoadICStrict), A(1, 2), U8(0), U8((wide_idx_2 += 2)), //
|
||||
B(Star), R(0)), //
|
||||
B(LoadICStrictWide), A(1, 2), U16(0), U16(wide_idx_2 + 2), //
|
||||
B(Return), //
|
||||
},
|
||||
1,
|
||||
{"name"}},
|
||||
{
|
||||
"function f(a, b) {\n"
|
||||
" var c;\n"
|
||||
REPEAT_127(SPACE, " c = a[b]; ")
|
||||
" return a[b]; }\n"
|
||||
"f({name : \"test\"}, \"name\")\n",
|
||||
1 * kPointerSize,
|
||||
3,
|
||||
896,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(Ldar), A(2, 3), //
|
||||
B(KeyedLoadICSloppy), A(1, 3), U8((wide_idx_3 += 2)), //
|
||||
B(Star), R(0)), //
|
||||
B(Ldar), A(2, 3), //
|
||||
B(KeyedLoadICSloppyWide), A(1, 3), U16(wide_idx_3 + 2), //
|
||||
B(Return), //
|
||||
}},
|
||||
{
|
||||
"function f(a, b) {\n"
|
||||
" 'use strict'; var c;\n"
|
||||
REPEAT_127(SPACE, " c = a[b]; ")
|
||||
" return a[b]; }\n"
|
||||
"f({name : \"test\"}, \"name\")\n",
|
||||
1 * kPointerSize,
|
||||
3,
|
||||
896,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(Ldar), A(2, 3), //
|
||||
B(KeyedLoadICStrict), A(1, 3), U8((wide_idx_4 += 2)), //
|
||||
B(Star), R(0)), //
|
||||
B(Ldar), A(2, 3), //
|
||||
B(KeyedLoadICStrictWide), A(1, 3), U16(wide_idx_4 + 2), //
|
||||
B(Return), //
|
||||
}},
|
||||
};
|
||||
{"function f(a, b) { \"use strict\"; return a[b]; }\n"
|
||||
"f({arg : \"test\"}, \"arg\")",
|
||||
0,
|
||||
3,
|
||||
6,
|
||||
{
|
||||
B(Ldar), A(2, 3), //
|
||||
B(KeyedLoadICStrict), A(1, 3), U8(vector->GetIndex(slot1)), //
|
||||
B(Return), //
|
||||
},
|
||||
0},
|
||||
{"function f(a) {\n"
|
||||
" var b;\n" REPEAT_127(SPACE, " b = a.name; ") " return a.name; }\n"
|
||||
"f({name : \"test\"})\n",
|
||||
1 * kPointerSize,
|
||||
2,
|
||||
767,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(LoadICSloppy), A(1, 2), U8(0),
|
||||
U8((wide_idx_1 += 2)), //
|
||||
B(Star), R(0)), //
|
||||
B(LoadICSloppy),
|
||||
A(1, 2), U8(0), U8(wide_idx_1 + 2), //
|
||||
B(Return), //
|
||||
},
|
||||
1,
|
||||
{"name"}},
|
||||
{"function f(a) {\n"
|
||||
" 'use strict'; var b;\n" REPEAT_127(
|
||||
SPACE, " b = a.name; ") " return a.name; }\n"
|
||||
"f({name : \"test\"})\n",
|
||||
1 * kPointerSize,
|
||||
2,
|
||||
767,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(LoadICStrict), A(1, 2), U8(0),
|
||||
U8((wide_idx_2 += 2)), //
|
||||
B(Star), R(0)), //
|
||||
B(LoadICStrict),
|
||||
A(1, 2), U8(0), U8(wide_idx_2 + 2), //
|
||||
B(Return), //
|
||||
},
|
||||
1,
|
||||
{"name"}},
|
||||
{"function f(a, b) {\n"
|
||||
" var c;\n" REPEAT_127(SPACE,
|
||||
" c = a[b]; ") " return a[b]; }\n"
|
||||
"f({name : \"test\"}, \"name\")\n",
|
||||
1 * kPointerSize,
|
||||
3,
|
||||
895,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(Ldar), A(2, 3), //
|
||||
B(KeyedLoadICSloppy), A(1, 3), U8((wide_idx_3 += 2)), //
|
||||
B(Star), R(0)), //
|
||||
B(Ldar),
|
||||
A(2, 3), //
|
||||
B(KeyedLoadICSloppy), A(1, 3), U8(wide_idx_3 + 2), //
|
||||
B(Return), //
|
||||
}},
|
||||
{"function f(a, b) {\n"
|
||||
" 'use strict'; var c;\n" REPEAT_127(
|
||||
SPACE, " c = a[b]; ") " return a[b]; }\n"
|
||||
"f({name : \"test\"}, \"name\")\n",
|
||||
1 * kPointerSize,
|
||||
3,
|
||||
895,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(Ldar), A(2, 3), //
|
||||
B(KeyedLoadICStrict), A(1, 3), U8((wide_idx_4 += 2)), //
|
||||
B(Star), R(0)), //
|
||||
B(Ldar),
|
||||
A(2, 3), //
|
||||
B(KeyedLoadICStrict), A(1, 3), U8(wide_idx_4 + 2), //
|
||||
B(Return), //
|
||||
}},
|
||||
};
|
||||
for (size_t i = 0; i < arraysize(snippets); i++) {
|
||||
Handle<BytecodeArray> bytecode_array =
|
||||
helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName);
|
||||
@ -1053,13 +1049,13 @@ TEST(PropertyStores) {
|
||||
2,
|
||||
12,
|
||||
{
|
||||
B(LdaSmi8), U8(100), //
|
||||
B(Star), R(0), //
|
||||
B(LdaConstant), U8(0), //
|
||||
B(KeyedStoreICSloppy), A(1, 2), R(0), //
|
||||
U8(vector->GetIndex(slot1)), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
B(LdaSmi8), U8(100), //
|
||||
B(Star), R(0), //
|
||||
B(LdaConstant), U8(0), //
|
||||
B(KeyedStoreICSloppy), A(1, 2), R(0), //
|
||||
U8(vector->GetIndex(slot1)), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
},
|
||||
1,
|
||||
{"val"}},
|
||||
@ -1068,11 +1064,11 @@ TEST(PropertyStores) {
|
||||
3,
|
||||
8,
|
||||
{
|
||||
B(LdaConstant), U8(0), //
|
||||
B(KeyedStoreICSloppy), A(1, 3), A(2, 3), //
|
||||
U8(vector->GetIndex(slot1)), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
B(LdaConstant), U8(0), //
|
||||
B(KeyedStoreICSloppy), A(1, 3), A(2, 3), //
|
||||
U8(vector->GetIndex(slot1)), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
},
|
||||
1,
|
||||
{"val"}},
|
||||
@ -1109,87 +1105,89 @@ TEST(PropertyStores) {
|
||||
3,
|
||||
8,
|
||||
{
|
||||
B(LdaConstant), U8(0), //
|
||||
B(KeyedStoreICStrict), A(1, 3), A(2, 3), //
|
||||
U8(vector->GetIndex(slot1)), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
B(LdaConstant), U8(0), //
|
||||
B(KeyedStoreICStrict), A(1, 3), A(2, 3), //
|
||||
U8(vector->GetIndex(slot1)), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
},
|
||||
1,
|
||||
{"val"}},
|
||||
{"function f(a) {\n"
|
||||
REPEAT_127(SPACE, " a.name = 1; ")
|
||||
" a.name = 2; }\n"
|
||||
"f({name : \"test\"})\n",
|
||||
{"function f(a) {\n" REPEAT_127(SPACE,
|
||||
" a.name = 1; ") " a.name = 2; }\n"
|
||||
"f({name : \"test\"})\n",
|
||||
0,
|
||||
2,
|
||||
772,
|
||||
770,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(StoreICSloppy), A(1, 2), U8(0), U8((wide_idx_1 += 2))), //
|
||||
B(LdaSmi8), U8(2), //
|
||||
B(StoreICSloppyWide), A(1, 2), U16(0), U16(wide_idx_1 + 2), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
REPEAT_127(COMMA, //
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(StoreICSloppy), A(1, 2), U8(0),
|
||||
U8((wide_idx_1 += 2))), //
|
||||
B(LdaSmi8),
|
||||
U8(2), //
|
||||
B(StoreICSloppy), A(1, 2), U8(0), U8(wide_idx_1 + 2), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
},
|
||||
1,
|
||||
{"name"}},
|
||||
{"function f(a) {\n"
|
||||
"'use strict';\n"
|
||||
REPEAT_127(SPACE, " a.name = 1; ")
|
||||
" a.name = 2; }\n"
|
||||
"f({name : \"test\"})\n",
|
||||
"'use strict';\n" REPEAT_127(SPACE,
|
||||
" a.name = 1; ") " a.name = 2; }\n"
|
||||
"f({name : \"test\"})\n",
|
||||
0,
|
||||
2,
|
||||
772,
|
||||
770,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(StoreICStrict), A(1, 2), U8(0), U8((wide_idx_2 += 2))), //
|
||||
B(LdaSmi8), U8(2), //
|
||||
B(StoreICStrictWide), A(1, 2), U16(0), U16(wide_idx_2 + 2), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
REPEAT_127(COMMA, //
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(StoreICStrict), A(1, 2), U8(0),
|
||||
U8((wide_idx_2 += 2))), //
|
||||
B(LdaSmi8),
|
||||
U8(2), //
|
||||
B(StoreICStrict), A(1, 2), U8(0), U8(wide_idx_2 + 2), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
},
|
||||
1,
|
||||
{"name"}},
|
||||
{"function f(a, b) {\n"
|
||||
REPEAT_127(SPACE, " a[b] = 1; ")
|
||||
" a[b] = 2; }\n"
|
||||
"f({name : \"test\"})\n",
|
||||
{"function f(a, b) {\n" REPEAT_127(
|
||||
SPACE, " a[b] = 1; ") " a[b] = 2; }\n"
|
||||
"f({name : \"test\"})\n",
|
||||
0,
|
||||
3,
|
||||
771,
|
||||
770,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(KeyedStoreICSloppy), A(1, 3), A(2, 3), //
|
||||
U8((wide_idx_3 += 2))), //
|
||||
B(LdaSmi8), U8(2), //
|
||||
B(KeyedStoreICSloppyWide), A(1, 3), A(2, 3), //
|
||||
U16(wide_idx_3 + 2), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
REPEAT_127(COMMA, //
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(KeyedStoreICSloppy), A(1, 3), A(2, 3), //
|
||||
U8((wide_idx_3 += 2))), //
|
||||
B(LdaSmi8),
|
||||
U8(2), //
|
||||
B(KeyedStoreICSloppy), A(1, 3), A(2, 3), //
|
||||
U8(wide_idx_3 + 2), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
}},
|
||||
{"function f(a, b) {\n"
|
||||
"'use strict';\n"
|
||||
REPEAT_127(SPACE, " a[b] = 1; ")
|
||||
" a[b] = 2; }\n"
|
||||
"f({name : \"test\"})\n",
|
||||
"'use strict';\n" REPEAT_127(SPACE,
|
||||
" a[b] = 1; ") " a[b] = 2; }\n"
|
||||
"f({name : \"test\"})\n",
|
||||
0,
|
||||
3,
|
||||
771,
|
||||
770,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(KeyedStoreICStrict), A(1, 3), A(2, 3), //
|
||||
U8((wide_idx_4 += 2))), //
|
||||
B(LdaSmi8), U8(2), //
|
||||
B(KeyedStoreICStrictWide), A(1, 3), A(2, 3), //
|
||||
U16(wide_idx_4 + 2), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
REPEAT_127(COMMA, //
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(KeyedStoreICStrict), A(1, 3), A(2, 3), //
|
||||
U8((wide_idx_4 += 2))), //
|
||||
B(LdaSmi8),
|
||||
U8(2), //
|
||||
B(KeyedStoreICStrict), A(1, 3), A(2, 3), //
|
||||
U8(wide_idx_4 + 2), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
}}};
|
||||
for (size_t i = 0; i < arraysize(snippets); i++) {
|
||||
Handle<BytecodeArray> bytecode_array =
|
||||
@ -1270,21 +1268,21 @@ TEST(PropertyCall) {
|
||||
},
|
||||
1,
|
||||
{"func"}},
|
||||
{"function f(a) {\n"
|
||||
REPEAT_127(SPACE, " a.func;\n")
|
||||
" return a.func(); }\nf(" FUNC_ARG ")",
|
||||
{"function f(a) {\n" REPEAT_127(
|
||||
SPACE, " a.func;\n") " return a.func(); }\nf(" FUNC_ARG ")",
|
||||
2 * kPointerSize,
|
||||
2,
|
||||
528,
|
||||
526,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(LoadICSloppy), A(1, 2), U8(0), U8((wide_idx += 2))), //
|
||||
B(Ldar), A(1, 2), //
|
||||
B(Star), R(1), //
|
||||
B(LoadICSloppyWide), R(1), U16(0), U16(wide_idx + 4), //
|
||||
B(Star), R(0), //
|
||||
B(CallWide), R(0), R(1), U16(0), U16(wide_idx + 2), //
|
||||
B(Return), //
|
||||
REPEAT_127(COMMA, //
|
||||
B(LoadICSloppy), A(1, 2), U8(0), U8((wide_idx += 2))), //
|
||||
B(Ldar),
|
||||
A(1, 2), //
|
||||
B(Star), R(1), //
|
||||
B(LoadICSloppyWide), R(1), U16(0), U16(wide_idx + 4), //
|
||||
B(Star), R(0), //
|
||||
B(Call), R(0), R(1), U8(0), U8(wide_idx + 2), //
|
||||
B(Return), //
|
||||
},
|
||||
1,
|
||||
{"func"}},
|
||||
@ -1353,32 +1351,32 @@ TEST(LoadGlobal) {
|
||||
},
|
||||
1,
|
||||
{"a"}},
|
||||
{"a = 1; function f(b) {\n"
|
||||
REPEAT_127(SPACE, "b.name; ")
|
||||
" return a; }\nf({name: 1});",
|
||||
{"a = 1; function f(b) {\n" REPEAT_127(
|
||||
SPACE, "b.name; ") " return a; }\nf({name: 1});",
|
||||
0,
|
||||
2,
|
||||
514,
|
||||
512,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(LoadICSloppy), A(1, 2), U8(0), U8(wide_idx_1 += 2)), //
|
||||
B(LdaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2), //
|
||||
B(Return), //
|
||||
REPEAT_127(COMMA, //
|
||||
B(LoadICSloppy), A(1, 2), U8(0), U8(wide_idx_1 += 2)), //
|
||||
B(LdaGlobalSloppy),
|
||||
U8(1), U8(wide_idx_1 + 2), //
|
||||
B(Return), //
|
||||
},
|
||||
2,
|
||||
{"name", "a"}},
|
||||
{"a = 1; function f(b) {\n"
|
||||
" 'use strict';\n"
|
||||
REPEAT_127(SPACE, "b.name; ")
|
||||
" return a; }\nf({name: 1});",
|
||||
" 'use strict';\n" REPEAT_127(SPACE,
|
||||
"b.name; ") " return a; }\nf({name: 1});",
|
||||
0,
|
||||
2,
|
||||
514,
|
||||
512,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(LoadICStrict), A(1, 2), U8(0), U8(wide_idx_2 += 2)), //
|
||||
B(LdaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2), //
|
||||
B(Return), //
|
||||
REPEAT_127(COMMA, //
|
||||
B(LoadICStrict), A(1, 2), U8(0), U8(wide_idx_2 += 2)), //
|
||||
B(LdaGlobalStrict),
|
||||
U8(1), U8(wide_idx_2 + 2), //
|
||||
B(Return), //
|
||||
},
|
||||
2,
|
||||
{"name", "a"}},
|
||||
@ -1456,36 +1454,36 @@ TEST(StoreGlobal) {
|
||||
},
|
||||
1,
|
||||
{"a"}},
|
||||
{"a = 1; function f(b) {\n"
|
||||
REPEAT_127(SPACE, "b.name; ")
|
||||
" a = 2; }\nf({name: 1});",
|
||||
{"a = 1; function f(b) {\n" REPEAT_127(
|
||||
SPACE, "b.name; ") " a = 2; }\nf({name: 1});",
|
||||
0,
|
||||
2,
|
||||
517,
|
||||
515,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(LoadICSloppy), A(1, 2), U8(0), U8(wide_idx_1 += 2)), //
|
||||
B(LdaSmi8), U8(2), //
|
||||
B(StaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
REPEAT_127(COMMA, //
|
||||
B(LoadICSloppy), A(1, 2), U8(0), U8(wide_idx_1 += 2)), //
|
||||
B(LdaSmi8),
|
||||
U8(2), //
|
||||
B(StaGlobalSloppy), U8(1), U8(wide_idx_1 + 2), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
},
|
||||
2,
|
||||
{"name", "a"}},
|
||||
{"a = 1; function f(b) {\n"
|
||||
" 'use strict';\n"
|
||||
REPEAT_127(SPACE, "b.name; ")
|
||||
" a = 2; }\nf({name: 1});",
|
||||
" 'use strict';\n" REPEAT_127(SPACE,
|
||||
"b.name; ") " a = 2; }\nf({name: 1});",
|
||||
0,
|
||||
2,
|
||||
517,
|
||||
515,
|
||||
{
|
||||
REPEAT_127(COMMA, //
|
||||
B(LoadICStrict), A(1, 2), U8(0), U8(wide_idx_2 += 2)), //
|
||||
B(LdaSmi8), U8(2), //
|
||||
B(StaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
REPEAT_127(COMMA, //
|
||||
B(LoadICStrict), A(1, 2), U8(0), U8(wide_idx_2 += 2)), //
|
||||
B(LdaSmi8),
|
||||
U8(2), //
|
||||
B(StaGlobalStrict), U8(1), U8(wide_idx_2 + 2), //
|
||||
B(LdaUndefined), //
|
||||
B(Return), //
|
||||
},
|
||||
2,
|
||||
{"name", "a"}},
|
||||
@ -3399,7 +3397,7 @@ TEST(TopLevelObjectLiterals) {
|
||||
B(CreateObjectLiteral), U8(0), U8(has_function_flags), //
|
||||
B(Star), R(4), //
|
||||
B(CreateClosure), U8(4), U8(1), //
|
||||
B(StoreICSloppy), R(4), U8(3), U8(5), //
|
||||
B(StoreICSloppy), R(4), U8(3), U8(3), //
|
||||
B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), //
|
||||
B(Ldar), R(4), //
|
||||
B(Star), R(3), //
|
||||
|
@ -47,8 +47,6 @@ TEST(VectorStructure) {
|
||||
CHECK(Handle<FixedArray>::cast(vector)
|
||||
.is_identical_to(factory->empty_fixed_array()));
|
||||
// Which can nonetheless be queried.
|
||||
CHECK_EQ(0, vector->ic_with_type_info_count());
|
||||
CHECK_EQ(0, vector->ic_generic_count());
|
||||
CHECK(vector->is_empty());
|
||||
|
||||
{
|
||||
@ -135,8 +133,6 @@ TEST(VectorICMetadata) {
|
||||
|
||||
// Meanwhile set some feedback values and type feedback values to
|
||||
// verify the data structure remains intact.
|
||||
vector->change_ic_with_type_info_count(100);
|
||||
vector->change_ic_generic_count(3333);
|
||||
vector->Set(FeedbackVectorSlot(0), *vector);
|
||||
|
||||
// Verify the metadata is correctly set up from the spec.
|
||||
@ -200,60 +196,6 @@ TEST(VectorSlotClearing) {
|
||||
}
|
||||
|
||||
|
||||
TEST(VectorICProfilerStatistics) {
|
||||
if (i::FLAG_always_opt) return;
|
||||
CcTest::InitializeVM();
|
||||
LocalContext context;
|
||||
v8::HandleScope scope(context->GetIsolate());
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
Heap* heap = isolate->heap();
|
||||
|
||||
// Make sure function f has a call that uses a type feedback slot.
|
||||
CompileRun(
|
||||
"function fun() {};"
|
||||
"function f(a) { a(); } f(fun);");
|
||||
Handle<JSFunction> f = GetFunction("f");
|
||||
// There should be one IC.
|
||||
Handle<Code> code = handle(f->shared()->code(), isolate);
|
||||
TypeFeedbackInfo* feedback_info =
|
||||
TypeFeedbackInfo::cast(code->type_feedback_info());
|
||||
CHECK_EQ(1, feedback_info->ic_total_count());
|
||||
CHECK_EQ(0, feedback_info->ic_with_type_info_count());
|
||||
CHECK_EQ(0, feedback_info->ic_generic_count());
|
||||
Handle<TypeFeedbackVector> feedback_vector =
|
||||
handle(f->shared()->feedback_vector(), isolate);
|
||||
FeedbackVectorHelper helper(feedback_vector);
|
||||
CallICNexus nexus(feedback_vector, helper.slot(0));
|
||||
CHECK_EQ(1, feedback_vector->ic_with_type_info_count());
|
||||
CHECK_EQ(0, feedback_vector->ic_generic_count());
|
||||
|
||||
// Now send the information generic.
|
||||
CompileRun("f(Object);");
|
||||
CHECK_EQ(0, feedback_vector->ic_with_type_info_count());
|
||||
CHECK_EQ(1, feedback_vector->ic_generic_count());
|
||||
|
||||
// A collection will not affect the site.
|
||||
heap->CollectAllGarbage();
|
||||
CHECK_EQ(0, feedback_vector->ic_with_type_info_count());
|
||||
CHECK_EQ(1, feedback_vector->ic_generic_count());
|
||||
|
||||
// The Array function is special. A call to array remains monomorphic
|
||||
// and isn't cleared by gc because an AllocationSite is being held.
|
||||
// Clear the IC manually in order to test this case.
|
||||
nexus.Clear(*code);
|
||||
CompileRun("f(Array);");
|
||||
CHECK_EQ(1, feedback_vector->ic_with_type_info_count());
|
||||
CHECK_EQ(0, feedback_vector->ic_generic_count());
|
||||
|
||||
|
||||
CHECK(nexus.GetFeedback()->IsAllocationSite());
|
||||
heap->CollectAllGarbage();
|
||||
CHECK_EQ(1, feedback_vector->ic_with_type_info_count());
|
||||
CHECK_EQ(0, feedback_vector->ic_generic_count());
|
||||
CHECK(nexus.GetFeedback()->IsAllocationSite());
|
||||
}
|
||||
|
||||
|
||||
TEST(VectorCallICStates) {
|
||||
if (i::FLAG_always_opt) return;
|
||||
CcTest::InitializeVM();
|
||||
|
Loading…
Reference in New Issue
Block a user