New heap profiler: include all heap objects and refs into snapshot.

Otherwise, retaned memory sizes are not precise. This increases size
of heap snapshot, I will deal with this later. Heap objects and
references previously missing in snapshot are now marked as 'hidden'.
That means, they not shown to user, but participate in sizes
calculation.

Other small changes:
 - added 'shortcut' graph edges: e.g. to pin global objects on top
   level;
 - meta-information in JSON snapshot is no more double encoded.

Review URL: http://codereview.chromium.org/5139002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5849 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 7d72d303
...@@ -197,8 +197,13 @@ class V8EXPORT HeapGraphEdge { ...@@ -197,8 +197,13 @@ class V8EXPORT HeapGraphEdge {
kContextVariable = 0, // A variable from a function context. kContextVariable = 0, // A variable from a function context.
kElement = 1, // An element of an array. kElement = 1, // An element of an array.
kProperty = 2, // A named object property. kProperty = 2, // A named object property.
kInternal = 3 // A link that can't be accessed from JS, kInternal = 3, // A link that can't be accessed from JS,
// thus, its name isn't a real property name. // thus, its name isn't a real property name
// (e.g. parts of a ConsString).
kHidden = 4, // A link that is needed for proper sizes
// calculation, but may be hidden from user.
kShortcut = 5 // A link that must not be followed during
// sizes calculation.
}; };
/** Returns edge type (see HeapGraphEdge::Type). */ /** Returns edge type (see HeapGraphEdge::Type). */
...@@ -240,7 +245,7 @@ class V8EXPORT HeapGraphPath { ...@@ -240,7 +245,7 @@ class V8EXPORT HeapGraphPath {
class V8EXPORT HeapGraphNode { class V8EXPORT HeapGraphNode {
public: public:
enum Type { enum Type {
kInternal = 0, // Internal node, a virtual one, for housekeeping. kHidden = 0, // Hidden node, may be filtered when shown to user.
kArray = 1, // An array of elements. kArray = 1, // An array of elements.
kString = 2, // A string. kString = 2, // A string.
kObject = 3, // A JS object (except for arrays and strings). kObject = 3, // A JS object (except for arrays and strings).
......
...@@ -4669,9 +4669,11 @@ Handle<Value> HeapGraphEdge::GetName() const { ...@@ -4669,9 +4669,11 @@ Handle<Value> HeapGraphEdge::GetName() const {
case i::HeapGraphEdge::kContextVariable: case i::HeapGraphEdge::kContextVariable:
case i::HeapGraphEdge::kInternal: case i::HeapGraphEdge::kInternal:
case i::HeapGraphEdge::kProperty: case i::HeapGraphEdge::kProperty:
case i::HeapGraphEdge::kShortcut:
return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol( return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
edge->name()))); edge->name())));
case i::HeapGraphEdge::kElement: case i::HeapGraphEdge::kElement:
case i::HeapGraphEdge::kHidden:
return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt( return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt(
edge->index()))); edge->index())));
default: UNREACHABLE(); default: UNREACHABLE();
......
...@@ -927,10 +927,16 @@ class AllocatingRetainersIterator { ...@@ -927,10 +927,16 @@ class AllocatingRetainersIterator {
void Call(const JSObjectsCluster& cluster, void Call(const JSObjectsCluster& cluster,
const NumberAndSizeInfo& number_and_size) { const NumberAndSizeInfo& number_and_size) {
int child_index, retainer_index; int child_index, retainer_index;
map_->CountReference(ClusterAsHeapObject(cluster), child_, map_->CountReference(ClusterAsHeapObject(cluster),
&child_index, &retainer_index); child_,
map_->Map(ClusterAsHeapObject(cluster))->SetElementReference( &child_index,
child_index, number_and_size.number(), child_entry_, retainer_index); &retainer_index);
map_->Map(ClusterAsHeapObject(cluster))->SetIndexedReference(
HeapGraphEdge::kElement,
child_index,
number_and_size.number(),
child_entry_,
retainer_index);
} }
private: private:
...@@ -1042,7 +1048,7 @@ void AggregatedHeapSnapshotGenerator::FillHeapSnapshot(HeapSnapshot* snapshot) { ...@@ -1042,7 +1048,7 @@ void AggregatedHeapSnapshotGenerator::FillHeapSnapshot(HeapSnapshot* snapshot) {
if (agg_snapshot_->info()[i].bytes() > 0) { if (agg_snapshot_->info()[i].bytes() > 0) {
AddEntryFromAggregatedSnapshot(snapshot, AddEntryFromAggregatedSnapshot(snapshot,
&root_child_index, &root_child_index,
HeapEntry::kInternal, HeapEntry::kHidden,
agg_snapshot_->info()[i].name(), agg_snapshot_->info()[i].name(),
agg_snapshot_->info()[i].number(), agg_snapshot_->info()[i].number(),
agg_snapshot_->info()[i].bytes(), agg_snapshot_->info()[i].bytes(),
......
...@@ -110,15 +110,13 @@ void HeapEntriesMap::UpdateEntries(Visitor* visitor) { ...@@ -110,15 +110,13 @@ void HeapEntriesMap::UpdateEntries(Visitor* visitor) {
for (HashMap::Entry* p = entries_.Start(); for (HashMap::Entry* p = entries_.Start();
p != NULL; p != NULL;
p = entries_.Next(p)) { p = entries_.Next(p)) {
if (!IsAlias(p->value)) { EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value);
EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value); entry_info->entry = visitor->GetEntry(
entry_info->entry = visitor->GetEntry( reinterpret_cast<HeapObject*>(p->key),
reinterpret_cast<HeapObject*>(p->key), entry_info->children_count,
entry_info->children_count, entry_info->retainers_count);
entry_info->retainers_count); entry_info->children_count = 0;
entry_info->children_count = 0; entry_info->retainers_count = 0;
entry_info->retainers_count = 0;
}
} }
} }
......
This diff is collapsed.
...@@ -439,22 +439,26 @@ class HeapGraphEdge BASE_EMBEDDED { ...@@ -439,22 +439,26 @@ class HeapGraphEdge BASE_EMBEDDED {
kContextVariable = v8::HeapGraphEdge::kContextVariable, kContextVariable = v8::HeapGraphEdge::kContextVariable,
kElement = v8::HeapGraphEdge::kElement, kElement = v8::HeapGraphEdge::kElement,
kProperty = v8::HeapGraphEdge::kProperty, kProperty = v8::HeapGraphEdge::kProperty,
kInternal = v8::HeapGraphEdge::kInternal kInternal = v8::HeapGraphEdge::kInternal,
kHidden = v8::HeapGraphEdge::kHidden,
kShortcut = v8::HeapGraphEdge::kShortcut
}; };
HeapGraphEdge() { } HeapGraphEdge() { }
void Init(int child_index, Type type, const char* name, HeapEntry* to); void Init(int child_index, Type type, const char* name, HeapEntry* to);
void Init(int child_index, Type type, int index, HeapEntry* to);
void Init(int child_index, int index, HeapEntry* to); void Init(int child_index, int index, HeapEntry* to);
Type type() { return static_cast<Type>(type_); } Type type() { return static_cast<Type>(type_); }
int index() { int index() {
ASSERT(type_ == kElement); ASSERT(type_ == kElement || type_ == kHidden);
return index_; return index_;
} }
const char* name() { const char* name() {
ASSERT(type_ == kContextVariable ASSERT(type_ == kContextVariable
|| type_ == kProperty || type_ == kProperty
|| type_ == kInternal); || type_ == kInternal
|| type_ == kShortcut);
return name_; return name_;
} }
HeapEntry* to() { return to_; } HeapEntry* to() { return to_; }
...@@ -462,8 +466,8 @@ class HeapGraphEdge BASE_EMBEDDED { ...@@ -462,8 +466,8 @@ class HeapGraphEdge BASE_EMBEDDED {
HeapEntry* From(); HeapEntry* From();
private: private:
int child_index_ : 30; int child_index_ : 29;
unsigned type_ : 2; unsigned type_ : 3;
union { union {
int index_; int index_;
const char* name_; const char* name_;
...@@ -500,7 +504,7 @@ class HeapSnapshot; ...@@ -500,7 +504,7 @@ class HeapSnapshot;
class HeapEntry BASE_EMBEDDED { class HeapEntry BASE_EMBEDDED {
public: public:
enum Type { enum Type {
kInternal = v8::HeapGraphNode::kInternal, kHidden = v8::HeapGraphNode::kHidden,
kArray = v8::HeapGraphNode::kArray, kArray = v8::HeapGraphNode::kArray,
kString = v8::HeapGraphNode::kString, kString = v8::HeapGraphNode::kString,
kObject = v8::HeapGraphNode::kObject, kObject = v8::HeapGraphNode::kObject,
...@@ -547,8 +551,11 @@ class HeapEntry BASE_EMBEDDED { ...@@ -547,8 +551,11 @@ class HeapEntry BASE_EMBEDDED {
void ApplyAndPaintAllReachable(Visitor* visitor); void ApplyAndPaintAllReachable(Visitor* visitor);
void PaintAllReachable(); void PaintAllReachable();
void SetElementReference( void SetIndexedReference(HeapGraphEdge::Type type,
int child_index, int index, HeapEntry* entry, int retainer_index); int child_index,
int index,
HeapEntry* entry,
int retainer_index);
void SetNamedReference(HeapGraphEdge::Type type, void SetNamedReference(HeapGraphEdge::Type type,
int child_index, int child_index,
const char* name, const char* name,
...@@ -668,12 +675,12 @@ class HeapSnapshot { ...@@ -668,12 +675,12 @@ class HeapSnapshot {
const char* title() { return title_; } const char* title() { return title_; }
unsigned uid() { return uid_; } unsigned uid() { return uid_; }
HeapEntry* root() { return root_entry_; } HeapEntry* root() { return root_entry_; }
HeapEntry* gc_roots() { return gc_roots_entry_; }
void AllocateEntries( void AllocateEntries(
int entries_count, int children_count, int retainers_count); int entries_count, int children_count, int retainers_count);
HeapEntry* AddEntry( HeapEntry* AddEntry(
HeapObject* object, int children_count, int retainers_count); HeapObject* object, int children_count, int retainers_count);
bool WillAddEntry(HeapObject* object);
HeapEntry* AddEntry(HeapEntry::Type type, HeapEntry* AddEntry(HeapEntry::Type type,
const char* name, const char* name,
uint64_t id, uint64_t id,
...@@ -693,7 +700,8 @@ class HeapSnapshot { ...@@ -693,7 +700,8 @@ class HeapSnapshot {
void Print(int max_depth); void Print(int max_depth);
void PrintEntriesSize(); void PrintEntriesSize();
static HeapObject *const kInternalRootObject; static HeapObject* const kInternalRootObject;
static HeapObject* const kGcRootsObject;
private: private:
HeapEntry* AddEntry(HeapObject* object, HeapEntry* AddEntry(HeapObject* object,
...@@ -702,14 +710,13 @@ class HeapSnapshot { ...@@ -702,14 +710,13 @@ class HeapSnapshot {
int children_count, int children_count,
int retainers_count); int retainers_count);
HeapEntry* GetNextEntryToInit(); HeapEntry* GetNextEntryToInit();
static int GetObjectSize(HeapObject* obj);
static int CalculateNetworkSize(JSObject* obj);
HeapSnapshotsCollection* collection_; HeapSnapshotsCollection* collection_;
Type type_; Type type_;
const char* title_; const char* title_;
unsigned uid_; unsigned uid_;
HeapEntry* root_entry_; HeapEntry* root_entry_;
HeapEntry* gc_roots_entry_;
char* raw_entries_; char* raw_entries_;
List<HeapEntry*> entries_; List<HeapEntry*> entries_;
bool entries_sorted_; bool entries_sorted_;
...@@ -733,6 +740,10 @@ class HeapObjectsMap { ...@@ -733,6 +740,10 @@ class HeapObjectsMap {
uint64_t FindObject(Address addr); uint64_t FindObject(Address addr);
void MoveObject(Address from, Address to); void MoveObject(Address from, Address to);
static const uint64_t kInternalRootObjectId;
static const uint64_t kGcRootsObjectId;
static const uint64_t kFirstAvailableObjectId;
private: private:
struct EntryInfo { struct EntryInfo {
explicit EntryInfo(uint64_t id) : id(id), accessed(true) { } explicit EntryInfo(uint64_t id) : id(id), accessed(true) { }
...@@ -868,9 +879,6 @@ class HeapEntriesMap { ...@@ -868,9 +879,6 @@ class HeapEntriesMap {
HeapEntriesMap(); HeapEntriesMap();
~HeapEntriesMap(); ~HeapEntriesMap();
// Aliasing is used for skipping intermediate proxy objects, like
// JSGlobalPropertyCell.
void Alias(HeapObject* from, HeapObject* to);
HeapEntry* Map(HeapObject* object); HeapEntry* Map(HeapObject* object);
void Pair(HeapObject* object, HeapEntry* entry); void Pair(HeapObject* object, HeapEntry* entry);
void CountReference(HeapObject* from, HeapObject* to, void CountReference(HeapObject* from, HeapObject* to,
...@@ -894,41 +902,45 @@ class HeapEntriesMap { ...@@ -894,41 +902,45 @@ class HeapEntriesMap {
int retainers_count; int retainers_count;
}; };
uint32_t Hash(HeapObject* object) { static uint32_t Hash(HeapObject* object) {
return ComputeIntegerHash( return ComputeIntegerHash(
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object))); static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object)));
} }
static bool HeapObjectsMatch(void* key1, void* key2) { return key1 == key2; } static bool HeapObjectsMatch(void* key1, void* key2) { return key1 == key2; }
bool IsAlias(void* ptr) {
return reinterpret_cast<intptr_t>(ptr) & kAliasTag;
}
void* MakeAlias(void* ptr) {
return reinterpret_cast<void*>(reinterpret_cast<intptr_t>(ptr) | kAliasTag);
}
void* Unalias(void* ptr) {
return reinterpret_cast<void*>(
reinterpret_cast<intptr_t>(ptr) & (~kAliasTag));
}
HashMap entries_; HashMap entries_;
int entries_count_; int entries_count_;
int total_children_count_; int total_children_count_;
int total_retainers_count_; int total_retainers_count_;
static const intptr_t kAliasTag = 1; friend class HeapObjectsSet;
DISALLOW_COPY_AND_ASSIGN(HeapEntriesMap); DISALLOW_COPY_AND_ASSIGN(HeapEntriesMap);
}; };
class HeapObjectsSet {
public:
HeapObjectsSet();
void Clear();
bool Contains(Object* object);
void Insert(Object* obj);
private:
HashMap entries_;
DISALLOW_COPY_AND_ASSIGN(HeapObjectsSet);
};
class HeapSnapshotGenerator { class HeapSnapshotGenerator {
public: public:
class SnapshotFillerInterface { class SnapshotFillerInterface {
public: public:
virtual ~SnapshotFillerInterface() { } virtual ~SnapshotFillerInterface() { }
virtual HeapEntry* AddEntry(HeapObject* obj) = 0; virtual HeapEntry* AddEntry(HeapObject* obj) = 0;
virtual void SetElementReference(HeapObject* parent_obj, virtual void SetIndexedReference(HeapGraphEdge::Type type,
HeapObject* parent_obj,
HeapEntry* parent_entry, HeapEntry* parent_entry,
int index, int index,
Object* child_obj, Object* child_obj,
...@@ -939,8 +951,11 @@ class HeapSnapshotGenerator { ...@@ -939,8 +951,11 @@ class HeapSnapshotGenerator {
const char* reference_name, const char* reference_name,
Object* child_obj, Object* child_obj,
HeapEntry* child_entry) = 0; HeapEntry* child_entry) = 0;
virtual void SetRootReference(Object* child_obj, virtual void SetRootGcRootsReference() = 0;
HeapEntry* child_entry) = 0; virtual void SetRootShortcutReference(Object* child_obj,
HeapEntry* child_entry) = 0;
virtual void SetStrongRootReference(Object* child_obj,
HeapEntry* child_entry) = 0;
}; };
explicit HeapSnapshotGenerator(HeapSnapshot* snapshot); explicit HeapSnapshotGenerator(HeapSnapshot* snapshot);
...@@ -969,19 +984,33 @@ class HeapSnapshotGenerator { ...@@ -969,19 +984,33 @@ class HeapSnapshotGenerator {
HeapEntry* parent, HeapEntry* parent,
int index, int index,
Object* child); Object* child);
void SetHiddenReference(HeapObject* parent_obj,
HeapEntry* parent,
int index,
Object* child);
void SetPropertyReference(HeapObject* parent_obj, void SetPropertyReference(HeapObject* parent_obj,
HeapEntry* parent, HeapEntry* parent,
String* reference_name, String* reference_name,
Object* child); Object* child);
void SetRootReference(Object* child); void SetPropertyShortcutReference(HeapObject* parent_obj,
HeapEntry* parent,
String* reference_name,
Object* child);
void SetRootShortcutReference(Object* child);
void SetRootGcRootsReference();
void SetGcRootsReference(Object* child);
HeapSnapshot* snapshot_; HeapSnapshot* snapshot_;
HeapSnapshotsCollection* collection_; HeapSnapshotsCollection* collection_;
// Mapping from HeapObject* pointers to HeapEntry* pointers. // Mapping from HeapObject* pointers to HeapEntry* pointers.
HeapEntriesMap entries_; HeapEntriesMap entries_;
SnapshotFillerInterface* filler_; SnapshotFillerInterface* filler_;
// Used during references extraction to mark heap objects that
// are references via non-hidden properties.
HeapObjectsSet known_references_;
friend class IndexedReferencesExtractor; friend class IndexedReferencesExtractor;
friend class RootsReferencesExtractor;
DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator); DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator);
}; };
......
This diff is collapsed.
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