| Index: src/profile-generator.cc
|
| diff --git a/src/profile-generator.cc b/src/profile-generator.cc
|
| index c81354f7a459848d64a8fd91e510470bcf2a6eed..79dd264765e73e1110be5e8ce6f6c00096bb819d 100644
|
| --- a/src/profile-generator.cc
|
| +++ b/src/profile-generator.cc
|
| @@ -957,11 +957,6 @@ void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) {
|
| }
|
|
|
|
|
| -HeapEntry* HeapGraphEdge::From() {
|
| - return reinterpret_cast<HeapEntry*>(this - child_index_) - 1;
|
| -}
|
| -
|
| -
|
| void HeapEntry::Init(HeapSnapshot* snapshot,
|
| Type type,
|
| const char* name,
|
| @@ -972,6 +967,7 @@ void HeapEntry::Init(HeapSnapshot* snapshot,
|
| snapshot_ = snapshot;
|
| type_ = type;
|
| painted_ = false;
|
| + reachable_from_window_ = false;
|
| name_ = name;
|
| self_size_ = self_size;
|
| retained_size_ = 0;
|
| @@ -2158,15 +2154,15 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj,
|
| Object* k = dictionary->KeyAt(i);
|
| if (dictionary->IsKey(k)) {
|
| Object* target = dictionary->ValueAt(i);
|
| - SetPropertyReference(
|
| - js_obj, entry, String::cast(k), target);
|
| // We assume that global objects can only have slow properties.
|
| - if (target->IsJSGlobalPropertyCell()) {
|
| - SetPropertyShortcutReference(js_obj,
|
| - entry,
|
| - String::cast(k),
|
| - JSGlobalPropertyCell::cast(
|
| - target)->value());
|
| + Object* value = target->IsJSGlobalPropertyCell()
|
| + ? JSGlobalPropertyCell::cast(target)->value()
|
| + : target;
|
| + if (String::cast(k)->length() > 0) {
|
| + SetPropertyReference(js_obj, entry, String::cast(k), value);
|
| + } else {
|
| + TagObject(value, "(hidden properties)");
|
| + SetInternalReference(js_obj, entry, "hidden_properties", value);
|
| }
|
| }
|
| }
|
| @@ -2617,7 +2613,7 @@ void V8HeapExplorer::TagGlobalObjects() {
|
| Handle<JSGlobalObject> global_obj = enumerator.at(i);
|
| Object* obj_document;
|
| if (global_obj->GetProperty(*document_string)->ToObject(&obj_document) &&
|
| - obj_document->IsJSObject()) {
|
| + obj_document->IsJSObject()) {
|
| JSObject* document = JSObject::cast(obj_document);
|
| Object* obj_url;
|
| if (document->GetProperty(*url_string)->ToObject(&obj_url) &&
|
| @@ -3171,19 +3167,55 @@ bool HeapSnapshotGenerator::FillReferences() {
|
| }
|
|
|
|
|
| -void HeapSnapshotGenerator::FillReversePostorderIndexes(
|
| +void HeapSnapshotGenerator::MarkWindowReachableObjects() {
|
| + List<HeapEntry*> worklist;
|
| +
|
| + Vector<HeapGraphEdge> children = snapshot_->root()->children();
|
| + for (int i = 0; i < children.length(); ++i) {
|
| + if (children[i].type() == HeapGraphEdge::kShortcut) {
|
| + worklist.Add(children[i].to());
|
| + }
|
| + }
|
| +
|
| + while (!worklist.is_empty()) {
|
| + HeapEntry* entry = worklist.RemoveLast();
|
| + if (entry->reachable_from_window()) continue;
|
| + entry->set_reachable_from_window();
|
| + Vector<HeapGraphEdge> children = entry->children();
|
| + for (int i = 0; i < children.length(); ++i) {
|
| + HeapEntry* child = children[i].to();
|
| + if (!child->reachable_from_window()) {
|
| + worklist.Add(child);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +static bool IsRetainingEdge(HeapGraphEdge* edge) {
|
| + if (edge->type() == HeapGraphEdge::kShortcut) return false;
|
| + // The edge is not retaining if it goes from system domain
|
| + // (i.e. an object not reachable from window) to the user domain
|
| + // (i.e. a reachable object).
|
| + return edge->from()->reachable_from_window()
|
| + || !edge->to()->reachable_from_window();
|
| +}
|
| +
|
| +
|
| +void HeapSnapshotGenerator::FillPostorderIndexes(
|
| Vector<HeapEntry*>* entries) {
|
| snapshot_->ClearPaint();
|
| int current_entry = 0;
|
| List<HeapEntry*> nodes_to_visit;
|
| - nodes_to_visit.Add(snapshot_->root());
|
| + HeapEntry* root = snapshot_->root();
|
| + nodes_to_visit.Add(root);
|
| snapshot_->root()->paint();
|
| while (!nodes_to_visit.is_empty()) {
|
| HeapEntry* entry = nodes_to_visit.last();
|
| Vector<HeapGraphEdge> children = entry->children();
|
| bool has_new_edges = false;
|
| for (int i = 0; i < children.length(); ++i) {
|
| - if (children[i].type() == HeapGraphEdge::kShortcut) continue;
|
| + if (entry != root && !IsRetainingEdge(&children[i])) continue;
|
| HeapEntry* child = children[i].to();
|
| if (!child->painted()) {
|
| nodes_to_visit.Add(child);
|
| @@ -3218,6 +3250,7 @@ bool HeapSnapshotGenerator::BuildDominatorTree(
|
| const Vector<HeapEntry*>& entries,
|
| Vector<int>* dominators) {
|
| if (entries.length() == 0) return true;
|
| + HeapEntry* root = snapshot_->root();
|
| const int entries_length = entries.length(), root_index = entries_length - 1;
|
| static const int kNoDominator = -1;
|
| for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator;
|
| @@ -3246,8 +3279,8 @@ bool HeapSnapshotGenerator::BuildDominatorTree(
|
| int new_idom_index = kNoDominator;
|
| Vector<HeapGraphEdge*> rets = entries[i]->retainers();
|
| for (int j = 0; j < rets.length(); ++j) {
|
| - if (rets[j]->type() == HeapGraphEdge::kShortcut) continue;
|
| - int ret_index = rets[j]->From()->ordered_index();
|
| + if (rets[j]->from() != root && !IsRetainingEdge(rets[j])) continue;
|
| + int ret_index = rets[j]->from()->ordered_index();
|
| if (dominators->at(ret_index) != kNoDominator) {
|
| new_idom_index = new_idom_index == kNoDominator
|
| ? ret_index
|
| @@ -3273,9 +3306,10 @@ bool HeapSnapshotGenerator::BuildDominatorTree(
|
|
|
|
|
| bool HeapSnapshotGenerator::SetEntriesDominators() {
|
| - // This array is used for maintaining reverse postorder of nodes.
|
| + MarkWindowReachableObjects();
|
| + // This array is used for maintaining postorder of nodes.
|
| ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length());
|
| - FillReversePostorderIndexes(&ordered_entries);
|
| + FillPostorderIndexes(&ordered_entries);
|
| ScopedVector<int> dominators(ordered_entries.length());
|
| if (!BuildDominatorTree(ordered_entries, &dominators)) return false;
|
| for (int i = 0; i < ordered_entries.length(); ++i) {
|
|
|