Add code age subtype tracking to --track-gc-object-stats
authorhpayer@chromium.org <hpayer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 24 Oct 2013 10:50:35 +0000 (10:50 +0000)
committerhpayer@chromium.org <hpayer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 24 Oct 2013 10:50:35 +0000 (10:50 +0000)
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 <rmcilroy@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17369 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

12 files changed:
src/arm/codegen-arm.cc
src/builtins.h
src/heap.cc
src/heap.h
src/ia32/codegen-ia32.cc
src/mark-compact.cc
src/mips/codegen-mips.cc
src/objects.cc
src/objects.h
src/v8-counters.cc
src/v8-counters.h
src/x64/codegen-x64.cc

index 717f286..44c331b 100644 (file)
@@ -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 {
index c1c8a5d..9b589d8 100644 (file)
@@ -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)          \
index 1c55c60..33ee5f3 100644 (file)
@@ -7937,6 +7937,18 @@ void Heap::CheckpointObjectStats() {
       static_cast<int>(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<int>(object_counts_[index]));             \
+  counters->count_of_CODE_AGE_##name()->Decrement(          \
+      static_cast<int>(object_counts_last_time_[index]));   \
+  counters->size_of_CODE_AGE_##name()->Increment(           \
+      static_cast<int>(object_sizes_[index]));              \
+  counters->size_of_CODE_AGE_##name()->Decrement(          \
+      static_cast<int>(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_));
index 92e8089..deb1e26 100644 (file)
@@ -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();
index 226b6b0..d09a85f 100644 (file)
@@ -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 {
index 8ec1e4b..b75ddb3 100644 (file)
@@ -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());
     }
index fb250fa..ec66495 100644 (file)
@@ -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 {
index feca669..944bfa6 100644 (file)
@@ -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;
index 431f8b8..267ef13 100644 (file)
@@ -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,
index 6711c80..a0c3ebd 100644 (file)
@@ -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
 }
 
 
index 04f57f7..476021c 100644 (file)
@@ -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);
index 2002608..8ef577f 100644 (file)
@@ -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 {