Commit 1ab272ab authored by danno@chromium.org's avatar danno@chromium.org

Track counts/sizes of CODE sub types with --track-gc-object-stats

R=mstarzinger@chromium.org

Review URL: https://chromiumcodereview.appspot.com/10792014

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12104 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 6744e6e9
...@@ -7211,6 +7211,18 @@ void Heap::CheckpointObjectStats() { ...@@ -7211,6 +7211,18 @@ void Heap::CheckpointObjectStats() {
static_cast<int>(object_sizes_last_time_[name])); static_cast<int>(object_sizes_last_time_[name]));
INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT) INSTANCE_TYPE_LIST(ADJUST_LAST_TIME_OBJECT_COUNT)
#undef ADJUST_LAST_TIME_OBJECT_COUNT #undef ADJUST_LAST_TIME_OBJECT_COUNT
#define ADJUST_LAST_TIME_OBJECT_COUNT(name) \
counters->count_of_CODE_TYPE_##name()->Increment( \
object_counts_[FIRST_CODE_KIND_SUB_TYPE + Code::name]); \
counters->count_of_CODE_TYPE_##name()->Decrement( \
object_counts_last_time_[FIRST_CODE_KIND_SUB_TYPE + Code::name]); \
counters->size_of_CODE_TYPE_##name()->Increment( \
object_sizes_[FIRST_CODE_KIND_SUB_TYPE + Code::name]); \
counters->size_of_CODE_TYPE_##name()->Decrement( \
object_sizes_last_time_[FIRST_CODE_KIND_SUB_TYPE + Code::name]);
CODE_KIND_LIST(ADJUST_LAST_TIME_OBJECT_COUNT)
#undef ADJUST_LAST_TIME_OBJECT_COUNT
memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); memcpy(object_counts_last_time_, object_counts_, sizeof(object_counts_));
memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); memcpy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_));
ClearObjectStats(); ClearObjectStats();
......
...@@ -1596,10 +1596,26 @@ class Heap { ...@@ -1596,10 +1596,26 @@ class Heap {
global_ic_age_ = (global_ic_age_ + 1) & SharedFunctionInfo::ICAgeBits::kMax; global_ic_age_ = (global_ic_age_ + 1) & SharedFunctionInfo::ICAgeBits::kMax;
} }
void RecordObjectStats(InstanceType type, size_t size) { // ObjectStats are kept in two arrays, counts and sizes. Related stats are
// stored in a contiguous linear buffer. Stats groups are stored one after
// another.
enum {
FIRST_CODE_KIND_SUB_TYPE = LAST_TYPE + 1,
OBJECT_STATS_COUNT = FIRST_CODE_KIND_SUB_TYPE + Code::LAST_CODE_KIND + 1
};
void RecordObjectStats(InstanceType type, int sub_type, size_t size) {
ASSERT(type <= LAST_TYPE); ASSERT(type <= LAST_TYPE);
object_counts_[type]++; if (sub_type < 0) {
object_sizes_[type] += size; object_counts_[type]++;
object_sizes_[type] += size;
} else {
if (type == CODE_TYPE) {
ASSERT(sub_type <= Code::LAST_CODE_KIND);
object_counts_[FIRST_CODE_KIND_SUB_TYPE + sub_type]++;
object_sizes_[FIRST_CODE_KIND_SUB_TYPE + sub_type] += size;
}
}
} }
void CheckpointObjectStats(); void CheckpointObjectStats();
...@@ -2004,10 +2020,10 @@ class Heap { ...@@ -2004,10 +2020,10 @@ class Heap {
static const int kInitialNumberStringCacheSize = 256; static const int kInitialNumberStringCacheSize = 256;
// Object counts and used memory by InstanceType // Object counts and used memory by InstanceType
size_t object_counts_[LAST_TYPE + 1]; size_t object_counts_[OBJECT_STATS_COUNT];
size_t object_counts_last_time_[LAST_TYPE + 1]; size_t object_counts_last_time_[OBJECT_STATS_COUNT];
size_t object_sizes_[LAST_TYPE + 1]; size_t object_sizes_[OBJECT_STATS_COUNT];
size_t object_sizes_last_time_[LAST_TYPE + 1]; size_t object_sizes_last_time_[OBJECT_STATS_COUNT];
// Maximum GC pause. // Maximum GC pause.
int max_gc_pause_; int max_gc_pause_;
......
...@@ -947,92 +947,10 @@ class StaticMarkingVisitor : public StaticVisitorBase { ...@@ -947,92 +947,10 @@ class StaticMarkingVisitor : public StaticVisitorBase {
template<int id> template<int id>
class ObjectStatsTracker { class ObjectStatsTracker {
public: public:
static inline void Visit(Map* map, HeapObject* obj) { static inline void Visit(Map* map, HeapObject* obj);
Heap* heap = map->GetHeap();
int object_size = obj->Size();
heap->RecordObjectStats(map->instance_type(), object_size);
non_count_table_.GetVisitorById(static_cast<VisitorId>(id))(map, obj);
}
}; };
static void Initialize() { static void Initialize();
table_.Register(kVisitShortcutCandidate,
&FixedBodyVisitor<StaticMarkingVisitor,
ConsString::BodyDescriptor,
void>::Visit);
table_.Register(kVisitConsString,
&FixedBodyVisitor<StaticMarkingVisitor,
ConsString::BodyDescriptor,
void>::Visit);
table_.Register(kVisitSlicedString,
&FixedBodyVisitor<StaticMarkingVisitor,
SlicedString::BodyDescriptor,
void>::Visit);
table_.Register(kVisitFixedArray,
&FlexibleBodyVisitor<StaticMarkingVisitor,
FixedArray::BodyDescriptor,
void>::Visit);
table_.Register(kVisitGlobalContext, &VisitGlobalContext);
table_.Register(kVisitFixedDoubleArray, DataObjectVisitor::Visit);
table_.Register(kVisitByteArray, &DataObjectVisitor::Visit);
table_.Register(kVisitFreeSpace, &DataObjectVisitor::Visit);
table_.Register(kVisitSeqAsciiString, &DataObjectVisitor::Visit);
table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit);
table_.Register(kVisitJSWeakMap, &VisitJSWeakMap);
table_.Register(kVisitOddball,
&FixedBodyVisitor<StaticMarkingVisitor,
Oddball::BodyDescriptor,
void>::Visit);
table_.Register(kVisitMap,
&FixedBodyVisitor<StaticMarkingVisitor,
Map::BodyDescriptor,
void>::Visit);
table_.Register(kVisitCode, &VisitCode);
table_.Register(kVisitSharedFunctionInfo,
&VisitSharedFunctionInfoAndFlushCode);
table_.Register(kVisitJSFunction,
&VisitJSFunctionAndFlushCode);
table_.Register(kVisitJSRegExp,
&VisitRegExpAndFlushCode);
table_.Register(kVisitPropertyCell,
&FixedBodyVisitor<StaticMarkingVisitor,
JSGlobalPropertyCell::BodyDescriptor,
void>::Visit);
table_.RegisterSpecializations<DataObjectVisitor,
kVisitDataObject,
kVisitDataObjectGeneric>();
table_.RegisterSpecializations<JSObjectVisitor,
kVisitJSObject,
kVisitJSObjectGeneric>();
table_.RegisterSpecializations<StructObjectVisitor,
kVisitStruct,
kVisitStructGeneric>();
if (FLAG_track_gc_object_stats) {
// Copy the visitor table to make call-through possible.
non_count_table_.CopyFrom(&table_);
#define VISITOR_ID_COUNT_FUNCTION(id)\
table_.Register(kVisit##id, ObjectStatsTracker<kVisit##id>::Visit);
VISITOR_ID_LIST(VISITOR_ID_COUNT_FUNCTION)
#undef VISITOR_ID_COUNT_FUNCTION
}
}
INLINE(static void VisitPointer(Heap* heap, Object** p)) { INLINE(static void VisitPointer(Heap* heap, Object** p)) {
MarkObjectByPointer(heap->mark_compact_collector(), p, p); MarkObjectByPointer(heap->mark_compact_collector(), p, p);
...@@ -1581,6 +1499,112 @@ class StaticMarkingVisitor : public StaticVisitorBase { ...@@ -1581,6 +1499,112 @@ class StaticMarkingVisitor : public StaticVisitorBase {
}; };
template<int id>
void StaticMarkingVisitor::ObjectStatsTracker<id>::Visit(
Map* map, HeapObject* obj) {
Heap* heap = map->GetHeap();
int object_size = obj->Size();
heap->RecordObjectStats(map->instance_type(), -1, object_size);
non_count_table_.GetVisitorById(static_cast<VisitorId>(id))(map, obj);
}
template<>
class StaticMarkingVisitor::ObjectStatsTracker<
StaticMarkingVisitor::kVisitCode> {
public:
static inline void Visit(Map* map, HeapObject* obj) {
Heap* heap = map->GetHeap();
int object_size = obj->Size();
ASSERT(map->instance_type() == CODE_TYPE);
heap->RecordObjectStats(CODE_TYPE, -1, object_size);
heap->RecordObjectStats(CODE_TYPE, Code::cast(obj)->kind(), object_size);
non_count_table_.GetVisitorById(
static_cast<VisitorId>(kVisitCode))(map, obj);
}
};
void StaticMarkingVisitor::Initialize() {
table_.Register(kVisitShortcutCandidate,
&FixedBodyVisitor<StaticMarkingVisitor,
ConsString::BodyDescriptor,
void>::Visit);
table_.Register(kVisitConsString,
&FixedBodyVisitor<StaticMarkingVisitor,
ConsString::BodyDescriptor,
void>::Visit);
table_.Register(kVisitSlicedString,
&FixedBodyVisitor<StaticMarkingVisitor,
SlicedString::BodyDescriptor,
void>::Visit);
table_.Register(kVisitFixedArray,
&FlexibleBodyVisitor<StaticMarkingVisitor,
FixedArray::BodyDescriptor,
void>::Visit);
table_.Register(kVisitGlobalContext, &VisitGlobalContext);
table_.Register(kVisitFixedDoubleArray, DataObjectVisitor::Visit);
table_.Register(kVisitByteArray, &DataObjectVisitor::Visit);
table_.Register(kVisitFreeSpace, &DataObjectVisitor::Visit);
table_.Register(kVisitSeqAsciiString, &DataObjectVisitor::Visit);
table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit);
table_.Register(kVisitJSWeakMap, &VisitJSWeakMap);
table_.Register(kVisitOddball,
&FixedBodyVisitor<StaticMarkingVisitor,
Oddball::BodyDescriptor,
void>::Visit);
table_.Register(kVisitMap,
&FixedBodyVisitor<StaticMarkingVisitor,
Map::BodyDescriptor,
void>::Visit);
table_.Register(kVisitCode, &VisitCode);
table_.Register(kVisitSharedFunctionInfo,
&VisitSharedFunctionInfoAndFlushCode);
table_.Register(kVisitJSFunction,
&VisitJSFunctionAndFlushCode);
table_.Register(kVisitJSRegExp,
&VisitRegExpAndFlushCode);
table_.Register(kVisitPropertyCell,
&FixedBodyVisitor<StaticMarkingVisitor,
JSGlobalPropertyCell::BodyDescriptor,
void>::Visit);
table_.RegisterSpecializations<DataObjectVisitor,
kVisitDataObject,
kVisitDataObjectGeneric>();
table_.RegisterSpecializations<JSObjectVisitor,
kVisitJSObject,
kVisitJSObjectGeneric>();
table_.RegisterSpecializations<StructObjectVisitor,
kVisitStruct,
kVisitStructGeneric>();
if (FLAG_track_gc_object_stats) {
// Copy the visitor table to make call-through possible.
non_count_table_.CopyFrom(&table_);
#define VISITOR_ID_COUNT_FUNCTION(id) \
table_.Register(kVisit##id, ObjectStatsTracker<kVisit##id>::Visit);
VISITOR_ID_LIST(VISITOR_ID_COUNT_FUNCTION)
#undef VISITOR_ID_COUNT_FUNCTION
}
}
VisitorDispatchTable<StaticMarkingVisitor::Callback> VisitorDispatchTable<StaticMarkingVisitor::Callback>
StaticMarkingVisitor::table_; StaticMarkingVisitor::table_;
VisitorDispatchTable<StaticMarkingVisitor::Callback> VisitorDispatchTable<StaticMarkingVisitor::Callback>
......
...@@ -4178,30 +4178,38 @@ class Code: public HeapObject { ...@@ -4178,30 +4178,38 @@ class Code: public HeapObject {
FLAGS_MAX_VALUE = kMaxInt FLAGS_MAX_VALUE = kMaxInt
}; };
#define CODE_KIND_LIST(V) \
V(FUNCTION) \
V(OPTIMIZED_FUNCTION) \
V(STUB) \
V(BUILTIN) \
V(LOAD_IC) \
V(KEYED_LOAD_IC) \
V(CALL_IC) \
V(KEYED_CALL_IC) \
V(STORE_IC) \
V(KEYED_STORE_IC) \
V(UNARY_OP_IC) \
V(BINARY_OP_IC) \
V(COMPARE_IC) \
V(TO_BOOLEAN_IC)
enum Kind { enum Kind {
FUNCTION, #define DEFINE_CODE_KIND_ENUM(name) name,
OPTIMIZED_FUNCTION, CODE_KIND_LIST(DEFINE_CODE_KIND_ENUM)
STUB, #undef DEFINE_CODE_KIND_ENUM
BUILTIN,
LOAD_IC,
KEYED_LOAD_IC,
CALL_IC,
KEYED_CALL_IC,
STORE_IC,
KEYED_STORE_IC,
UNARY_OP_IC,
BINARY_OP_IC,
COMPARE_IC,
TO_BOOLEAN_IC,
// No more than 16 kinds. The value currently encoded in four bits in
// Flags.
// Pseudo-kinds. // Pseudo-kinds.
LAST_CODE_KIND = TO_BOOLEAN_IC,
REGEXP = BUILTIN, REGEXP = BUILTIN,
FIRST_IC_KIND = LOAD_IC, FIRST_IC_KIND = LOAD_IC,
LAST_IC_KIND = TO_BOOLEAN_IC LAST_IC_KIND = TO_BOOLEAN_IC
}; };
// No more than 16 kinds. The value is currently encoded in four bits in
// Flags.
STATIC_ASSERT(LAST_CODE_KIND < 16);
// Types of stubs. // Types of stubs.
enum StubType { enum StubType {
NORMAL, NORMAL,
......
...@@ -61,6 +61,16 @@ Counters::Counters() { ...@@ -61,6 +61,16 @@ Counters::Counters() {
INSTANCE_TYPE_LIST(SC) INSTANCE_TYPE_LIST(SC)
#undef SC #undef SC
#define SC(name) \
StatsCounter count_of_CODE_TYPE_##name = { \
"c:" "V8.CountOf_CODE_TYPE-" #name, NULL, false }; \
count_of_CODE_TYPE_##name##_ = count_of_CODE_TYPE_##name; \
StatsCounter size_of_CODE_TYPE_##name = { \
"c:" "V8.SizeOf_CODE_TYPE-" #name, NULL, false }; \
size_of_CODE_TYPE_##name##_ = size_of_CODE_TYPE_##name;
CODE_KIND_LIST(SC)
#undef SC
StatsCounter state_counters[] = { StatsCounter state_counters[] = {
#define COUNTER_NAME(name) \ #define COUNTER_NAME(name) \
{ "c:V8.State" #name, NULL, false }, { "c:V8.State" #name, NULL, false },
......
...@@ -315,6 +315,14 @@ class Counters { ...@@ -315,6 +315,14 @@ class Counters {
INSTANCE_TYPE_LIST(SC) INSTANCE_TYPE_LIST(SC)
#undef SC #undef SC
#define SC(name) \
StatsCounter* count_of_CODE_TYPE_##name() \
{ return &count_of_CODE_TYPE_##name##_; } \
StatsCounter* size_of_CODE_TYPE_##name() \
{ return &size_of_CODE_TYPE_##name##_; }
CODE_KIND_LIST(SC)
#undef SC
enum Id { enum Id {
#define RATE_ID(name, caption) k_##name, #define RATE_ID(name, caption) k_##name,
HISTOGRAM_TIMER_LIST(RATE_ID) HISTOGRAM_TIMER_LIST(RATE_ID)
...@@ -329,6 +337,10 @@ class Counters { ...@@ -329,6 +337,10 @@ class Counters {
#define COUNTER_ID(name) kCountOf##name, kSizeOf##name, #define COUNTER_ID(name) kCountOf##name, kSizeOf##name,
INSTANCE_TYPE_LIST(COUNTER_ID) INSTANCE_TYPE_LIST(COUNTER_ID)
#undef COUNTER_ID #undef COUNTER_ID
#define COUNTER_ID(name) kCountOfCODE_TYPE_##name, \
kSizeOfCODE_TYPE_##name,
CODE_KIND_LIST(COUNTER_ID)
#undef COUNTER_ID
#define COUNTER_ID(name) k_##name, #define COUNTER_ID(name) k_##name,
STATE_TAG_LIST(COUNTER_ID) STATE_TAG_LIST(COUNTER_ID)
#undef COUNTER_ID #undef COUNTER_ID
...@@ -362,6 +374,12 @@ class Counters { ...@@ -362,6 +374,12 @@ class Counters {
INSTANCE_TYPE_LIST(SC) INSTANCE_TYPE_LIST(SC)
#undef SC #undef SC
#define SC(name) \
StatsCounter size_of_CODE_TYPE_##name##_; \
StatsCounter count_of_CODE_TYPE_##name##_;
CODE_KIND_LIST(SC)
#undef SC
enum { enum {
#define COUNTER_ID(name) __##name, #define COUNTER_ID(name) __##name,
STATE_TAG_LIST(COUNTER_ID) STATE_TAG_LIST(COUNTER_ID)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment