From 2b63d6b079540d51489ab38c1d769a842576fe9b Mon Sep 17 00:00:00 2001 From: mvstanton Date: Wed, 9 Dec 2015 00:32:56 -0800 Subject: [PATCH] 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} --- src/arm/code-stubs-arm.cc | 16 - src/arm64/code-stubs-arm64.cc | 16 - src/ia32/code-stubs-ia32.cc | 10 - src/ic/ic.cc | 41 +- src/ic/ic.h | 4 +- src/mips/code-stubs-mips.cc | 16 - src/mips64/code-stubs-mips64.cc | 16 - src/objects-printer.cc | 3 - src/runtime-profiler.cc | 6 +- src/type-feedback-vector-inl.h | 57 ++- src/type-feedback-vector.cc | 2 - src/type-feedback-vector.h | 9 +- src/x64/code-stubs-x64.cc | 10 - .../interpreter/test-bytecode-generator.cc | 404 +++++++++--------- test/cctest/test-feedback-vector.cc | 58 --- 15 files changed, 247 insertions(+), 421 deletions(-) diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index b517437fcd..971e67004e 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -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)); diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc index f4cf4705fd..f0bc691e83 100644 --- a/src/arm64/code-stubs-arm64.cc +++ b/src/arm64/code-stubs-arm64.cc @@ -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, diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index 70ac4562e4..6c7420e84f 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -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), diff --git a/src/ic/ic.cc b/src/ic/ic.cc index dd9b0f10ab..7062a5c3dc 100644 --- a/src/ic/ic.cc +++ b/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, Handle 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, 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 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); } diff --git a/src/ic/ic.h b/src/ic/ic.h index 3abc4b6e4f..a3265d70b9 100644 --- a/src/ic/ic.h +++ b/src/ic/ic.h @@ -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. diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index cefe97c8a5..476f82eaf8 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -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)); diff --git a/src/mips64/code-stubs-mips64.cc b/src/mips64/code-stubs-mips64.cc index 86d0e6ef9b..9649e420d8 100644 --- a/src/mips64/code-stubs-mips64.cc +++ b/src/mips64/code-stubs-mips64.cc @@ -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)); diff --git a/src/objects-printer.cc b/src/objects-printer.cc index ea5dec8e71..42d78882a3 100644 --- a/src/objects-printer.cc +++ b/src/objects-printer.cc @@ -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(); diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc index c2254207fe..2d4ee9c1a8 100644 --- a/src/runtime-profiler.cc +++ b/src/runtime-profiler.cc @@ -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; diff --git a/src/type-feedback-vector-inl.h b/src/type-feedback-vector-inl.h index fed28b671e..97df1b9ae9 100644 --- a/src/type-feedback-vector-inl.h +++ b/src/type-feedback-vector-inl.h @@ -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 TypeFeedbackVector::UninitializedSentinel(Isolate* isolate) { return isolate->factory()->uninitialized_symbol(); } diff --git a/src/type-feedback-vector.cc b/src/type-feedback-vector.cc index 7b7b434f56..4d637089d7 100644 --- a/src/type-feedback-vector.cc +++ b/src/type-feedback-vector.cc @@ -140,8 +140,6 @@ Handle TypeFeedbackVector::New( Handle 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 uninitialized_sentinel = UninitializedSentinel(isolate); diff --git a/src/type-feedback-vector.h b/src/type-feedback-vector.h index 05dfff7dba..80267a4d54 100644 --- a/src/type-feedback-vector.h +++ b/src/type-feedback-vector.h @@ -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; diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index cd1266701a..a97e7ecaae 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -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), diff --git a/test/cctest/interpreter/test-bytecode-generator.cc b/test/cctest/interpreter/test-bytecode-generator.cc index 673766d698..436c45f61a 100644 --- a/test/cctest/interpreter/test-bytecode-generator.cc +++ b/test/cctest/interpreter/test-bytecode-generator.cc @@ -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 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 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), // diff --git a/test/cctest/test-feedback-vector.cc b/test/cctest/test-feedback-vector.cc index 719c87d15b..755f3c1ac5 100644 --- a/test/cctest/test-feedback-vector.cc +++ b/test/cctest/test-feedback-vector.cc @@ -47,8 +47,6 @@ TEST(VectorStructure) { CHECK(Handle::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 f = GetFunction("f"); - // There should be one IC. - Handle 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 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();