Add v8::HeapGraphNode::GetHeapValue method.

This allows getting a heap object by a heap snapshot node for further
inspection. Very useful for objects from bindings that mostly have
getter-provided fields.

R=vegorov@google.com
BUG=webkit/61179
TEST=test-heap-profiler/GetHeapValue,GetHeapValueForDeletedObject

Review URL: http://codereview.chromium.org/8046006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9430 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f69c0b04
......@@ -307,6 +307,12 @@ class V8EXPORT HeapGraphNode {
* path from the snapshot root to the current node.
*/
const HeapGraphNode* GetDominatorNode() const;
/**
* Finds and returns a value from the heap corresponding to this node,
* if the value is still reachable.
*/
Handle<Value> GetHeapValue() const;
};
......
......@@ -5811,6 +5811,16 @@ const HeapGraphNode* HeapGraphNode::GetDominatorNode() const {
}
v8::Handle<v8::Value> HeapGraphNode::GetHeapValue() const {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::HeapGraphNode::GetHeapValue");
i::Handle<i::HeapObject> object = ToInternal(this)->GetHeapObject();
return v8::Handle<Value>(!object.is_null() ?
ToApi<Value>(object) : ToApi<Value>(
isolate->factory()->undefined_value()));
}
static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
return const_cast<i::HeapSnapshot*>(
reinterpret_cast<const i::HeapSnapshot*>(snapshot));
......
......@@ -1015,6 +1015,11 @@ int HeapEntry::RetainedSize(bool exact) {
}
Handle<HeapObject> HeapEntry::GetHeapObject() {
return snapshot_->collection()->FindHeapObjectById(id());
}
template<class Visitor>
void HeapEntry::ApplyAndPaintAllReachable(Visitor* visitor) {
List<HeapEntry*> list(10);
......@@ -1522,6 +1527,26 @@ void HeapSnapshotsCollection::RemoveSnapshot(HeapSnapshot* snapshot) {
}
Handle<HeapObject> HeapSnapshotsCollection::FindHeapObjectById(uint64_t id) {
// First perform a full GC in order to avoid dead objects.
HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask);
AssertNoAllocation no_allocation;
HeapObject* object = NULL;
HeapIterator iterator(HeapIterator::kFilterUnreachable);
// Make sure that object with the given id is still reachable.
for (HeapObject* obj = iterator.next();
obj != NULL;
obj = iterator.next()) {
if (ids_.FindObject(obj->address()) == id) {
ASSERT(object == NULL);
object = obj;
// Can't break -- kFilterUnreachable requires full heap traversal.
}
}
return object != NULL ? Handle<HeapObject>(object) : Handle<HeapObject>();
}
HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder =
reinterpret_cast<HeapEntry*>(1);
......
......@@ -588,6 +588,8 @@ class HeapEntry BASE_EMBEDDED {
void Print(int max_depth, int indent);
Handle<HeapObject> GetHeapObject();
static int EntriesSize(int entries_count,
int children_count,
int retainers_count);
......@@ -766,6 +768,7 @@ class HeapSnapshotsCollection {
TokenEnumerator* token_enumerator() { return token_enumerator_; }
uint64_t GetObjectId(Address addr) { return ids_.FindObject(addr); }
Handle<HeapObject> FindHeapObjectById(uint64_t id);
void ObjectMoveEvent(Address from, Address to) { ids_.MoveObject(from, to); }
private:
......
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