Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(975)

Unified Diff: src/profile-generator.cc

Issue 7082012: Heap profiler: fetch document.URL of global objects. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Style fix Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/profile-generator.cc
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index c954c4fbc63189d046638e61a4070ce1ff3378f5..1ad3fa91714422accde71b622e3614cbc87f3ebd 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -1602,6 +1602,28 @@ void HeapObjectsSet::Insert(Object* obj) {
}
+const char* HeapObjectsSet::GetTag(Object* obj) {
+ HeapObject* object = HeapObject::cast(obj);
+ HashMap::Entry* cache_entry =
+ entries_.Lookup(object, HeapEntriesMap::Hash(object), false);
+ if (cache_entry != NULL
+ && cache_entry->value != HeapEntriesMap::kHeapEntryPlaceholder) {
+ return reinterpret_cast<const char*>(cache_entry->value);
+ } else {
+ return NULL;
+ }
+}
+
+
+void HeapObjectsSet::SetTag(Object* obj, const char* tag) {
+ if (!obj->IsHeapObject()) return;
+ HeapObject* object = HeapObject::cast(obj);
+ HashMap::Entry* cache_entry =
+ entries_.Lookup(object, HeapEntriesMap::Hash(object), true);
+ cache_entry->value = const_cast<char*>(tag);
+}
+
+
HeapObject *const V8HeapExplorer::kInternalRootObject =
reinterpret_cast<HeapObject*>(
static_cast<intptr_t>(HeapObjectsMap::kInternalRootObjectId));
@@ -1639,6 +1661,19 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
return snapshot_->AddRootEntry(children_count);
} else if (object == kGcRootsObject) {
return snapshot_->AddGcRootsEntry(children_count, retainers_count);
+ } else if (object->IsJSGlobalObject()) {
+ const char* tag = objects_tags_.GetTag(object);
+ const char* name = collection_->names()->GetName(
+ GetConstructorNameForHeapProfile(
+ JSObject::cast(object)));
Vitaly Repeshko 2011/05/29 23:01:34 nit: Fits on the previous line?
mnaganov (inactive) 2011/05/30 14:20:42 Done.
+ if (tag != NULL) {
+ name = collection_->names()->GetFormatted("%s / %s", name, tag);
+ }
+ return AddEntry(object,
+ HeapEntry::kObject,
+ name,
+ children_count,
+ retainers_count);
} else if (object->IsJSFunction()) {
JSFunction* func = JSFunction::cast(object);
SharedFunctionInfo* shared = func->shared();
@@ -1780,6 +1815,7 @@ class IndexedReferencesExtractor : public ObjectVisitor {
ASSERT(Memory::Object_at(field)->IsHeapObject());
*field |= kFailureTag;
}
+
private:
bool CheckVisitedAndUnmark(Object** field) {
if ((*field)->IsFailure()) {
@@ -2206,6 +2242,89 @@ void V8HeapExplorer::SetGcRootsReference(Object* child_obj) {
}
+class GlobalObjectsCounter : public ObjectVisitor {
+ public:
+ GlobalObjectsCounter() : count_(0) {}
+ void VisitPointers(Object** start, Object** end) {
Vitaly Repeshko 2011/05/29 23:01:34 nit: virtual
mnaganov (inactive) 2011/05/30 14:20:42 Done.
+ for (Object** p = start; p < end; p++) {
+ if ((*p)->IsGlobalContext())
+ ++count_;
+ }
+ }
+ int count() { return count_; }
+
+ private:
+ int count_;
+};
+
+
+class GlobalObjectsEnumerator : public ObjectVisitor {
+ public:
+ explicit GlobalObjectsEnumerator(int length)
+ : length_(length),
+ count_(0),
+ objects_(NewArray<Handle<JSGlobalObject> >(length)) {}
+ ~GlobalObjectsEnumerator() {
+ DeleteArray(objects_);
+ }
+ void VisitPointers(Object** start, Object** end) {
Vitaly Repeshko 2011/05/29 23:01:34 nit: virtual
mnaganov (inactive) 2011/05/30 14:20:42 Done.
+ for (Object** p = start; count_ < length_ && p < end; p++) {
+ if ((*p)->IsGlobalContext()) {
+ Context* context = Context::cast(*p);
+ JSObject* proxy = context->global_proxy();
+ if (proxy->IsJSGlobalProxy()) {
Vitaly Repeshko 2011/05/29 23:01:34 Given that this loop has more conditions than its
mnaganov (inactive) 2011/05/30 14:20:42 Fixed by eliminating the counter class.
+ Object* global = proxy->map()->prototype();
+ if (global->IsJSGlobalObject())
Vitaly Repeshko 2011/05/29 23:01:34 nit: {}
mnaganov (inactive) 2011/05/30 14:20:42 Done.
+ objects_[count_++] =
+ Handle<JSGlobalObject>(JSGlobalObject::cast(global));
+ }
+ }
+ }
+ }
+ int count() { return count_; }
+ Handle<JSGlobalObject>* objects() { return objects_; }
+
+ private:
+ const int length_;
+ int count_;
+ Handle<JSGlobalObject>* objects_;
Vitaly Repeshko 2011/05/29 23:01:34 Can we use a growable collection of handles (e.g.
mnaganov (inactive) 2011/05/30 14:20:42 Sure. Sorry, I forgot about their existence.
+};
+
+
+// Modifies heap. Must not be run during heap traversal.
+void V8HeapExplorer::TagGlobalObjects() {
Vitaly Repeshko 2011/05/29 23:01:34 Random idea. I don't know how flexible we want to
mnaganov (inactive) 2011/05/30 14:20:42 Let's discuss it later.
+ Isolate* isolate = Isolate::Current();
+ GlobalObjectsCounter counter;
+ isolate->global_handles()->IterateAllRoots(&counter);
+ GlobalObjectsEnumerator enumerator(counter.count());
+ isolate->global_handles()->IterateAllRoots(&enumerator);
+ Handle<String> document_string =
+ isolate->factory()->NewStringFromAscii(CStrVector("document"));
+ Handle<String> url_string =
+ isolate->factory()->NewStringFromAscii(CStrVector("URL"));
+ const char** urls = NewArray<const char*>(counter.count());
+ for (int i = 0; i < counter.count(); ++i) {
+ urls[i] = NULL;
+ Handle<JSGlobalObject>& go = enumerator.objects()[i];
Vitaly Repeshko 2011/05/29 23:01:34 Reference is not needed here. "go" is too short.
mnaganov (inactive) 2011/05/30 14:20:42 Removed ref. s/go/global_obj/
+ Object* obj_document = go->GetPropertyNoExceptionThrown(*document_string);
Vitaly Repeshko 2011/05/29 23:01:34 This is not safe, because it asserts on failure/ex
mnaganov (inactive) 2011/05/30 14:20:42 Done.
+ if (obj_document->IsJSObject()) {
+ JSObject* document = JSObject::cast(obj_document);
+ Object* obj_url = document->GetProperty(*url_string)->ToObjectUnchecked();
Vitaly Repeshko 2011/05/29 23:01:34 Also asserts on failure/exception.
mnaganov (inactive) 2011/05/30 14:20:42 Done.
+ if (obj_url->IsString()) {
+ urls[i] = collection_->names()->GetName(String::cast(obj_url));
+ }
+ }
+ }
+
+ AssertNoAllocation no_allocation;
+ for (int i = 0; i < counter.count(); ++i) {
+ objects_tags_.SetTag(*enumerator.objects()[i], urls[i]);
+ }
+
+ DeleteArray(urls);
+}
+
+
class GlobalHandlesExtractor : public ObjectVisitor {
public:
explicit GlobalHandlesExtractor(NativeObjectsExplorer* explorer)
@@ -2448,6 +2567,7 @@ class SnapshotCounter : public SnapshotFillerInterface {
HeapEntry*) {
entries_->CountReference(parent_ptr, child_ptr);
}
+
private:
HeapEntriesMap* entries_;
};
@@ -2519,6 +2639,7 @@ class SnapshotFiller : public SnapshotFillerInterface {
child_entry,
retainer_index);
}
+
private:
HeapSnapshot* snapshot_;
HeapSnapshotsCollection* collection_;
@@ -2527,6 +2648,8 @@ class SnapshotFiller : public SnapshotFillerInterface {
bool HeapSnapshotGenerator::GenerateSnapshot() {
+ v8_heap_explorer_.TagGlobalObjects();
+
AssertNoAllocation no_alloc;
SetProgressTotal(4); // 2 passes + dominators + sizes.

Powered by Google App Engine
This is Rietveld 408576698