| Index: src/heap-snapshot-generator.cc
|
| diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
|
| index 271f95c5ca0a40c871a99e822f793d1f078d077e..84e819d7a6d08a1d9ec4c846b1a17952f57f80ac 100644
|
| --- a/src/heap-snapshot-generator.cc
|
| +++ b/src/heap-snapshot-generator.cc
|
| @@ -100,7 +100,7 @@ void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type,
|
|
|
|
|
| Handle<HeapObject> HeapEntry::GetHeapObject() {
|
| - return snapshot_->collection()->FindHeapObjectById(id());
|
| + return snapshot_->profiler()->FindHeapObjectById(id());
|
| }
|
|
|
|
|
| @@ -202,10 +202,10 @@ template <> struct SnapshotSizeConstants<8> {
|
|
|
| } // namespace
|
|
|
| -HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
|
| +HeapSnapshot::HeapSnapshot(HeapProfiler* profiler,
|
| const char* title,
|
| unsigned uid)
|
| - : collection_(collection),
|
| + : profiler_(profiler),
|
| title_(title),
|
| uid_(uid),
|
| root_index_(HeapEntry::kNoEntry),
|
| @@ -225,13 +225,13 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
|
|
|
|
|
| void HeapSnapshot::Delete() {
|
| - collection_->RemoveSnapshot(this);
|
| + profiler_->RemoveSnapshot(this);
|
| delete this;
|
| }
|
|
|
|
|
| void HeapSnapshot::RememberLastJSObjectId() {
|
| - max_snapshot_js_object_id_ = collection_->last_assigned_id();
|
| + max_snapshot_js_object_id_ = profiler_->heap_object_map()->last_assigned_id();
|
| }
|
|
|
|
|
| @@ -346,12 +346,6 @@ void HeapSnapshot::Print(int max_depth) {
|
| }
|
|
|
|
|
| -template<typename T, class P>
|
| -static size_t GetMemoryUsedByList(const List<T, P>& list) {
|
| - return list.length() * sizeof(T) + sizeof(list);
|
| -}
|
| -
|
| -
|
| size_t HeapSnapshot::RawSnapshotSize() const {
|
| return
|
| sizeof(*this) +
|
| @@ -394,11 +388,6 @@ HeapObjectsMap::HeapObjectsMap(Heap* heap)
|
| }
|
|
|
|
|
| -void HeapObjectsMap::SnapshotGenerationFinished() {
|
| - RemoveDeadEntries();
|
| -}
|
| -
|
| -
|
| void HeapObjectsMap::MoveObject(Address from, Address to, int object_size) {
|
| ASSERT(to != NULL);
|
| ASSERT(from != NULL);
|
| @@ -502,7 +491,7 @@ void HeapObjectsMap::UpdateHeapObjectsMap() {
|
| entries_map_.occupancy());
|
| }
|
| heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask,
|
| - "HeapSnapshotsCollection::UpdateHeapObjectsMap");
|
| + "HeapObjectsMap::UpdateHeapObjectsMap");
|
| HeapIterator iterator(heap_);
|
| for (HeapObject* obj = iterator.next();
|
| obj != NULL;
|
| @@ -710,13 +699,12 @@ void HeapObjectsMap::RemoveDeadEntries() {
|
| }
|
|
|
|
|
| -SnapshotObjectId HeapObjectsMap::GenerateId(Heap* heap,
|
| - v8::RetainedObjectInfo* info) {
|
| +SnapshotObjectId HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) {
|
| SnapshotObjectId id = static_cast<SnapshotObjectId>(info->GetHash());
|
| const char* label = info->GetLabel();
|
| id ^= StringHasher::HashSequentialString(label,
|
| static_cast<int>(strlen(label)),
|
| - heap->HashSeed());
|
| + heap_->HashSeed());
|
| intptr_t element_count = info->GetElementCount();
|
| if (element_count != -1)
|
| id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count),
|
| @@ -734,104 +722,6 @@ size_t HeapObjectsMap::GetUsedMemorySize() const {
|
| }
|
|
|
|
|
| -HeapSnapshotsCollection::HeapSnapshotsCollection(Heap* heap)
|
| - : names_(heap),
|
| - ids_(heap),
|
| - allocation_tracker_(NULL) {
|
| -}
|
| -
|
| -
|
| -static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) {
|
| - delete *snapshot_ptr;
|
| -}
|
| -
|
| -
|
| -HeapSnapshotsCollection::~HeapSnapshotsCollection() {
|
| - delete allocation_tracker_;
|
| - snapshots_.Iterate(DeleteHeapSnapshot);
|
| -}
|
| -
|
| -
|
| -void HeapSnapshotsCollection::StartHeapObjectsTracking(bool track_allocations) {
|
| - ids_.UpdateHeapObjectsMap();
|
| - ASSERT(allocation_tracker_ == NULL);
|
| - if (track_allocations) {
|
| - allocation_tracker_ = new AllocationTracker(&ids_, names());
|
| - }
|
| -}
|
| -
|
| -
|
| -void HeapSnapshotsCollection::StopHeapObjectsTracking() {
|
| - ids_.StopHeapObjectsTracking();
|
| - if (allocation_tracker_ != NULL) {
|
| - delete allocation_tracker_;
|
| - allocation_tracker_ = NULL;
|
| - }
|
| -}
|
| -
|
| -
|
| -HeapSnapshot* HeapSnapshotsCollection::NewSnapshot(const char* name,
|
| - unsigned uid) {
|
| - return new HeapSnapshot(this, name, uid);
|
| -}
|
| -
|
| -
|
| -void HeapSnapshotsCollection::SnapshotGenerationFinished(
|
| - HeapSnapshot* snapshot) {
|
| - ids_.SnapshotGenerationFinished();
|
| - if (snapshot != NULL) {
|
| - snapshots_.Add(snapshot);
|
| - }
|
| -}
|
| -
|
| -
|
| -void HeapSnapshotsCollection::RemoveSnapshot(HeapSnapshot* snapshot) {
|
| - snapshots_.RemoveElement(snapshot);
|
| -}
|
| -
|
| -
|
| -Handle<HeapObject> HeapSnapshotsCollection::FindHeapObjectById(
|
| - SnapshotObjectId id) {
|
| - // First perform a full GC in order to avoid dead objects.
|
| - heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
|
| - "HeapSnapshotsCollection::FindHeapObjectById");
|
| - DisallowHeapAllocation no_allocation;
|
| - HeapObject* object = NULL;
|
| - HeapIterator iterator(heap(), 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_.FindEntry(obj->address()) == id) {
|
| - ASSERT(object == NULL);
|
| - object = obj;
|
| - // Can't break -- kFilterUnreachable requires full heap traversal.
|
| - }
|
| - }
|
| - return object != NULL ? Handle<HeapObject>(object) : Handle<HeapObject>();
|
| -}
|
| -
|
| -
|
| -void HeapSnapshotsCollection::AllocationEvent(Address addr, int size) {
|
| - DisallowHeapAllocation no_allocation;
|
| - if (allocation_tracker_ != NULL) {
|
| - allocation_tracker_->AllocationEvent(addr, size);
|
| - }
|
| -}
|
| -
|
| -
|
| -size_t HeapSnapshotsCollection::GetUsedMemorySize() const {
|
| - size_t size = sizeof(*this);
|
| - size += names_.GetUsedMemorySize();
|
| - size += ids_.GetUsedMemorySize();
|
| - size += GetMemoryUsedByList(snapshots_);
|
| - for (int i = 0; i < snapshots_.length(); ++i) {
|
| - size += snapshots_[i]->RawSnapshotSize();
|
| - }
|
| - return size;
|
| -}
|
| -
|
| -
|
| HeapEntriesMap::HeapEntriesMap()
|
| : entries_(HeapThingsMatch) {
|
| }
|
| @@ -912,9 +802,10 @@ V8HeapExplorer::V8HeapExplorer(
|
| HeapSnapshot* snapshot,
|
| SnapshottingProgressReportingInterface* progress,
|
| v8::HeapProfiler::ObjectNameResolver* resolver)
|
| - : heap_(snapshot->collection()->heap()),
|
| + : heap_(snapshot->profiler()->heap_object_map()->heap()),
|
| snapshot_(snapshot),
|
| - collection_(snapshot_->collection()),
|
| + names_(snapshot_->profiler()->names()),
|
| + heap_object_map_(snapshot_->profiler()->heap_object_map()),
|
| progress_(progress),
|
| filler_(NULL),
|
| global_object_name_resolver_(resolver) {
|
| @@ -944,20 +835,20 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) {
|
| JSFunction* func = JSFunction::cast(object);
|
| SharedFunctionInfo* shared = func->shared();
|
| const char* name = shared->bound() ? "native_bind" :
|
| - collection_->names()->GetName(String::cast(shared->name()));
|
| + names_->GetName(String::cast(shared->name()));
|
| return AddEntry(object, HeapEntry::kClosure, name);
|
| } else if (object->IsJSRegExp()) {
|
| JSRegExp* re = JSRegExp::cast(object);
|
| return AddEntry(object,
|
| HeapEntry::kRegExp,
|
| - collection_->names()->GetName(re->Pattern()));
|
| + names_->GetName(re->Pattern()));
|
| } else if (object->IsJSObject()) {
|
| - const char* name = collection_->names()->GetName(
|
| + const char* name = names_->GetName(
|
| GetConstructorName(JSObject::cast(object)));
|
| if (object->IsJSGlobalObject()) {
|
| const char* tag = objects_tags_.GetTag(object);
|
| if (tag != NULL) {
|
| - name = collection_->names()->GetFormatted("%s / %s", name, tag);
|
| + name = names_->GetFormatted("%s / %s", name, tag);
|
| }
|
| }
|
| return AddEntry(object, HeapEntry::kObject, name);
|
| @@ -973,20 +864,20 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) {
|
| "(sliced string)");
|
| return AddEntry(object,
|
| HeapEntry::kString,
|
| - collection_->names()->GetName(String::cast(object)));
|
| + names_->GetName(String::cast(object)));
|
| } else if (object->IsCode()) {
|
| return AddEntry(object, HeapEntry::kCode, "");
|
| } else if (object->IsSharedFunctionInfo()) {
|
| String* name = String::cast(SharedFunctionInfo::cast(object)->name());
|
| return AddEntry(object,
|
| HeapEntry::kCode,
|
| - collection_->names()->GetName(name));
|
| + names_->GetName(name));
|
| } else if (object->IsScript()) {
|
| Object* name = Script::cast(object)->name();
|
| return AddEntry(object,
|
| HeapEntry::kCode,
|
| name->IsString()
|
| - ? collection_->names()->GetName(String::cast(name))
|
| + ? names_->GetName(String::cast(name))
|
| : "");
|
| } else if (object->IsNativeContext()) {
|
| return AddEntry(object, HeapEntry::kHidden, "system / NativeContext");
|
| @@ -1009,7 +900,7 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
|
| const char* name) {
|
| int object_size = object->Size();
|
| SnapshotObjectId object_id =
|
| - collection_->GetObjectId(object->address(), object_size);
|
| + heap_object_map_->FindOrAddEntry(object->address(), object_size);
|
| return snapshot_->AddEntry(type, name, object_id, object_size);
|
| }
|
|
|
| @@ -1356,14 +1247,13 @@ void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) {
|
| void V8HeapExplorer::ExtractSharedFunctionInfoReferences(
|
| int entry, SharedFunctionInfo* shared) {
|
| HeapObject* obj = shared;
|
| - StringsStorage* names = collection_->names();
|
| String* shared_name = shared->DebugName();
|
| const char* name = NULL;
|
| if (shared_name != *heap_->isolate()->factory()->empty_string()) {
|
| - name = names->GetName(shared_name);
|
| - TagObject(shared->code(), names->GetFormatted("(code for %s)", name));
|
| + name = names_->GetName(shared_name);
|
| + TagObject(shared->code(), names_->GetFormatted("(code for %s)", name));
|
| } else {
|
| - TagObject(shared->code(), names->GetFormatted("(%s code)",
|
| + TagObject(shared->code(), names_->GetFormatted("(%s code)",
|
| Code::Kind2String(shared->code()->kind())));
|
| }
|
|
|
| @@ -1384,7 +1274,7 @@ void V8HeapExplorer::ExtractSharedFunctionInfoReferences(
|
| "script", shared->script(),
|
| SharedFunctionInfo::kScriptOffset);
|
| const char* construct_stub_name = name ?
|
| - names->GetFormatted("(construct stub code for %s)", name) :
|
| + names_->GetFormatted("(construct stub code for %s)", name) :
|
| "(construct stub code)";
|
| TagObject(shared->construct_stub(), construct_stub_name);
|
| SetInternalReference(obj, entry,
|
| @@ -1452,14 +1342,13 @@ void V8HeapExplorer::ExtractCodeCacheReferences(
|
|
|
|
|
| void V8HeapExplorer::TagCodeObject(Code* code, const char* external_name) {
|
| - TagObject(code, collection_->names()->GetFormatted("(%s code)",
|
| - external_name));
|
| + TagObject(code, names_->GetFormatted("(%s code)", external_name));
|
| }
|
|
|
|
|
| void V8HeapExplorer::TagCodeObject(Code* code) {
|
| if (code->kind() == Code::STUB) {
|
| - TagObject(code, collection_->names()->GetFormatted(
|
| + TagObject(code, names_->GetFormatted(
|
| "(%s code)", CodeStub::MajorName(
|
| static_cast<CodeStub::Major>(code->major_key()), true)));
|
| }
|
| @@ -1537,7 +1426,7 @@ void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry) {
|
| bindings->get(JSFunction::kBoundFunctionIndex));
|
| for (int i = JSFunction::kBoundArgumentsStartIndex;
|
| i < bindings->length(); i++) {
|
| - const char* reference_name = collection_->names()->GetFormatted(
|
| + const char* reference_name = names_->GetFormatted(
|
| "bound_argument_%d",
|
| i - JSFunction::kBoundArgumentsStartIndex);
|
| SetNativeBindReference(js_obj, entry, reference_name,
|
| @@ -1844,7 +1733,7 @@ void V8HeapExplorer::SetContextReference(HeapObject* parent_obj,
|
| if (child_entry != NULL) {
|
| filler_->SetNamedReference(HeapGraphEdge::kContextVariable,
|
| parent_entry,
|
| - collection_->names()->GetName(reference_name),
|
| + names_->GetName(reference_name),
|
| child_entry);
|
| IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
|
| }
|
| @@ -1910,7 +1799,7 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
|
| if (IsEssentialObject(child_obj)) {
|
| filler_->SetNamedReference(HeapGraphEdge::kInternal,
|
| parent_entry,
|
| - collection_->names()->GetName(index),
|
| + names_->GetName(index),
|
| child_entry);
|
| }
|
| IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
|
| @@ -1963,11 +1852,11 @@ void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
|
| reference_name->IsSymbol() || String::cast(reference_name)->length() > 0
|
| ? HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
|
| const char* name = name_format_string != NULL && reference_name->IsString()
|
| - ? collection_->names()->GetFormatted(
|
| + ? names_->GetFormatted(
|
| name_format_string,
|
| *String::cast(reference_name)->ToCString(
|
| DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)) :
|
| - collection_->names()->GetName(reference_name);
|
| + names_->GetName(reference_name);
|
|
|
| filler_->SetNamedReference(type,
|
| parent_entry,
|
| @@ -2143,13 +2032,15 @@ class BasicHeapEntriesAllocator : public HeapEntriesAllocator {
|
| HeapSnapshot* snapshot,
|
| HeapEntry::Type entries_type)
|
| : snapshot_(snapshot),
|
| - collection_(snapshot_->collection()),
|
| + names_(snapshot_->profiler()->names()),
|
| + heap_object_map_(snapshot_->profiler()->heap_object_map()),
|
| entries_type_(entries_type) {
|
| }
|
| virtual HeapEntry* AllocateEntry(HeapThing ptr);
|
| private:
|
| HeapSnapshot* snapshot_;
|
| - HeapSnapshotsCollection* collection_;
|
| + StringsStorage* names_;
|
| + HeapObjectsMap* heap_object_map_;
|
| HeapEntry::Type entries_type_;
|
| };
|
|
|
| @@ -2159,13 +2050,13 @@ HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(HeapThing ptr) {
|
| intptr_t elements = info->GetElementCount();
|
| intptr_t size = info->GetSizeInBytes();
|
| const char* name = elements != -1
|
| - ? collection_->names()->GetFormatted(
|
| + ? names_->GetFormatted(
|
| "%s / %" V8_PTR_PREFIX "d entries", info->GetLabel(), elements)
|
| - : collection_->names()->GetCopy(info->GetLabel());
|
| + : names_->GetCopy(info->GetLabel());
|
| return snapshot_->AddEntry(
|
| entries_type_,
|
| name,
|
| - HeapObjectsMap::GenerateId(collection_->heap(), info),
|
| + heap_object_map_->GenerateId(info),
|
| size != -1 ? static_cast<int>(size) : 0);
|
| }
|
|
|
| @@ -2173,9 +2064,9 @@ HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(HeapThing ptr) {
|
| NativeObjectsExplorer::NativeObjectsExplorer(
|
| HeapSnapshot* snapshot,
|
| SnapshottingProgressReportingInterface* progress)
|
| - : isolate_(snapshot->collection()->heap()->isolate()),
|
| + : isolate_(snapshot->profiler()->heap_object_map()->heap()->isolate()),
|
| snapshot_(snapshot),
|
| - collection_(snapshot_->collection()),
|
| + names_(snapshot_->profiler()->names()),
|
| progress_(progress),
|
| embedder_queried_(false),
|
| objects_by_info_(RetainedInfosMatch),
|
| @@ -2337,7 +2228,7 @@ class NativeGroupRetainedObjectInfo : public v8::RetainedObjectInfo {
|
|
|
| NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo(
|
| const char* label) {
|
| - const char* label_copy = collection_->names()->GetCopy(label);
|
| + const char* label_copy = names_->GetCopy(label);
|
| uint32_t hash = StringHasher::HashSequentialString(
|
| label_copy,
|
| static_cast<int>(strlen(label_copy)),
|
| @@ -2415,7 +2306,7 @@ class SnapshotFiller : public SnapshotFillerInterface {
|
| public:
|
| explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
|
| : snapshot_(snapshot),
|
| - collection_(snapshot->collection()),
|
| + names_(snapshot->profiler()->names()),
|
| entries_(entries) { }
|
| HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
|
| HeapEntry* entry = allocator->AllocateEntry(ptr);
|
| @@ -2458,13 +2349,13 @@ class SnapshotFiller : public SnapshotFillerInterface {
|
| int index = parent_entry->children_count() + 1;
|
| parent_entry->SetNamedReference(
|
| type,
|
| - collection_->names()->GetName(index),
|
| + names_->GetName(index),
|
| child_entry);
|
| }
|
|
|
| private:
|
| HeapSnapshot* snapshot_;
|
| - HeapSnapshotsCollection* collection_;
|
| + StringsStorage* names_;
|
| HeapEntriesMap* entries_;
|
| };
|
|
|
| @@ -2670,7 +2561,7 @@ const int HeapSnapshotJSONSerializer::kNodeFieldsCount = 5;
|
|
|
| void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) {
|
| if (AllocationTracker* allocation_tracker =
|
| - snapshot_->collection()->allocation_tracker()) {
|
| + snapshot_->profiler()->allocation_tracker()) {
|
| allocation_tracker->PrepareForSerialization();
|
| }
|
| ASSERT(writer_ == NULL);
|
| @@ -2889,7 +2780,7 @@ void HeapSnapshotJSONSerializer::SerializeSnapshot() {
|
| writer_->AddNumber(snapshot_->edges().length());
|
| writer_->AddString(",\"trace_function_count\":");
|
| uint32_t count = 0;
|
| - AllocationTracker* tracker = snapshot_->collection()->allocation_tracker();
|
| + AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker();
|
| if (tracker) {
|
| count = tracker->id_to_function_info()->occupancy();
|
| }
|
| @@ -2908,7 +2799,7 @@ static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) {
|
|
|
|
|
| void HeapSnapshotJSONSerializer::SerializeTraceTree() {
|
| - AllocationTracker* tracker = snapshot_->collection()->allocation_tracker();
|
| + AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker();
|
| if (!tracker) return;
|
| AllocationTraceTree* traces = tracker->trace_tree();
|
| SerializeTraceNode(traces->root());
|
| @@ -2959,7 +2850,7 @@ static int SerializePosition(int position, const Vector<char>& buffer,
|
|
|
|
|
| void HeapSnapshotJSONSerializer::SerializeTraceNodeInfos() {
|
| - AllocationTracker* tracker = snapshot_->collection()->allocation_tracker();
|
| + AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker();
|
| if (!tracker) return;
|
| // The buffer needs space for 6 unsigned ints, 6 commas, \n and \0
|
| const int kBufferSize =
|
|
|