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