From 2dfaf2aab536cc32c844679ab0d6cb29a82066be Mon Sep 17 00:00:00 2001 From: "hpayer@chromium.org" Date: Thu, 24 Oct 2013 10:50:35 +0000 Subject: [PATCH] Add code age subtype tracking to --track-gc-object-stats Adds counters which track the age of code in the heap during a gc if --track-gc-object-stats is enabled. - Splits RecordObjectStats into RecordObjectStats, RecordCodeSubTypeStats and RecordFixedArraySubTypeStats. - Renames kNoAge to kNoAgeCodeAge to follow other code age enums and enable the name to be used in Macro based initialization of the counters. BUG=None R=hpayer@chromium.org Review URL: https://codereview.chromium.org/26179004 Patch from Ross McIlroy . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17369 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/codegen-arm.cc | 4 ++-- src/builtins.h | 4 ++++ src/heap.cc | 12 ++++++++++++ src/heap.h | 38 +++++++++++++++++++++----------------- src/ia32/codegen-ia32.cc | 4 ++-- src/mark-compact.cc | 41 +++++++++++++++++------------------------ src/mips/codegen-mips.cc | 4 ++-- src/objects.cc | 4 ++-- src/objects.h | 2 +- src/v8-counters.cc | 8 ++++++++ src/v8-counters.h | 18 ++++++++++++++++++ src/x64/codegen-x64.cc | 4 ++-- 12 files changed, 91 insertions(+), 52 deletions(-) diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index 717f286..44c331b 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -871,7 +871,7 @@ bool Code::IsYoungSequence(byte* sequence) { void Code::GetCodeAgeAndParity(byte* sequence, Age* age, MarkingParity* parity) { if (IsYoungSequence(sequence)) { - *age = kNoAge; + *age = kNoAgeCodeAge; *parity = NO_MARKING_PARITY; } else { Address target_address = Memory::Address_at( @@ -888,7 +888,7 @@ void Code::PatchPlatformCodeAge(Isolate* isolate, MarkingParity parity) { uint32_t young_length; byte* young_sequence = GetNoCodeAgeSequence(&young_length); - if (age == kNoAge) { + if (age == kNoAgeCodeAge) { CopyBytes(sequence, young_sequence, young_length); CPU::FlushICache(sequence, young_length); } else { diff --git a/src/builtins.h b/src/builtins.h index c1c8a5d..9b589d8 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -50,6 +50,10 @@ enum BuiltinExtraArguments { #define CODE_AGE_LIST(V) \ CODE_AGE_LIST_WITH_ARG(CODE_AGE_LIST_IGNORE_ARG, V) +#define CODE_AGE_LIST_WITH_NO_AGE(V) \ + V(NoAge) \ + CODE_AGE_LIST_WITH_ARG(CODE_AGE_LIST_IGNORE_ARG, V) + #define DECLARE_CODE_AGE_BUILTIN(C, V) \ V(Make##C##CodeYoungAgainOddMarking, BUILTIN, \ UNINITIALIZED, Code::kNoExtraICState) \ diff --git a/src/heap.cc b/src/heap.cc index 1c55c60..33ee5f3 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -7937,6 +7937,18 @@ void Heap::CheckpointObjectStats() { static_cast(object_sizes_last_time_[index])); FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) #undef ADJUST_LAST_TIME_OBJECT_COUNT +#define ADJUST_LAST_TIME_OBJECT_COUNT(name) \ + index = FIRST_CODE_AGE_SUB_TYPE + Code::k##name##CodeAge; \ + counters->count_of_CODE_AGE_##name()->Increment( \ + static_cast(object_counts_[index])); \ + counters->count_of_CODE_AGE_##name()->Decrement( \ + static_cast(object_counts_last_time_[index])); \ + counters->size_of_CODE_AGE_##name()->Increment( \ + static_cast(object_sizes_[index])); \ + counters->size_of_CODE_AGE_##name()->Decrement( \ + static_cast(object_sizes_last_time_[index])); + CODE_AGE_LIST_WITH_NO_AGE(ADJUST_LAST_TIME_OBJECT_COUNT) +#undef ADJUST_LAST_TIME_OBJECT_COUNT OS::MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); OS::MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); diff --git a/src/heap.h b/src/heap.h index 92e8089..deb1e26 100644 --- a/src/heap.h +++ b/src/heap.h @@ -1810,26 +1810,30 @@ class Heap { FIRST_CODE_KIND_SUB_TYPE = LAST_TYPE + 1, FIRST_FIXED_ARRAY_SUB_TYPE = FIRST_CODE_KIND_SUB_TYPE + Code::NUMBER_OF_KINDS, - OBJECT_STATS_COUNT = - FIRST_FIXED_ARRAY_SUB_TYPE + LAST_FIXED_ARRAY_SUB_TYPE + 1 + FIRST_CODE_AGE_SUB_TYPE = + FIRST_FIXED_ARRAY_SUB_TYPE + LAST_FIXED_ARRAY_SUB_TYPE + 1, + OBJECT_STATS_COUNT = FIRST_CODE_AGE_SUB_TYPE + Code::kLastCodeAge + 1 }; - void RecordObjectStats(InstanceType type, int sub_type, size_t size) { + void RecordObjectStats(InstanceType type, size_t size) { ASSERT(type <= LAST_TYPE); - if (sub_type < 0) { - object_counts_[type]++; - object_sizes_[type] += size; - } else { - if (type == CODE_TYPE) { - ASSERT(sub_type < Code::NUMBER_OF_KINDS); - object_counts_[FIRST_CODE_KIND_SUB_TYPE + sub_type]++; - object_sizes_[FIRST_CODE_KIND_SUB_TYPE + sub_type] += size; - } else if (type == FIXED_ARRAY_TYPE) { - ASSERT(sub_type <= LAST_FIXED_ARRAY_SUB_TYPE); - object_counts_[FIRST_FIXED_ARRAY_SUB_TYPE + sub_type]++; - object_sizes_[FIRST_FIXED_ARRAY_SUB_TYPE + sub_type] += size; - } - } + object_counts_[type]++; + object_sizes_[type] += size; + } + + void RecordCodeSubTypeStats(int code_sub_type, int code_age, size_t size) { + ASSERT(code_sub_type < Code::NUMBER_OF_KINDS); + ASSERT(code_age < Code::kLastCodeAge); + object_counts_[FIRST_CODE_KIND_SUB_TYPE + code_sub_type]++; + object_sizes_[FIRST_CODE_KIND_SUB_TYPE + code_sub_type] += size; + object_counts_[FIRST_CODE_AGE_SUB_TYPE + code_age]++; + object_sizes_[FIRST_CODE_AGE_SUB_TYPE + code_age] += size; + } + + void RecordFixedArraySubTypeStats(int array_sub_type, size_t size) { + ASSERT(array_sub_type <= LAST_FIXED_ARRAY_SUB_TYPE); + object_counts_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type]++; + object_sizes_[FIRST_FIXED_ARRAY_SUB_TYPE + array_sub_type] += size; } void CheckpointObjectStats(); diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index 226b6b0..d09a85f 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -1149,7 +1149,7 @@ bool Code::IsYoungSequence(byte* sequence) { void Code::GetCodeAgeAndParity(byte* sequence, Age* age, MarkingParity* parity) { if (IsYoungSequence(sequence)) { - *age = kNoAge; + *age = kNoAgeCodeAge; *parity = NO_MARKING_PARITY; } else { sequence++; // Skip the kCallOpcode byte @@ -1167,7 +1167,7 @@ void Code::PatchPlatformCodeAge(Isolate* isolate, MarkingParity parity) { uint32_t young_length; byte* young_sequence = GetNoCodeAgeSequence(&young_length); - if (age == kNoAge) { + if (age == kNoAgeCodeAge) { CopyBytes(sequence, young_sequence, young_length); CPU::FlushICache(sequence, young_length); } else { diff --git a/src/mark-compact.cc b/src/mark-compact.cc index 8ec1e4b..b75ddb3 100644 --- a/src/mark-compact.cc +++ b/src/mark-compact.cc @@ -1570,13 +1570,11 @@ void MarkCompactMarkingVisitor::ObjectStatsCountFixedArray( fixed_array->map() != heap->fixed_double_array_map() && fixed_array != heap->empty_fixed_array()) { if (fixed_array->IsDictionary()) { - heap->RecordObjectStats(FIXED_ARRAY_TYPE, - dictionary_type, - fixed_array->Size()); + heap->RecordFixedArraySubTypeStats(dictionary_type, + fixed_array->Size()); } else { - heap->RecordObjectStats(FIXED_ARRAY_TYPE, - fast_type, - fixed_array->Size()); + heap->RecordFixedArraySubTypeStats(fast_type, + fixed_array->Size()); } } } @@ -1586,7 +1584,7 @@ void MarkCompactMarkingVisitor::ObjectStatsVisitBase( MarkCompactMarkingVisitor::VisitorId id, Map* map, HeapObject* obj) { Heap* heap = map->GetHeap(); int object_size = obj->Size(); - heap->RecordObjectStats(map->instance_type(), -1, object_size); + heap->RecordObjectStats(map->instance_type(), object_size); non_count_table_.GetVisitorById(id)(map, obj); if (obj->IsJSObject()) { JSObject* object = JSObject::cast(obj); @@ -1619,25 +1617,20 @@ class MarkCompactMarkingVisitor::ObjectStatsTracker< if (map_obj->owns_descriptors() && array != heap->empty_descriptor_array()) { int fixed_array_size = array->Size(); - heap->RecordObjectStats(FIXED_ARRAY_TYPE, - DESCRIPTOR_ARRAY_SUB_TYPE, - fixed_array_size); + heap->RecordFixedArraySubTypeStats(DESCRIPTOR_ARRAY_SUB_TYPE, + fixed_array_size); } if (map_obj->HasTransitionArray()) { int fixed_array_size = map_obj->transitions()->Size(); - heap->RecordObjectStats(FIXED_ARRAY_TYPE, - TRANSITION_ARRAY_SUB_TYPE, - fixed_array_size); + heap->RecordFixedArraySubTypeStats(TRANSITION_ARRAY_SUB_TYPE, + fixed_array_size); } if (map_obj->has_code_cache()) { CodeCache* cache = CodeCache::cast(map_obj->code_cache()); - heap->RecordObjectStats( - FIXED_ARRAY_TYPE, - MAP_CODE_CACHE_SUB_TYPE, - cache->default_cache()->Size()); + heap->RecordFixedArraySubTypeStats(MAP_CODE_CACHE_SUB_TYPE, + cache->default_cache()->Size()); if (!cache->normal_type_cache()->IsUndefined()) { - heap->RecordObjectStats( - FIXED_ARRAY_TYPE, + heap->RecordFixedArraySubTypeStats( MAP_CODE_CACHE_SUB_TYPE, FixedArray::cast(cache->normal_type_cache())->Size()); } @@ -1655,7 +1648,9 @@ class MarkCompactMarkingVisitor::ObjectStatsTracker< Heap* heap = map->GetHeap(); int object_size = obj->Size(); ASSERT(map->instance_type() == CODE_TYPE); - heap->RecordObjectStats(CODE_TYPE, Code::cast(obj)->kind(), object_size); + Code* code_obj = Code::cast(obj); + heap->RecordCodeSubTypeStats(code_obj->kind(), code_obj->GetAge(), + object_size); ObjectStatsVisitBase(kVisitCode, map, obj); } }; @@ -1669,8 +1664,7 @@ class MarkCompactMarkingVisitor::ObjectStatsTracker< Heap* heap = map->GetHeap(); SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj); if (sfi->scope_info() != heap->empty_fixed_array()) { - heap->RecordObjectStats( - FIXED_ARRAY_TYPE, + heap->RecordFixedArraySubTypeStats( SCOPE_INFO_SUB_TYPE, FixedArray::cast(sfi->scope_info())->Size()); } @@ -1687,8 +1681,7 @@ class MarkCompactMarkingVisitor::ObjectStatsTracker< Heap* heap = map->GetHeap(); FixedArray* fixed_array = FixedArray::cast(obj); if (fixed_array == heap->string_table()) { - heap->RecordObjectStats( - FIXED_ARRAY_TYPE, + heap->RecordFixedArraySubTypeStats( STRING_TABLE_SUB_TYPE, fixed_array->Size()); } diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc index fb250fa..ec66495 100644 --- a/src/mips/codegen-mips.cc +++ b/src/mips/codegen-mips.cc @@ -638,7 +638,7 @@ bool Code::IsYoungSequence(byte* sequence) { void Code::GetCodeAgeAndParity(byte* sequence, Age* age, MarkingParity* parity) { if (IsYoungSequence(sequence)) { - *age = kNoAge; + *age = kNoAgeCodeAge; *parity = NO_MARKING_PARITY; } else { Address target_address = Memory::Address_at( @@ -655,7 +655,7 @@ void Code::PatchPlatformCodeAge(Isolate* isolate, MarkingParity parity) { uint32_t young_length; byte* young_sequence = GetNoCodeAgeSequence(&young_length); - if (age == kNoAge) { + if (age == kNoAgeCodeAge) { CopyBytes(sequence, young_sequence, young_length); CPU::FlushICache(sequence, young_length); } else { diff --git a/src/objects.cc b/src/objects.cc index feca669..944bfa6 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -10609,7 +10609,7 @@ BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) { void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) { - PatchPlatformCodeAge(isolate, sequence, kNoAge, NO_MARKING_PARITY); + PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY); } @@ -10654,7 +10654,7 @@ byte* Code::FindCodeAgeSequence() { Code::Age Code::GetAge() { byte* sequence = FindCodeAgeSequence(); if (sequence == NULL) { - return Code::kNoAge; + return Code::kNoAgeCodeAge; } Age age; MarkingParity parity; diff --git a/src/objects.h b/src/objects.h index 431f8b8..267ef13 100644 --- a/src/objects.h +++ b/src/objects.h @@ -5301,7 +5301,7 @@ class Code: public HeapObject { enum Age { kNotExecutedCodeAge = -2, kExecutedOnceCodeAge = -1, - kNoAge = 0, + kNoAgeCodeAge = 0, CODE_AGE_LIST(DECLARE_CODE_AGE_ENUM) kAfterLastCodeAge, kLastCodeAge = kAfterLastCodeAge - 1, diff --git a/src/v8-counters.cc b/src/v8-counters.cc index 6711c80..a0c3ebd 100644 --- a/src/v8-counters.cc +++ b/src/v8-counters.cc @@ -76,6 +76,14 @@ Counters::Counters(Isolate* isolate) { StatsCounter(isolate, "c:" "V8.SizeOf_FIXED_ARRAY-" #name); FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(SC) #undef SC + +#define SC(name) \ + count_of_CODE_AGE_##name##_ = \ + StatsCounter(isolate, "c:" "V8.CountOf_CODE_AGE-" #name); \ + size_of_CODE_AGE_##name##_ = \ + StatsCounter(isolate, "c:" "V8.SizeOf_CODE_AGE-" #name); + CODE_AGE_LIST_WITH_NO_AGE(SC) +#undef SC } diff --git a/src/v8-counters.h b/src/v8-counters.h index 04f57f7..476021c 100644 --- a/src/v8-counters.h +++ b/src/v8-counters.h @@ -336,6 +336,14 @@ class Counters { FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(SC) #undef SC +#define SC(name) \ + StatsCounter* count_of_CODE_AGE_##name() \ + { return &count_of_CODE_AGE_##name##_; } \ + StatsCounter* size_of_CODE_AGE_##name() \ + { return &size_of_CODE_AGE_##name##_; } + CODE_AGE_LIST_WITH_NO_AGE(SC) +#undef SC + enum Id { #define RATE_ID(name, caption) k_##name, HISTOGRAM_TIMER_LIST(RATE_ID) @@ -361,6 +369,10 @@ class Counters { kSizeOfFIXED_ARRAY__##name, FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(COUNTER_ID) #undef COUNTER_ID +#define COUNTER_ID(name) kCountOfCODE_AGE__##name, \ + kSizeOfCODE_AGE__##name, + CODE_AGE_LIST_WITH_NO_AGE(COUNTER_ID) +#undef COUNTER_ID stats_counter_count }; @@ -406,6 +418,12 @@ class Counters { FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(SC) #undef SC +#define SC(name) \ + StatsCounter size_of_CODE_AGE_##name##_; \ + StatsCounter count_of_CODE_AGE_##name##_; + CODE_AGE_LIST_WITH_NO_AGE(SC) +#undef SC + friend class Isolate; explicit Counters(Isolate* isolate); diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index 2002608..8ef577f 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -706,7 +706,7 @@ bool Code::IsYoungSequence(byte* sequence) { void Code::GetCodeAgeAndParity(byte* sequence, Age* age, MarkingParity* parity) { if (IsYoungSequence(sequence)) { - *age = kNoAge; + *age = kNoAgeCodeAge; *parity = NO_MARKING_PARITY; } else { sequence++; // Skip the kCallOpcode byte @@ -724,7 +724,7 @@ void Code::PatchPlatformCodeAge(Isolate* isolate, MarkingParity parity) { uint32_t young_length; byte* young_sequence = GetNoCodeAgeSequence(&young_length); - if (age == kNoAge) { + if (age == kNoAgeCodeAge) { CopyBytes(sequence, young_sequence, young_length); CPU::FlushICache(sequence, young_length); } else { -- 2.7.4