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
This commit is contained in:
parent
6744e6e9a6
commit
1ab272ab36
12
src/heap.cc
12
src/heap.cc
@ -7211,6 +7211,18 @@ void Heap::CheckpointObjectStats() {
|
||||
static_cast<int>(object_sizes_last_time_[name]));
|
||||
INSTANCE_TYPE_LIST(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_sizes_last_time_, object_sizes_, sizeof(object_sizes_));
|
||||
ClearObjectStats();
|
||||
|
30
src/heap.h
30
src/heap.h
@ -1596,10 +1596,26 @@ class Heap {
|
||||
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);
|
||||
object_counts_[type]++;
|
||||
object_sizes_[type] += size;
|
||||
if (sub_type < 0) {
|
||||
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();
|
||||
@ -2004,10 +2020,10 @@ class Heap {
|
||||
static const int kInitialNumberStringCacheSize = 256;
|
||||
|
||||
// Object counts and used memory by InstanceType
|
||||
size_t object_counts_[LAST_TYPE + 1];
|
||||
size_t object_counts_last_time_[LAST_TYPE + 1];
|
||||
size_t object_sizes_[LAST_TYPE + 1];
|
||||
size_t object_sizes_last_time_[LAST_TYPE + 1];
|
||||
size_t object_counts_[OBJECT_STATS_COUNT];
|
||||
size_t object_counts_last_time_[OBJECT_STATS_COUNT];
|
||||
size_t object_sizes_[OBJECT_STATS_COUNT];
|
||||
size_t object_sizes_last_time_[OBJECT_STATS_COUNT];
|
||||
|
||||
// Maximum GC pause.
|
||||
int max_gc_pause_;
|
||||
|
@ -947,92 +947,10 @@ class StaticMarkingVisitor : public StaticVisitorBase {
|
||||
template<int id>
|
||||
class ObjectStatsTracker {
|
||||
public:
|
||||
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 inline void Visit(Map* map, HeapObject* obj);
|
||||
};
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
static void Initialize();
|
||||
|
||||
INLINE(static void VisitPointer(Heap* heap, Object** p)) {
|
||||
MarkObjectByPointer(heap->mark_compact_collector(), p, p);
|
||||
@ -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>
|
||||
StaticMarkingVisitor::table_;
|
||||
VisitorDispatchTable<StaticMarkingVisitor::Callback>
|
||||
|
@ -4178,30 +4178,38 @@ class Code: public HeapObject {
|
||||
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 {
|
||||
FUNCTION,
|
||||
OPTIMIZED_FUNCTION,
|
||||
STUB,
|
||||
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.
|
||||
#define DEFINE_CODE_KIND_ENUM(name) name,
|
||||
CODE_KIND_LIST(DEFINE_CODE_KIND_ENUM)
|
||||
#undef DEFINE_CODE_KIND_ENUM
|
||||
|
||||
// Pseudo-kinds.
|
||||
LAST_CODE_KIND = TO_BOOLEAN_IC,
|
||||
REGEXP = BUILTIN,
|
||||
FIRST_IC_KIND = LOAD_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.
|
||||
enum StubType {
|
||||
NORMAL,
|
||||
|
@ -61,6 +61,16 @@ Counters::Counters() {
|
||||
INSTANCE_TYPE_LIST(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[] = {
|
||||
#define COUNTER_NAME(name) \
|
||||
{ "c:V8.State" #name, NULL, false },
|
||||
|
@ -315,6 +315,14 @@ class Counters {
|
||||
INSTANCE_TYPE_LIST(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 {
|
||||
#define RATE_ID(name, caption) k_##name,
|
||||
HISTOGRAM_TIMER_LIST(RATE_ID)
|
||||
@ -329,6 +337,10 @@ class Counters {
|
||||
#define COUNTER_ID(name) kCountOf##name, kSizeOf##name,
|
||||
INSTANCE_TYPE_LIST(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,
|
||||
STATE_TAG_LIST(COUNTER_ID)
|
||||
#undef COUNTER_ID
|
||||
@ -362,6 +374,12 @@ class Counters {
|
||||
INSTANCE_TYPE_LIST(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 {
|
||||
#define COUNTER_ID(name) __##name,
|
||||
STATE_TAG_LIST(COUNTER_ID)
|
||||
|
Loading…
Reference in New Issue
Block a user