Remove snapshots-related code that is implemented in DevTools heap profiler.
Diffs and retaining paths are implemented on JS side. There is no need to maintain native implementation. R=vitalyr@chromium.org BUG=none TEST=none Review URL: http://codereview.chromium.org/6770009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7412 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
770df67e16
commit
2d95ed4b25
@ -240,22 +240,6 @@ class V8EXPORT HeapGraphEdge {
|
||||
};
|
||||
|
||||
|
||||
class V8EXPORT HeapGraphPath {
|
||||
public:
|
||||
/** Returns the number of edges in the path. */
|
||||
int GetEdgesCount() const;
|
||||
|
||||
/** Returns an edge from the path. */
|
||||
const HeapGraphEdge* GetEdge(int index) const;
|
||||
|
||||
/** Returns origin node. */
|
||||
const HeapGraphNode* GetFromNode() const;
|
||||
|
||||
/** Returns destination node. */
|
||||
const HeapGraphNode* GetToNode() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* HeapGraphNode represents a node in a heap graph.
|
||||
*/
|
||||
@ -325,12 +309,6 @@ class V8EXPORT HeapGraphNode {
|
||||
/** Returns a retainer by index. */
|
||||
const HeapGraphEdge* GetRetainer(int index) const;
|
||||
|
||||
/** Returns the number of simple retaining paths from the root to the node. */
|
||||
int GetRetainingPathsCount() const;
|
||||
|
||||
/** Returns a retaining path by index. */
|
||||
const HeapGraphPath* GetRetainingPath(int index) const;
|
||||
|
||||
/**
|
||||
* Returns a dominator node. This is the node that participates in every
|
||||
* path from the snapshot root to the current node.
|
||||
@ -339,16 +317,6 @@ class V8EXPORT HeapGraphNode {
|
||||
};
|
||||
|
||||
|
||||
class V8EXPORT HeapSnapshotsDiff {
|
||||
public:
|
||||
/** Returns the root node for added nodes. */
|
||||
const HeapGraphNode* GetAdditionsRoot() const;
|
||||
|
||||
/** Returns the root node for deleted nodes. */
|
||||
const HeapGraphNode* GetDeletionsRoot() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* HeapSnapshots record the state of the JS heap at some moment.
|
||||
*/
|
||||
@ -378,12 +346,6 @@ class V8EXPORT HeapSnapshot {
|
||||
/** Returns a node by its id. */
|
||||
const HeapGraphNode* GetNodeById(uint64_t id) const;
|
||||
|
||||
/**
|
||||
* Returns a diff between this snapshot and another one. Only snapshots
|
||||
* of the same type can be compared.
|
||||
*/
|
||||
const HeapSnapshotsDiff* CompareWith(const HeapSnapshot* snapshot) const;
|
||||
|
||||
/**
|
||||
* Deletes the snapshot and removes it from HeapProfiler's list.
|
||||
* All pointers to nodes, edges and paths previously returned become
|
||||
|
72
src/api.cc
72
src/api.cc
@ -5288,34 +5288,6 @@ const HeapGraphNode* HeapGraphEdge::GetToNode() const {
|
||||
}
|
||||
|
||||
|
||||
static i::HeapGraphPath* ToInternal(const HeapGraphPath* path) {
|
||||
return const_cast<i::HeapGraphPath*>(
|
||||
reinterpret_cast<const i::HeapGraphPath*>(path));
|
||||
}
|
||||
|
||||
|
||||
int HeapGraphPath::GetEdgesCount() const {
|
||||
return ToInternal(this)->path()->length();
|
||||
}
|
||||
|
||||
|
||||
const HeapGraphEdge* HeapGraphPath::GetEdge(int index) const {
|
||||
return reinterpret_cast<const HeapGraphEdge*>(
|
||||
ToInternal(this)->path()->at(index));
|
||||
}
|
||||
|
||||
|
||||
const HeapGraphNode* HeapGraphPath::GetFromNode() const {
|
||||
return GetEdgesCount() > 0 ? GetEdge(0)->GetFromNode() : NULL;
|
||||
}
|
||||
|
||||
|
||||
const HeapGraphNode* HeapGraphPath::GetToNode() const {
|
||||
const int count = GetEdgesCount();
|
||||
return count > 0 ? GetEdge(count - 1)->GetToNode() : NULL;
|
||||
}
|
||||
|
||||
|
||||
static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
|
||||
return const_cast<i::HeapEntry*>(
|
||||
reinterpret_cast<const i::HeapEntry*>(entry));
|
||||
@ -5397,21 +5369,6 @@ const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const {
|
||||
}
|
||||
|
||||
|
||||
int HeapGraphNode::GetRetainingPathsCount() const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
IsDeadCheck(isolate, "v8::HeapSnapshot::GetRetainingPathsCount");
|
||||
return ToInternal(this)->GetRetainingPaths()->length();
|
||||
}
|
||||
|
||||
|
||||
const HeapGraphPath* HeapGraphNode::GetRetainingPath(int index) const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
IsDeadCheck(isolate, "v8::HeapSnapshot::GetRetainingPath");
|
||||
return reinterpret_cast<const HeapGraphPath*>(
|
||||
ToInternal(this)->GetRetainingPaths()->at(index));
|
||||
}
|
||||
|
||||
|
||||
const HeapGraphNode* HeapGraphNode::GetDominatorNode() const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
IsDeadCheck(isolate, "v8::HeapSnapshot::GetDominatorNode");
|
||||
@ -5419,26 +5376,6 @@ const HeapGraphNode* HeapGraphNode::GetDominatorNode() const {
|
||||
}
|
||||
|
||||
|
||||
const HeapGraphNode* HeapSnapshotsDiff::GetAdditionsRoot() const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
IsDeadCheck(isolate, "v8::HeapSnapshotsDiff::GetAdditionsRoot");
|
||||
i::HeapSnapshotsDiff* diff =
|
||||
const_cast<i::HeapSnapshotsDiff*>(
|
||||
reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
|
||||
return reinterpret_cast<const HeapGraphNode*>(diff->additions_root());
|
||||
}
|
||||
|
||||
|
||||
const HeapGraphNode* HeapSnapshotsDiff::GetDeletionsRoot() const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
IsDeadCheck(isolate, "v8::HeapSnapshotsDiff::GetDeletionsRoot");
|
||||
i::HeapSnapshotsDiff* diff =
|
||||
const_cast<i::HeapSnapshotsDiff*>(
|
||||
reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
|
||||
return reinterpret_cast<const HeapGraphNode*>(diff->deletions_root());
|
||||
}
|
||||
|
||||
|
||||
static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
|
||||
return const_cast<i::HeapSnapshot*>(
|
||||
reinterpret_cast<const i::HeapSnapshot*>(snapshot));
|
||||
@ -5494,15 +5431,6 @@ const HeapGraphNode* HeapSnapshot::GetNodeById(uint64_t id) const {
|
||||
}
|
||||
|
||||
|
||||
const HeapSnapshotsDiff* HeapSnapshot::CompareWith(
|
||||
const HeapSnapshot* snapshot) const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
IsDeadCheck(isolate, "v8::HeapSnapshot::CompareWith");
|
||||
return reinterpret_cast<const HeapSnapshotsDiff*>(
|
||||
ToInternal(this)->CompareWith(ToInternal(snapshot)));
|
||||
}
|
||||
|
||||
|
||||
void HeapSnapshot::Serialize(OutputStream* stream,
|
||||
HeapSnapshot::SerializationFormat format) const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
|
@ -984,11 +984,6 @@ int HeapEntry::RetainedSize(bool exact) {
|
||||
}
|
||||
|
||||
|
||||
List<HeapGraphPath*>* HeapEntry::GetRetainingPaths() {
|
||||
return snapshot_->GetRetainingPaths(this);
|
||||
}
|
||||
|
||||
|
||||
template<class Visitor>
|
||||
void HeapEntry::ApplyAndPaintAllReachable(Visitor* visitor) {
|
||||
List<HeapEntry*> list(10);
|
||||
@ -1147,107 +1142,6 @@ void HeapEntry::CalculateExactRetainedSize() {
|
||||
}
|
||||
|
||||
|
||||
class CachedHeapGraphPath {
|
||||
public:
|
||||
CachedHeapGraphPath()
|
||||
: nodes_(NodesMatch) { }
|
||||
CachedHeapGraphPath(const CachedHeapGraphPath& src)
|
||||
: nodes_(NodesMatch, &HashMap::DefaultAllocator, src.nodes_.capacity()),
|
||||
path_(src.path_.length() + 1) {
|
||||
for (HashMap::Entry* p = src.nodes_.Start();
|
||||
p != NULL;
|
||||
p = src.nodes_.Next(p)) {
|
||||
nodes_.Lookup(p->key, p->hash, true);
|
||||
}
|
||||
path_.AddAll(src.path_);
|
||||
}
|
||||
void Add(HeapGraphEdge* edge) {
|
||||
nodes_.Lookup(edge->to(), Hash(edge->to()), true);
|
||||
path_.Add(edge);
|
||||
}
|
||||
bool ContainsNode(HeapEntry* node) {
|
||||
return nodes_.Lookup(node, Hash(node), false) != NULL;
|
||||
}
|
||||
const List<HeapGraphEdge*>* path() const { return &path_; }
|
||||
|
||||
private:
|
||||
static uint32_t Hash(HeapEntry* entry) {
|
||||
return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry));
|
||||
}
|
||||
static bool NodesMatch(void* key1, void* key2) { return key1 == key2; }
|
||||
|
||||
HashMap nodes_;
|
||||
List<HeapGraphEdge*> path_;
|
||||
};
|
||||
|
||||
|
||||
List<HeapGraphPath*>* HeapEntry::CalculateRetainingPaths() {
|
||||
List<HeapGraphPath*>* retaining_paths = new List<HeapGraphPath*>(4);
|
||||
CachedHeapGraphPath path;
|
||||
FindRetainingPaths(&path, retaining_paths);
|
||||
return retaining_paths;
|
||||
}
|
||||
|
||||
|
||||
void HeapEntry::FindRetainingPaths(CachedHeapGraphPath* prev_path,
|
||||
List<HeapGraphPath*>* retaining_paths) {
|
||||
Vector<HeapGraphEdge*> rets = retainers();
|
||||
for (int i = 0; i < rets.length(); ++i) {
|
||||
HeapGraphEdge* ret_edge = rets[i];
|
||||
if (prev_path->ContainsNode(ret_edge->From())) continue;
|
||||
if (ret_edge->From() != snapshot()->root()) {
|
||||
CachedHeapGraphPath path(*prev_path);
|
||||
path.Add(ret_edge);
|
||||
ret_edge->From()->FindRetainingPaths(&path, retaining_paths);
|
||||
} else {
|
||||
HeapGraphPath* ret_path = new HeapGraphPath(*prev_path->path());
|
||||
ret_path->Set(0, ret_edge);
|
||||
retaining_paths->Add(ret_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HeapGraphPath::HeapGraphPath(const List<HeapGraphEdge*>& path)
|
||||
: path_(path.length() + 1) {
|
||||
Add(NULL);
|
||||
for (int i = path.length() - 1; i >= 0; --i) {
|
||||
Add(path[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HeapGraphPath::Print() {
|
||||
path_[0]->From()->Print(1, 0);
|
||||
for (int i = 0; i < path_.length(); ++i) {
|
||||
OS::Print(" -> ");
|
||||
HeapGraphEdge* edge = path_[i];
|
||||
switch (edge->type()) {
|
||||
case HeapGraphEdge::kContextVariable:
|
||||
OS::Print("[#%s] ", edge->name());
|
||||
break;
|
||||
case HeapGraphEdge::kElement:
|
||||
case HeapGraphEdge::kHidden:
|
||||
OS::Print("[%d] ", edge->index());
|
||||
break;
|
||||
case HeapGraphEdge::kInternal:
|
||||
OS::Print("[$%s] ", edge->name());
|
||||
break;
|
||||
case HeapGraphEdge::kProperty:
|
||||
OS::Print("[%s] ", edge->name());
|
||||
break;
|
||||
case HeapGraphEdge::kShortcut:
|
||||
OS::Print("[^%s] ", edge->name());
|
||||
break;
|
||||
default:
|
||||
OS::Print("!!! unknown edge type: %d ", edge->type());
|
||||
}
|
||||
edge->to()->Print(1, 0);
|
||||
}
|
||||
OS::Print("\n");
|
||||
}
|
||||
|
||||
|
||||
// It is very important to keep objects that form a heap snapshot
|
||||
// as small as possible.
|
||||
namespace { // Avoid littering the global namespace.
|
||||
@ -1278,8 +1172,7 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
|
||||
gc_roots_entry_(NULL),
|
||||
natives_root_entry_(NULL),
|
||||
raw_entries_(NULL),
|
||||
entries_sorted_(false),
|
||||
retaining_paths_(HeapEntry::Match) {
|
||||
entries_sorted_(false) {
|
||||
STATIC_ASSERT(
|
||||
sizeof(HeapGraphEdge) ==
|
||||
SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOLINT
|
||||
@ -1288,21 +1181,8 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
|
||||
SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT
|
||||
}
|
||||
|
||||
|
||||
static void DeleteHeapGraphPath(HeapGraphPath** path_ptr) {
|
||||
delete *path_ptr;
|
||||
}
|
||||
|
||||
HeapSnapshot::~HeapSnapshot() {
|
||||
DeleteArray(raw_entries_);
|
||||
for (HashMap::Entry* p = retaining_paths_.Start();
|
||||
p != NULL;
|
||||
p = retaining_paths_.Next(p)) {
|
||||
List<HeapGraphPath*>* list =
|
||||
reinterpret_cast<List<HeapGraphPath*>*>(p->value);
|
||||
list->Iterate(DeleteHeapGraphPath);
|
||||
delete list;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1404,14 +1284,7 @@ HeapEntry* HeapSnapshot::GetNextEntryToInit() {
|
||||
}
|
||||
|
||||
|
||||
HeapSnapshotsDiff* HeapSnapshot::CompareWith(HeapSnapshot* snapshot) {
|
||||
return collection_->CompareSnapshots(this, snapshot);
|
||||
}
|
||||
|
||||
|
||||
HeapEntry* HeapSnapshot::GetEntryById(uint64_t id) {
|
||||
// GetSortedEntriesList is used in diff algorithm and sorts
|
||||
// entries by their id.
|
||||
List<HeapEntry*>* entries_by_id = GetSortedEntriesList();
|
||||
|
||||
// Perform a binary search by id.
|
||||
@ -1432,16 +1305,6 @@ HeapEntry* HeapSnapshot::GetEntryById(uint64_t id) {
|
||||
}
|
||||
|
||||
|
||||
List<HeapGraphPath*>* HeapSnapshot::GetRetainingPaths(HeapEntry* entry) {
|
||||
HashMap::Entry* p =
|
||||
retaining_paths_.Lookup(entry, HeapEntry::Hash(entry), true);
|
||||
if (p->value == NULL) {
|
||||
p->value = entry->CalculateRetainingPaths();
|
||||
}
|
||||
return reinterpret_cast<List<HeapGraphPath*>*>(p->value);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
static int SortByIds(const T* entry1_ptr,
|
||||
const T* entry2_ptr) {
|
||||
@ -1631,13 +1494,6 @@ void HeapSnapshotsCollection::RemoveSnapshot(HeapSnapshot* snapshot) {
|
||||
}
|
||||
|
||||
|
||||
HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots(
|
||||
HeapSnapshot* snapshot1,
|
||||
HeapSnapshot* snapshot2) {
|
||||
return comparator_.Compare(snapshot1, snapshot2);
|
||||
}
|
||||
|
||||
|
||||
HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder =
|
||||
reinterpret_cast<HeapEntry*>(1);
|
||||
|
||||
@ -2804,83 +2660,6 @@ bool HeapSnapshotGenerator::ApproximateRetainedSizes() {
|
||||
}
|
||||
|
||||
|
||||
void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) {
|
||||
raw_additions_root_ =
|
||||
NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0));
|
||||
additions_root()->Init(
|
||||
snapshot2_, HeapEntry::kHidden, "", 0, 0, additions_count, 0);
|
||||
raw_deletions_root_ =
|
||||
NewArray<char>(HeapEntry::EntriesSize(1, deletions_count, 0));
|
||||
deletions_root()->Init(
|
||||
snapshot1_, HeapEntry::kHidden, "", 0, 0, deletions_count, 0);
|
||||
}
|
||||
|
||||
|
||||
static void DeleteHeapSnapshotsDiff(HeapSnapshotsDiff** diff_ptr) {
|
||||
delete *diff_ptr;
|
||||
}
|
||||
|
||||
HeapSnapshotsComparator::~HeapSnapshotsComparator() {
|
||||
diffs_.Iterate(DeleteHeapSnapshotsDiff);
|
||||
}
|
||||
|
||||
|
||||
HeapSnapshotsDiff* HeapSnapshotsComparator::Compare(HeapSnapshot* snapshot1,
|
||||
HeapSnapshot* snapshot2) {
|
||||
snapshot1->ClearPaint();
|
||||
snapshot1->root()->PaintAllReachable();
|
||||
snapshot2->ClearPaint();
|
||||
snapshot2->root()->PaintAllReachable();
|
||||
|
||||
List<HeapEntry*>* entries1 = snapshot1->GetSortedEntriesList();
|
||||
List<HeapEntry*>* entries2 = snapshot2->GetSortedEntriesList();
|
||||
int i = 0, j = 0;
|
||||
List<HeapEntry*> added_entries, deleted_entries;
|
||||
while (i < entries1->length() && j < entries2->length()) {
|
||||
uint64_t id1 = entries1->at(i)->id();
|
||||
uint64_t id2 = entries2->at(j)->id();
|
||||
if (id1 == id2) {
|
||||
HeapEntry* entry1 = entries1->at(i++);
|
||||
HeapEntry* entry2 = entries2->at(j++);
|
||||
if (entry1->painted_reachable() != entry2->painted_reachable()) {
|
||||
if (entry1->painted_reachable())
|
||||
deleted_entries.Add(entry1);
|
||||
else
|
||||
added_entries.Add(entry2);
|
||||
}
|
||||
} else if (id1 < id2) {
|
||||
HeapEntry* entry = entries1->at(i++);
|
||||
deleted_entries.Add(entry);
|
||||
} else {
|
||||
HeapEntry* entry = entries2->at(j++);
|
||||
added_entries.Add(entry);
|
||||
}
|
||||
}
|
||||
while (i < entries1->length()) {
|
||||
HeapEntry* entry = entries1->at(i++);
|
||||
deleted_entries.Add(entry);
|
||||
}
|
||||
while (j < entries2->length()) {
|
||||
HeapEntry* entry = entries2->at(j++);
|
||||
added_entries.Add(entry);
|
||||
}
|
||||
|
||||
HeapSnapshotsDiff* diff = new HeapSnapshotsDiff(snapshot1, snapshot2);
|
||||
diffs_.Add(diff);
|
||||
diff->CreateRoots(added_entries.length(), deleted_entries.length());
|
||||
|
||||
for (int i = 0; i < deleted_entries.length(); ++i) {
|
||||
HeapEntry* entry = deleted_entries[i];
|
||||
diff->AddDeletedEntry(i, i + 1, entry);
|
||||
}
|
||||
for (int i = 0; i < added_entries.length(); ++i) {
|
||||
HeapEntry* entry = added_entries[i];
|
||||
diff->AddAddedEntry(i, i + 1, entry);
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
|
||||
class OutputStreamWriter {
|
||||
public:
|
||||
explicit OutputStreamWriter(v8::OutputStream* stream)
|
||||
|
@ -490,8 +490,6 @@ class HeapGraphEdge BASE_EMBEDDED {
|
||||
};
|
||||
|
||||
|
||||
class CachedHeapGraphPath;
|
||||
class HeapGraphPath;
|
||||
class HeapSnapshot;
|
||||
|
||||
// HeapEntry instances represent an entity from the heap (or a special
|
||||
@ -551,7 +549,6 @@ class HeapEntry BASE_EMBEDDED {
|
||||
return Vector<HeapGraphEdge>(children_arr(), children_count_); }
|
||||
Vector<HeapGraphEdge*> retainers() {
|
||||
return Vector<HeapGraphEdge*>(retainers_arr(), retainers_count_); }
|
||||
List<HeapGraphPath*>* GetRetainingPaths();
|
||||
HeapEntry* dominator() { return dominator_; }
|
||||
void set_dominator(HeapEntry* entry) { dominator_ = entry; }
|
||||
|
||||
@ -585,18 +582,12 @@ class HeapEntry BASE_EMBEDDED {
|
||||
|
||||
int EntrySize() { return EntriesSize(1, children_count_, retainers_count_); }
|
||||
int RetainedSize(bool exact);
|
||||
List<HeapGraphPath*>* CalculateRetainingPaths();
|
||||
|
||||
void Print(int max_depth, int indent);
|
||||
|
||||
static int EntriesSize(int entries_count,
|
||||
int children_count,
|
||||
int retainers_count);
|
||||
static uint32_t Hash(HeapEntry* entry) {
|
||||
return ComputeIntegerHash(
|
||||
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(entry)));
|
||||
}
|
||||
static bool Match(void* entry1, void* entry2) { return entry1 == entry2; }
|
||||
|
||||
private:
|
||||
HeapGraphEdge* children_arr() {
|
||||
@ -606,8 +597,6 @@ class HeapEntry BASE_EMBEDDED {
|
||||
return reinterpret_cast<HeapGraphEdge**>(children_arr() + children_count_);
|
||||
}
|
||||
void CalculateExactRetainedSize();
|
||||
void FindRetainingPaths(CachedHeapGraphPath* prev_path,
|
||||
List<HeapGraphPath*>* retaining_paths);
|
||||
const char* TypeAsString();
|
||||
|
||||
unsigned painted_: 2;
|
||||
@ -638,27 +627,7 @@ class HeapEntry BASE_EMBEDDED {
|
||||
};
|
||||
|
||||
|
||||
class HeapGraphPath {
|
||||
public:
|
||||
HeapGraphPath()
|
||||
: path_(8) { }
|
||||
explicit HeapGraphPath(const List<HeapGraphEdge*>& path);
|
||||
|
||||
void Add(HeapGraphEdge* edge) { path_.Add(edge); }
|
||||
void Set(int index, HeapGraphEdge* edge) { path_[index] = edge; }
|
||||
const List<HeapGraphEdge*>* path() { return &path_; }
|
||||
|
||||
void Print();
|
||||
|
||||
private:
|
||||
List<HeapGraphEdge*> path_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(HeapGraphPath);
|
||||
};
|
||||
|
||||
|
||||
class HeapSnapshotsCollection;
|
||||
class HeapSnapshotsDiff;
|
||||
|
||||
// HeapSnapshot represents a single heap snapshot. It is stored in
|
||||
// HeapSnapshotsCollection, which is also a factory for
|
||||
@ -700,9 +669,7 @@ class HeapSnapshot {
|
||||
HeapEntry* AddGcRootsEntry(int children_count, int retainers_count);
|
||||
HeapEntry* AddNativesRootEntry(int children_count, int retainers_count);
|
||||
void ClearPaint();
|
||||
HeapSnapshotsDiff* CompareWith(HeapSnapshot* snapshot);
|
||||
HeapEntry* GetEntryById(uint64_t id);
|
||||
List<HeapGraphPath*>* GetRetainingPaths(HeapEntry* entry);
|
||||
List<HeapEntry*>* GetSortedEntriesList();
|
||||
template<class Visitor>
|
||||
void IterateEntries(Visitor* visitor) { entries_.Iterate(visitor); }
|
||||
@ -724,7 +691,6 @@ class HeapSnapshot {
|
||||
char* raw_entries_;
|
||||
List<HeapEntry*> entries_;
|
||||
bool entries_sorted_;
|
||||
HashMap retaining_paths_;
|
||||
#ifdef DEBUG
|
||||
int raw_entries_size_;
|
||||
#endif
|
||||
@ -781,58 +747,6 @@ class HeapObjectsMap {
|
||||
};
|
||||
|
||||
|
||||
class HeapSnapshotsDiff {
|
||||
public:
|
||||
HeapSnapshotsDiff(HeapSnapshot* snapshot1, HeapSnapshot* snapshot2)
|
||||
: snapshot1_(snapshot1),
|
||||
snapshot2_(snapshot2),
|
||||
raw_additions_root_(NULL),
|
||||
raw_deletions_root_(NULL) { }
|
||||
|
||||
~HeapSnapshotsDiff() {
|
||||
DeleteArray(raw_deletions_root_);
|
||||
DeleteArray(raw_additions_root_);
|
||||
}
|
||||
|
||||
void AddAddedEntry(int child_index, int index, HeapEntry* entry) {
|
||||
additions_root()->SetUnidirElementReference(child_index, index, entry);
|
||||
}
|
||||
|
||||
void AddDeletedEntry(int child_index, int index, HeapEntry* entry) {
|
||||
deletions_root()->SetUnidirElementReference(child_index, index, entry);
|
||||
}
|
||||
|
||||
void CreateRoots(int additions_count, int deletions_count);
|
||||
|
||||
HeapEntry* additions_root() {
|
||||
return reinterpret_cast<HeapEntry*>(raw_additions_root_);
|
||||
}
|
||||
HeapEntry* deletions_root() {
|
||||
return reinterpret_cast<HeapEntry*>(raw_deletions_root_);
|
||||
}
|
||||
|
||||
private:
|
||||
HeapSnapshot* snapshot1_;
|
||||
HeapSnapshot* snapshot2_;
|
||||
char* raw_additions_root_;
|
||||
char* raw_deletions_root_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsDiff);
|
||||
};
|
||||
|
||||
|
||||
class HeapSnapshotsComparator {
|
||||
public:
|
||||
HeapSnapshotsComparator() { }
|
||||
~HeapSnapshotsComparator();
|
||||
HeapSnapshotsDiff* Compare(HeapSnapshot* snapshot1, HeapSnapshot* snapshot2);
|
||||
private:
|
||||
List<HeapSnapshotsDiff*> diffs_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsComparator);
|
||||
};
|
||||
|
||||
|
||||
class HeapSnapshotsCollection {
|
||||
public:
|
||||
HeapSnapshotsCollection();
|
||||
@ -853,9 +767,6 @@ class HeapSnapshotsCollection {
|
||||
uint64_t GetObjectId(Address addr) { return ids_.FindObject(addr); }
|
||||
void ObjectMoveEvent(Address from, Address to) { ids_.MoveObject(from, to); }
|
||||
|
||||
HeapSnapshotsDiff* CompareSnapshots(HeapSnapshot* snapshot1,
|
||||
HeapSnapshot* snapshot2);
|
||||
|
||||
private:
|
||||
INLINE(static bool HeapSnapshotsMatch(void* key1, void* key2)) {
|
||||
return key1 == key2;
|
||||
@ -869,7 +780,6 @@ class HeapSnapshotsCollection {
|
||||
TokenEnumerator* token_enumerator_;
|
||||
// Mapping from HeapObject addresses to objects' uids.
|
||||
HeapObjectsMap ids_;
|
||||
HeapSnapshotsComparator comparator_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsCollection);
|
||||
};
|
||||
|
@ -36,11 +36,6 @@ test-debug/DebuggerAgent: PASS, (PASS || FAIL) if $system == linux
|
||||
# BUG(382): Weird test. Can't guarantee that it never times out.
|
||||
test-api/ApplyInterruption: PASS || TIMEOUT
|
||||
|
||||
# BUG(484): This test which we thought was originally corrected in r5236
|
||||
# is re-appearing. Disabled until bug in test is fixed. This only fails
|
||||
# when snapshot is on, so I am marking it PASS || FAIL
|
||||
test-heap-profiler/HeapSnapshotsDiff: PASS || FAIL
|
||||
|
||||
# These tests always fail. They are here to test test.py. If
|
||||
# they don't fail then test.py has failed.
|
||||
test-serialize/TestThatAlwaysFails: FAIL
|
||||
|
@ -433,19 +433,6 @@ static const v8::HeapGraphNode* GetProperty(const v8::HeapGraphNode* node,
|
||||
}
|
||||
|
||||
|
||||
static bool IsNodeRetainedAs(const v8::HeapGraphNode* node,
|
||||
v8::HeapGraphEdge::Type type,
|
||||
const char* name) {
|
||||
for (int i = 0, count = node->GetRetainersCount(); i < count; ++i) {
|
||||
const v8::HeapGraphEdge* prop = node->GetRetainer(i);
|
||||
v8::String::AsciiValue prop_name(prop->GetName());
|
||||
if (prop->GetType() == type && strcmp(name, *prop_name) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool HasString(const v8::HeapGraphNode* node, const char* contents) {
|
||||
for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
|
||||
const v8::HeapGraphEdge* prop = node->GetChild(i);
|
||||
@ -496,56 +483,6 @@ TEST(HeapSnapshot) {
|
||||
CHECK(det.has_A2);
|
||||
CHECK(det.has_B2);
|
||||
CHECK(det.has_C2);
|
||||
|
||||
/*
|
||||
// Currently disabled. Too many retaining paths emerge, need to
|
||||
// reduce the amount.
|
||||
|
||||
// Verify 'a2' object retainers. They are:
|
||||
// - (global object).a2
|
||||
// - c2.x1, c2.x2, c2[1]
|
||||
// - b2_1 and b2_2 closures: via 'x' variable
|
||||
CHECK_EQ(6, a2_node->GetRetainingPathsCount());
|
||||
bool has_global_obj_a2_ref = false;
|
||||
bool has_c2_x1_ref = false, has_c2_x2_ref = false, has_c2_1_ref = false;
|
||||
bool has_b2_1_x_ref = false, has_b2_2_x_ref = false;
|
||||
for (int i = 0; i < a2_node->GetRetainingPathsCount(); ++i) {
|
||||
const v8::HeapGraphPath* path = a2_node->GetRetainingPath(i);
|
||||
const int edges_count = path->GetEdgesCount();
|
||||
CHECK_GT(edges_count, 0);
|
||||
const v8::HeapGraphEdge* last_edge = path->GetEdge(edges_count - 1);
|
||||
v8::String::AsciiValue last_edge_name(last_edge->GetName());
|
||||
if (strcmp("a2", *last_edge_name) == 0
|
||||
&& last_edge->GetType() == v8::HeapGraphEdge::kProperty) {
|
||||
has_global_obj_a2_ref = true;
|
||||
continue;
|
||||
}
|
||||
CHECK_GT(edges_count, 1);
|
||||
const v8::HeapGraphEdge* prev_edge = path->GetEdge(edges_count - 2);
|
||||
v8::String::AsciiValue prev_edge_name(prev_edge->GetName());
|
||||
if (strcmp("x1", *last_edge_name) == 0
|
||||
&& last_edge->GetType() == v8::HeapGraphEdge::kProperty
|
||||
&& strcmp("c2", *prev_edge_name) == 0) has_c2_x1_ref = true;
|
||||
if (strcmp("x2", *last_edge_name) == 0
|
||||
&& last_edge->GetType() == v8::HeapGraphEdge::kProperty
|
||||
&& strcmp("c2", *prev_edge_name) == 0) has_c2_x2_ref = true;
|
||||
if (strcmp("1", *last_edge_name) == 0
|
||||
&& last_edge->GetType() == v8::HeapGraphEdge::kElement
|
||||
&& strcmp("c2", *prev_edge_name) == 0) has_c2_1_ref = true;
|
||||
if (strcmp("x", *last_edge_name) == 0
|
||||
&& last_edge->GetType() == v8::HeapGraphEdge::kContextVariable
|
||||
&& strcmp("b2_1", *prev_edge_name) == 0) has_b2_1_x_ref = true;
|
||||
if (strcmp("x", *last_edge_name) == 0
|
||||
&& last_edge->GetType() == v8::HeapGraphEdge::kContextVariable
|
||||
&& strcmp("b2_2", *prev_edge_name) == 0) has_b2_2_x_ref = true;
|
||||
}
|
||||
CHECK(has_global_obj_a2_ref);
|
||||
CHECK(has_c2_x1_ref);
|
||||
CHECK(has_c2_x2_ref);
|
||||
CHECK(has_c2_1_ref);
|
||||
CHECK(has_b2_1_x_ref);
|
||||
CHECK(has_b2_2_x_ref);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@ -774,76 +711,6 @@ TEST(HeapEntryIdsAndGC) {
|
||||
}
|
||||
|
||||
|
||||
TEST(HeapSnapshotsDiff) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
|
||||
CompileRun(
|
||||
"function A() {}\n"
|
||||
"function B(x) { this.x = x; }\n"
|
||||
"function A2(a) { for (var i = 0; i < a; ++i) this[i] = i; }\n"
|
||||
"var a = new A();\n"
|
||||
"var b = new B(a);");
|
||||
const v8::HeapSnapshot* snapshot1 =
|
||||
v8::HeapProfiler::TakeSnapshot(v8::String::New("s1"));
|
||||
|
||||
CompileRun(
|
||||
"delete a;\n"
|
||||
"b.x = null;\n"
|
||||
"var a = new A2(20);\n"
|
||||
"var b2 = new B(a);");
|
||||
const v8::HeapSnapshot* snapshot2 =
|
||||
v8::HeapProfiler::TakeSnapshot(v8::String::New("s2"));
|
||||
|
||||
const v8::HeapSnapshotsDiff* diff = snapshot1->CompareWith(snapshot2);
|
||||
|
||||
// Verify additions: ensure that addition of A and B was detected.
|
||||
const v8::HeapGraphNode* additions_root = diff->GetAdditionsRoot();
|
||||
bool found_A = false, found_B = false;
|
||||
uint64_t s1_A_id = 0;
|
||||
for (int i = 0, count = additions_root->GetChildrenCount(); i < count; ++i) {
|
||||
const v8::HeapGraphEdge* prop = additions_root->GetChild(i);
|
||||
const v8::HeapGraphNode* node = prop->GetToNode();
|
||||
if (node->GetType() == v8::HeapGraphNode::kObject) {
|
||||
v8::String::AsciiValue node_name(node->GetName());
|
||||
if (strcmp(*node_name, "A2") == 0) {
|
||||
CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "a"));
|
||||
CHECK(!found_A);
|
||||
found_A = true;
|
||||
s1_A_id = node->GetId();
|
||||
} else if (strcmp(*node_name, "B") == 0) {
|
||||
CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "b2"));
|
||||
CHECK(!found_B);
|
||||
found_B = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
CHECK(found_A);
|
||||
CHECK(found_B);
|
||||
|
||||
// Verify deletions: ensure that deletion of A was detected.
|
||||
const v8::HeapGraphNode* deletions_root = diff->GetDeletionsRoot();
|
||||
bool found_A_del = false;
|
||||
uint64_t s2_A_id = 0;
|
||||
for (int i = 0, count = deletions_root->GetChildrenCount(); i < count; ++i) {
|
||||
const v8::HeapGraphEdge* prop = deletions_root->GetChild(i);
|
||||
const v8::HeapGraphNode* node = prop->GetToNode();
|
||||
if (node->GetType() == v8::HeapGraphNode::kObject) {
|
||||
v8::String::AsciiValue node_name(node->GetName());
|
||||
if (strcmp(*node_name, "A") == 0) {
|
||||
CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "a"));
|
||||
CHECK(!found_A_del);
|
||||
found_A_del = true;
|
||||
s2_A_id = node->GetId();
|
||||
}
|
||||
}
|
||||
}
|
||||
CHECK(found_A_del);
|
||||
CHECK_NE_UINT64_T(0, s1_A_id);
|
||||
CHECK(s1_A_id != s2_A_id);
|
||||
}
|
||||
|
||||
|
||||
TEST(HeapSnapshotRootPreservedAfterSorting) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
|
Loading…
Reference in New Issue
Block a user