External references should not affect dominance relation.
Review URL: https://chromiumcodereview.appspot.com/10007009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11247 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
502036ae06
commit
5ed3662407
@ -5998,7 +5998,7 @@ Handle<Value> HeapGraphEdge::GetName() const {
|
||||
const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
|
||||
i::Isolate* isolate = i::Isolate::Current();
|
||||
IsDeadCheck(isolate, "v8::HeapGraphEdge::GetFromNode");
|
||||
const i::HeapEntry* from = ToInternal(this)->From();
|
||||
const i::HeapEntry* from = ToInternal(this)->from();
|
||||
return reinterpret_cast<const HeapGraphNode*>(from);
|
||||
}
|
||||
|
||||
|
@ -95,6 +95,11 @@ CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) {
|
||||
}
|
||||
|
||||
|
||||
HeapEntry* HeapGraphEdge::from() {
|
||||
return reinterpret_cast<HeapEntry*>(this - child_index_) - 1;
|
||||
}
|
||||
|
||||
|
||||
SnapshotObjectId HeapObjectsMap::GetNthGcSubrootId(int delta) {
|
||||
return kGcRootsFirstSubrootId + delta * kObjectIdStep;
|
||||
}
|
||||
|
@ -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;
|
||||
@ -2178,15 +2174,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2637,7 +2633,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) &&
|
||||
@ -3191,19 +3187,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);
|
||||
@ -3238,6 +3270,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;
|
||||
@ -3266,8 +3299,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
|
||||
@ -3293,9 +3326,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) {
|
||||
|
@ -477,8 +477,7 @@ class HeapGraphEdge BASE_EMBEDDED {
|
||||
return name_;
|
||||
}
|
||||
HeapEntry* to() { return to_; }
|
||||
|
||||
HeapEntry* From();
|
||||
INLINE(HeapEntry* from());
|
||||
|
||||
private:
|
||||
int child_index_ : 29;
|
||||
@ -564,6 +563,8 @@ class HeapEntry BASE_EMBEDDED {
|
||||
void clear_paint() { painted_ = false; }
|
||||
bool painted() { return painted_; }
|
||||
void paint() { painted_ = true; }
|
||||
bool reachable_from_window() { return reachable_from_window_; }
|
||||
void set_reachable_from_window() { reachable_from_window_ = true; }
|
||||
|
||||
void SetIndexedReference(HeapGraphEdge::Type type,
|
||||
int child_index,
|
||||
@ -600,8 +601,9 @@ class HeapEntry BASE_EMBEDDED {
|
||||
const char* TypeAsString();
|
||||
|
||||
unsigned painted_: 1;
|
||||
unsigned reachable_from_window_: 1;
|
||||
unsigned type_: 4;
|
||||
int children_count_: 27;
|
||||
int children_count_: 26;
|
||||
int retainers_count_;
|
||||
int self_size_;
|
||||
union {
|
||||
@ -1100,7 +1102,8 @@ class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface {
|
||||
bool CalculateRetainedSizes();
|
||||
bool CountEntriesAndReferences();
|
||||
bool FillReferences();
|
||||
void FillReversePostorderIndexes(Vector<HeapEntry*>* entries);
|
||||
void FillPostorderIndexes(Vector<HeapEntry*>* entries);
|
||||
void MarkWindowReachableObjects();
|
||||
void ProgressStep();
|
||||
bool ProgressReport(bool force = false);
|
||||
bool SetEntriesDominators();
|
||||
|
@ -109,13 +109,13 @@ TEST(HeapSnapshot) {
|
||||
|
||||
// Verify, that JS global object of env2 has '..2' properties.
|
||||
const v8::HeapGraphNode* a2_node =
|
||||
GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "a2");
|
||||
GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "a2");
|
||||
CHECK_NE(NULL, a2_node);
|
||||
CHECK_NE(
|
||||
NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_1"));
|
||||
NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_1"));
|
||||
CHECK_NE(
|
||||
NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_2"));
|
||||
CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "c2"));
|
||||
NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_2"));
|
||||
CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "c2"));
|
||||
|
||||
// Paint all nodes reachable from global object.
|
||||
NamedEntriesDetector det;
|
||||
@ -142,7 +142,7 @@ TEST(HeapSnapshotObjectSizes) {
|
||||
v8::HeapProfiler::TakeSnapshot(v8_str("sizes"));
|
||||
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
|
||||
const v8::HeapGraphNode* x =
|
||||
GetProperty(global, v8::HeapGraphEdge::kShortcut, "x");
|
||||
GetProperty(global, v8::HeapGraphEdge::kProperty, "x");
|
||||
CHECK_NE(NULL, x);
|
||||
const v8::HeapGraphNode* x1 =
|
||||
GetProperty(x, v8::HeapGraphEdge::kProperty, "a");
|
||||
@ -169,7 +169,7 @@ TEST(BoundFunctionInSnapshot) {
|
||||
v8::HeapProfiler::TakeSnapshot(v8_str("sizes"));
|
||||
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
|
||||
const v8::HeapGraphNode* f =
|
||||
GetProperty(global, v8::HeapGraphEdge::kShortcut, "boundFunction");
|
||||
GetProperty(global, v8::HeapGraphEdge::kProperty, "boundFunction");
|
||||
CHECK(f);
|
||||
CHECK_EQ(v8::String::New("native_bind"), f->GetName());
|
||||
const v8::HeapGraphNode* bindings =
|
||||
@ -233,15 +233,15 @@ TEST(HeapSnapshotCodeObjects) {
|
||||
|
||||
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
|
||||
const v8::HeapGraphNode* compiled =
|
||||
GetProperty(global, v8::HeapGraphEdge::kShortcut, "compiled");
|
||||
GetProperty(global, v8::HeapGraphEdge::kProperty, "compiled");
|
||||
CHECK_NE(NULL, compiled);
|
||||
CHECK_EQ(v8::HeapGraphNode::kClosure, compiled->GetType());
|
||||
const v8::HeapGraphNode* lazy =
|
||||
GetProperty(global, v8::HeapGraphEdge::kShortcut, "lazy");
|
||||
GetProperty(global, v8::HeapGraphEdge::kProperty, "lazy");
|
||||
CHECK_NE(NULL, lazy);
|
||||
CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType());
|
||||
const v8::HeapGraphNode* anonymous =
|
||||
GetProperty(global, v8::HeapGraphEdge::kShortcut, "anonymous");
|
||||
GetProperty(global, v8::HeapGraphEdge::kProperty, "anonymous");
|
||||
CHECK_NE(NULL, anonymous);
|
||||
CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType());
|
||||
v8::String::AsciiValue anonymous_name(anonymous->GetName());
|
||||
@ -293,9 +293,9 @@ TEST(HeapSnapshotHeapNumbers) {
|
||||
const v8::HeapSnapshot* snapshot =
|
||||
v8::HeapProfiler::TakeSnapshot(v8_str("numbers"));
|
||||
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
|
||||
CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kShortcut, "a"));
|
||||
CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kProperty, "a"));
|
||||
const v8::HeapGraphNode* b =
|
||||
GetProperty(global, v8::HeapGraphEdge::kShortcut, "b");
|
||||
GetProperty(global, v8::HeapGraphEdge::kProperty, "b");
|
||||
CHECK_NE(NULL, b);
|
||||
CHECK_EQ(v8::HeapGraphNode::kHeapNumber, b->GetType());
|
||||
}
|
||||
@ -313,10 +313,10 @@ TEST(HeapSnapshotSlicedString) {
|
||||
v8::HeapProfiler::TakeSnapshot(v8_str("strings"));
|
||||
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
|
||||
const v8::HeapGraphNode* parent_string =
|
||||
GetProperty(global, v8::HeapGraphEdge::kShortcut, "parent_string");
|
||||
GetProperty(global, v8::HeapGraphEdge::kProperty, "parent_string");
|
||||
CHECK_NE(NULL, parent_string);
|
||||
const v8::HeapGraphNode* child_string =
|
||||
GetProperty(global, v8::HeapGraphEdge::kShortcut, "child_string");
|
||||
GetProperty(global, v8::HeapGraphEdge::kProperty, "child_string");
|
||||
CHECK_NE(NULL, child_string);
|
||||
const v8::HeapGraphNode* parent =
|
||||
GetProperty(child_string, v8::HeapGraphEdge::kInternal, "parent");
|
||||
@ -384,24 +384,17 @@ TEST(HeapEntryIdsAndArrayShift) {
|
||||
const v8::HeapGraphNode* a1 =
|
||||
GetProperty(global1, v8::HeapGraphEdge::kProperty, "a");
|
||||
CHECK_NE(NULL, a1);
|
||||
const v8::HeapGraphNode* e1 =
|
||||
GetProperty(a1, v8::HeapGraphEdge::kHidden, "1");
|
||||
CHECK_NE(NULL, e1);
|
||||
const v8::HeapGraphNode* k1 =
|
||||
GetProperty(e1, v8::HeapGraphEdge::kInternal, "elements");
|
||||
GetProperty(a1, v8::HeapGraphEdge::kInternal, "elements");
|
||||
CHECK_NE(NULL, k1);
|
||||
const v8::HeapGraphNode* a2 =
|
||||
GetProperty(global2, v8::HeapGraphEdge::kProperty, "a");
|
||||
CHECK_NE(NULL, a2);
|
||||
const v8::HeapGraphNode* e2 =
|
||||
GetProperty(a2, v8::HeapGraphEdge::kHidden, "1");
|
||||
CHECK_NE(NULL, e2);
|
||||
const v8::HeapGraphNode* k2 =
|
||||
GetProperty(e2, v8::HeapGraphEdge::kInternal, "elements");
|
||||
GetProperty(a2, v8::HeapGraphEdge::kInternal, "elements");
|
||||
CHECK_NE(NULL, k2);
|
||||
|
||||
CHECK_EQ_SNAPSHOT_OBJECT_ID(a1->GetId(), a2->GetId());
|
||||
CHECK_EQ_SNAPSHOT_OBJECT_ID(e1->GetId(), e2->GetId());
|
||||
CHECK_EQ_SNAPSHOT_OBJECT_ID(k1->GetId(), k2->GetId());
|
||||
}
|
||||
|
||||
@ -514,7 +507,7 @@ TEST(HeapEntryDominator) {
|
||||
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
|
||||
CHECK_NE(NULL, global);
|
||||
const v8::HeapGraphNode* node6 =
|
||||
GetProperty(global, v8::HeapGraphEdge::kShortcut, "node6");
|
||||
GetProperty(global, v8::HeapGraphEdge::kProperty, "node6");
|
||||
CHECK_NE(NULL, node6);
|
||||
const v8::HeapGraphNode* node5 =
|
||||
GetProperty(node6, v8::HeapGraphEdge::kProperty, "a");
|
||||
@ -658,7 +651,7 @@ TEST(HeapSnapshotJSONSerialization) {
|
||||
" GetChildPosByProperty(\n"
|
||||
" GetChildPosByProperty("
|
||||
" parsed.nodes[1 + children_offset + child_to_node_offset],"
|
||||
" \"b\",shortcut_type),\n"
|
||||
" \"b\", property_type),\n"
|
||||
" \"x\", property_type),"
|
||||
" \"s\", property_type)");
|
||||
CHECK(!string_obj_pos_val.IsEmpty());
|
||||
@ -959,9 +952,8 @@ TEST(HeapSnapshotImplicitReferences) {
|
||||
v8::HeapProfiler::TakeSnapshot(v8_str("implicit_refs"));
|
||||
|
||||
const v8::HeapGraphNode* global_object = GetGlobalObject(snapshot);
|
||||
// Use kShortcut type to skip intermediate JSGlobalPropertyCell
|
||||
const v8::HeapGraphNode* obj0 = GetProperty(
|
||||
global_object, v8::HeapGraphEdge::kShortcut, "root_object");
|
||||
global_object, v8::HeapGraphEdge::kProperty, "root_object");
|
||||
CHECK(obj0);
|
||||
CHECK_EQ(v8::HeapGraphNode::kObject, obj0->GetType());
|
||||
const v8::HeapGraphNode* obj1 = GetProperty(
|
||||
@ -1134,7 +1126,7 @@ TEST(GetHeapValue) {
|
||||
env->Global()->GetPrototype().As<v8::Object>();
|
||||
CHECK(js_global == global->GetHeapValue());
|
||||
const v8::HeapGraphNode* obj = GetProperty(
|
||||
global, v8::HeapGraphEdge::kShortcut, "a");
|
||||
global, v8::HeapGraphEdge::kProperty, "a");
|
||||
CHECK(obj->GetHeapValue()->IsObject());
|
||||
v8::Local<v8::Object> js_obj = js_global->Get(v8_str("a")).As<v8::Object>();
|
||||
CHECK(js_obj == obj->GetHeapValue());
|
||||
@ -1163,7 +1155,7 @@ TEST(GetHeapValueForDeletedObject) {
|
||||
v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
|
||||
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
|
||||
const v8::HeapGraphNode* obj = GetProperty(
|
||||
global, v8::HeapGraphEdge::kShortcut, "a");
|
||||
global, v8::HeapGraphEdge::kProperty, "a");
|
||||
const v8::HeapGraphNode* prop = GetProperty(
|
||||
obj, v8::HeapGraphEdge::kProperty, "p");
|
||||
{
|
||||
@ -1250,7 +1242,7 @@ TEST(FastCaseGetter) {
|
||||
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
|
||||
CHECK_NE(NULL, global);
|
||||
const v8::HeapGraphNode* obj1 =
|
||||
GetProperty(global, v8::HeapGraphEdge::kShortcut, "obj1");
|
||||
GetProperty(global, v8::HeapGraphEdge::kProperty, "obj1");
|
||||
CHECK_NE(NULL, obj1);
|
||||
const v8::HeapGraphNode* getterFunction =
|
||||
GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get-propWithGetter");
|
||||
@ -1332,7 +1324,7 @@ TEST(SfiAndJsFunctionWeakRefs) {
|
||||
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
|
||||
CHECK_NE(NULL, global);
|
||||
const v8::HeapGraphNode* fun =
|
||||
GetProperty(global, v8::HeapGraphEdge::kShortcut, "fun");
|
||||
GetProperty(global, v8::HeapGraphEdge::kProperty, "fun");
|
||||
CHECK(HasWeakEdge(fun));
|
||||
const v8::HeapGraphNode* shared =
|
||||
GetProperty(fun, v8::HeapGraphEdge::kInternal, "shared");
|
||||
|
Loading…
Reference in New Issue
Block a user