Commit a13ad531 authored by yurys@chromium.org's avatar yurys@chromium.org

Heap profiler should report implicit references.

Implicit references reported to V8 with V8::AddImplicitReferences calls are now reported by heap profiler as 'native' references with type kInternal.

Original WebKit bug report: https://bugs.webkit.org/show_bug.cgi?id=77414
Review URL: https://chromiumcodereview.appspot.com/9316092

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10603 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 405b875f
...@@ -2783,6 +2783,27 @@ void NativeObjectsExplorer::FillRetainedObjects() { ...@@ -2783,6 +2783,27 @@ void NativeObjectsExplorer::FillRetainedObjects() {
embedder_queried_ = true; embedder_queried_ = true;
} }
void NativeObjectsExplorer::FillImplicitReferences() {
Isolate* isolate = Isolate::Current();
List<ImplicitRefGroup*>* groups =
isolate->global_handles()->implicit_ref_groups();
for (int i = 0; i < groups->length(); ++i) {
ImplicitRefGroup* group = groups->at(i);
HeapObject* parent = *group->parent_;
HeapEntry* parent_entry = filler_->FindOrAddEntry(parent, this);
ASSERT(parent_entry != NULL);
Object*** children = group->children_;
for (size_t j = 0; j < group->length_; ++j) {
Object* child = *children[j];
HeapEntry* child_entry = filler_->FindOrAddEntry(child, this);
filler_->SetNamedReference(
HeapGraphEdge::kInternal,
parent, parent_entry,
"native",
child, child_entry);
}
}
}
List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo( List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo(
v8::RetainedObjectInfo* info) { v8::RetainedObjectInfo* info) {
...@@ -2799,22 +2820,24 @@ List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo( ...@@ -2799,22 +2820,24 @@ List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo(
bool NativeObjectsExplorer::IterateAndExtractReferences( bool NativeObjectsExplorer::IterateAndExtractReferences(
SnapshotFillerInterface* filler) { SnapshotFillerInterface* filler) {
if (EstimateObjectsCount() <= 0) return true;
filler_ = filler; filler_ = filler;
FillRetainedObjects(); FillRetainedObjects();
for (HashMap::Entry* p = objects_by_info_.Start(); FillImplicitReferences();
p != NULL; if (EstimateObjectsCount() > 0) {
p = objects_by_info_.Next(p)) { for (HashMap::Entry* p = objects_by_info_.Start();
v8::RetainedObjectInfo* info = p != NULL;
reinterpret_cast<v8::RetainedObjectInfo*>(p->key); p = objects_by_info_.Next(p)) {
SetNativeRootReference(info); v8::RetainedObjectInfo* info =
List<HeapObject*>* objects = reinterpret_cast<v8::RetainedObjectInfo*>(p->key);
reinterpret_cast<List<HeapObject*>* >(p->value); SetNativeRootReference(info);
for (int i = 0; i < objects->length(); ++i) { List<HeapObject*>* objects =
SetWrapperNativeReferences(objects->at(i), info); reinterpret_cast<List<HeapObject*>* >(p->value);
for (int i = 0; i < objects->length(); ++i) {
SetWrapperNativeReferences(objects->at(i), info);
}
} }
SetRootNativeRootsReference();
} }
SetRootNativeRootsReference();
filler_ = NULL; filler_ = NULL;
return true; return true;
} }
......
...@@ -1042,6 +1042,7 @@ class NativeObjectsExplorer : public HeapEntriesAllocator { ...@@ -1042,6 +1042,7 @@ class NativeObjectsExplorer : public HeapEntriesAllocator {
private: private:
void FillRetainedObjects(); void FillRetainedObjects();
void FillImplicitReferences();
List<HeapObject*>* GetListMaybeDisposeInfo(v8::RetainedObjectInfo* info); List<HeapObject*>* GetListMaybeDisposeInfo(v8::RetainedObjectInfo* info);
void SetNativeRootReference(v8::RetainedObjectInfo* info); void SetNativeRootReference(v8::RetainedObjectInfo* info);
void SetRootNativeRootsReference(); void SetRootNativeRootsReference();
......
...@@ -805,6 +805,75 @@ TEST(HeapSnapshotRetainedObjectInfo) { ...@@ -805,6 +805,75 @@ TEST(HeapSnapshotRetainedObjectInfo) {
} }
class GraphWithImplicitRefs {
public:
static const int kObjectsCount = 4;
explicit GraphWithImplicitRefs(LocalContext* env) {
CHECK_EQ(NULL, instance_);
instance_ = this;
for (int i = 0; i < kObjectsCount; i++) {
objects_[i] = v8::Persistent<v8::Object>::New(v8::Object::New());
}
(*env)->Global()->Set(v8_str("root_object"), objects_[0]);
}
~GraphWithImplicitRefs() {
instance_ = NULL;
}
static void gcPrologue() {
instance_->AddImplicitReferences();
}
private:
void AddImplicitReferences() {
// 0 -> 1
v8::V8::AddImplicitReferences(
v8::Persistent<v8::Object>::Cast(objects_[0]), &objects_[1], 1);
// Adding two more references(note length=2 in params): 1 -> 2, 1 -> 3
v8::V8::AddImplicitReferences(
v8::Persistent<v8::Object>::Cast(objects_[1]), &objects_[2], 2);
}
v8::Persistent<v8::Value> objects_[kObjectsCount];
static GraphWithImplicitRefs* instance_;
};
GraphWithImplicitRefs* GraphWithImplicitRefs::instance_ = NULL;
TEST(HeapSnapshotImplicitReferences) {
v8::HandleScope scope;
LocalContext env;
GraphWithImplicitRefs graph(&env);
v8::V8::SetGlobalGCPrologueCallback(&GraphWithImplicitRefs::gcPrologue);
const v8::HeapSnapshot* snapshot =
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");
CHECK(obj0);
CHECK_EQ(v8::HeapGraphNode::kObject, obj0->GetType());
const v8::HeapGraphNode* obj1 = GetProperty(
obj0, v8::HeapGraphEdge::kInternal, "native");
CHECK(obj1);
int implicit_targets_count = 0;
for (int i = 0, count = obj1->GetChildrenCount(); i < count; ++i) {
const v8::HeapGraphEdge* prop = obj1->GetChild(i);
v8::String::AsciiValue prop_name(prop->GetName());
if (prop->GetType() == v8::HeapGraphEdge::kInternal &&
strcmp("native", *prop_name) == 0) {
++implicit_targets_count;
}
}
CHECK_EQ(2, implicit_targets_count);
v8::V8::SetGlobalGCPrologueCallback(NULL);
}
TEST(DeleteAllHeapSnapshots) { TEST(DeleteAllHeapSnapshots) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
......
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