Commit 054bdf7f authored by yurys@chromium.org's avatar yurys@chromium.org

Remove HeapSnapshotsCollection class

The class added unecessary level of indirection to the heap profiler implementation. I merged some of its implementation into HeapProfiler and deleted the rest. This refactoring is also a prerequisite for keeping HeapObjectsMap alive even when all snapshots are deleted.

BUG=None
LOG=N
R=alph@chromium.org, mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/101393002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18221 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0fd81694
......@@ -28,28 +28,41 @@
#include "v8.h"
#include "heap-profiler.h"
#include "allocation-tracker.h"
#include "heap-snapshot-generator-inl.h"
namespace v8 {
namespace internal {
HeapProfiler::HeapProfiler(Heap* heap)
: snapshots_(new HeapSnapshotsCollection(heap)),
: ids_(new HeapObjectsMap(heap)),
names_(new StringsStorage(heap)),
next_snapshot_uid_(1),
is_tracking_allocations_(false),
is_tracking_object_moves_(false) {
}
static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) {
delete *snapshot_ptr;
}
HeapProfiler::~HeapProfiler() {
delete snapshots_;
snapshots_.Iterate(DeleteHeapSnapshot);
snapshots_.Clear();
}
void HeapProfiler::DeleteAllSnapshots() {
Heap* the_heap = heap();
delete snapshots_;
snapshots_ = new HeapSnapshotsCollection(the_heap);
snapshots_.Iterate(DeleteHeapSnapshot);
snapshots_.Clear();
names_.Reset(new StringsStorage(heap()));
}
void HeapProfiler::RemoveSnapshot(HeapSnapshot* snapshot) {
snapshots_.RemoveElement(snapshot);
}
......@@ -76,15 +89,17 @@ HeapSnapshot* HeapProfiler::TakeSnapshot(
const char* name,
v8::ActivityControl* control,
v8::HeapProfiler::ObjectNameResolver* resolver) {
HeapSnapshot* result = snapshots_->NewSnapshot(name, next_snapshot_uid_++);
HeapSnapshot* result = new HeapSnapshot(this, name, next_snapshot_uid_++);
{
HeapSnapshotGenerator generator(result, control, resolver, heap());
if (!generator.GenerateSnapshot()) {
delete result;
result = NULL;
} else {
snapshots_.Add(result);
}
}
snapshots_->SnapshotGenerationFinished(result);
ids_->RemoveDeadEntries();
is_tracking_object_moves_ = true;
return result;
}
......@@ -94,69 +109,79 @@ HeapSnapshot* HeapProfiler::TakeSnapshot(
String* name,
v8::ActivityControl* control,
v8::HeapProfiler::ObjectNameResolver* resolver) {
return TakeSnapshot(snapshots_->names()->GetName(name), control, resolver);
return TakeSnapshot(names_->GetName(name), control, resolver);
}
void HeapProfiler::StartHeapObjectsTracking(bool track_allocations) {
snapshots_->StartHeapObjectsTracking(track_allocations);
ids_->UpdateHeapObjectsMap();
is_tracking_object_moves_ = true;
ASSERT(!is_tracking_allocations_);
ASSERT(!is_tracking_allocations());
if (track_allocations) {
allocation_tracker_.Reset(new AllocationTracker(*ids_, *names_));
heap()->DisableInlineAllocation();
is_tracking_allocations_ = true;
}
}
SnapshotObjectId HeapProfiler::PushHeapObjectsStats(OutputStream* stream) {
return snapshots_->PushHeapObjectsStats(stream);
return ids_->PushHeapObjectsStats(stream);
}
void HeapProfiler::StopHeapObjectsTracking() {
snapshots_->StopHeapObjectsTracking();
if (is_tracking_allocations_) {
ids_->StopHeapObjectsTracking();
if (is_tracking_allocations()) {
allocation_tracker_.Reset(NULL);
heap()->EnableInlineAllocation();
is_tracking_allocations_ = false;
}
}
size_t HeapProfiler::GetMemorySizeUsedByProfiler() {
return snapshots_->GetUsedMemorySize();
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;
}
int HeapProfiler::GetSnapshotsCount() {
return snapshots_->snapshots()->length();
return snapshots_.length();
}
HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
return snapshots_->snapshots()->at(index);
return snapshots_.at(index);
}
SnapshotObjectId HeapProfiler::GetSnapshotObjectId(Handle<Object> obj) {
if (!obj->IsHeapObject())
return v8::HeapProfiler::kUnknownObjectId;
return snapshots_->FindObjectId(HeapObject::cast(*obj)->address());
return ids_->FindEntry(HeapObject::cast(*obj)->address());
}
void HeapProfiler::ObjectMoveEvent(Address from, Address to, int size) {
snapshots_->ObjectMoveEvent(from, to, size);
ids_->MoveObject(from, to, size);
}
void HeapProfiler::AllocationEvent(Address addr, int size) {
snapshots_->AllocationEvent(addr, size);
DisallowHeapAllocation no_allocation;
if (!allocation_tracker_.is_empty()) {
allocation_tracker_->AllocationEvent(addr, size);
}
}
void HeapProfiler::UpdateObjectSizeEvent(Address addr, int size) {
snapshots_->UpdateObjectSizeEvent(addr, size);
ids_->UpdateObjectSize(addr, size);
}
......@@ -167,4 +192,24 @@ void HeapProfiler::SetRetainedObjectInfo(UniqueId id,
}
Handle<HeapObject> HeapProfiler::FindHeapObjectById(SnapshotObjectId id) {
heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
"HeapProfiler::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>();
}
} } // namespace v8::internal
......@@ -30,12 +30,12 @@
#include "heap-snapshot-generator-inl.h"
#include "isolate.h"
#include "smart-pointers.h"
namespace v8 {
namespace internal {
class HeapSnapshot;
class HeapSnapshotsCollection;
class HeapProfiler {
public:
......@@ -55,12 +55,16 @@ class HeapProfiler {
void StartHeapObjectsTracking(bool track_allocations);
void StopHeapObjectsTracking();
AllocationTracker* allocation_tracker() { return *allocation_tracker_; }
HeapObjectsMap* heap_object_map() { return *ids_; }
StringsStorage* names() { return *names_; }
SnapshotObjectId PushHeapObjectsStats(OutputStream* stream);
int GetSnapshotsCount();
HeapSnapshot* GetSnapshot(int index);
SnapshotObjectId GetSnapshotObjectId(Handle<Object> obj);
void DeleteAllSnapshots();
void RemoveSnapshot(HeapSnapshot* snapshot);
void ObjectMoveEvent(Address from, Address to, int size);
......@@ -76,19 +80,20 @@ class HeapProfiler {
void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
bool is_tracking_object_moves() const { return is_tracking_object_moves_; }
bool is_tracking_allocations() const { return is_tracking_allocations_; }
bool is_tracking_allocations() { return !allocation_tracker_.is_empty(); }
int FindUntrackedObjects() {
return snapshots_->FindUntrackedObjects();
}
Handle<HeapObject> FindHeapObjectById(SnapshotObjectId id);
private:
Heap* heap() const { return snapshots_->heap(); }
Heap* heap() const { return ids_->heap(); }
HeapSnapshotsCollection* snapshots_;
// Mapping from HeapObject addresses to objects' uids.
SmartPointer<HeapObjectsMap> ids_;
List<HeapSnapshot*> snapshots_;
SmartPointer<StringsStorage> names_;
unsigned next_snapshot_uid_;
List<v8::HeapProfiler::WrapperInfoCallback> wrapper_callbacks_;
bool is_tracking_allocations_;
SmartPointer<AllocationTracker> allocation_tracker_;
bool is_tracking_object_moves_;
};
......
......@@ -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 =
......
......@@ -154,21 +154,19 @@ class HeapEntry BASE_EMBEDDED {
};
class HeapSnapshotsCollection;
// HeapSnapshot represents a single heap snapshot. It is stored in
// HeapSnapshotsCollection, which is also a factory for
// HeapProfiler, which is also a factory for
// HeapSnapshots. All HeapSnapshots share strings copied from JS heap
// to be able to return them even if they were collected.
// HeapSnapshotGenerator fills in a HeapSnapshot.
class HeapSnapshot {
public:
HeapSnapshot(HeapSnapshotsCollection* collection,
HeapSnapshot(HeapProfiler* profiler,
const char* title,
unsigned uid);
void Delete();
HeapSnapshotsCollection* collection() { return collection_; }
HeapProfiler* profiler() { return profiler_; }
const char* title() { return title_; }
unsigned uid() { return uid_; }
size_t RawSnapshotSize() const;
......@@ -202,7 +200,7 @@ class HeapSnapshot {
void PrintEntriesSize();
private:
HeapSnapshotsCollection* collection_;
HeapProfiler* profiler_;
const char* title_;
unsigned uid_;
int root_index_;
......@@ -227,7 +225,6 @@ class HeapObjectsMap {
Heap* heap() const { return heap_; }
void SnapshotGenerationFinished();
SnapshotObjectId FindEntry(Address addr);
SnapshotObjectId FindOrAddEntry(Address addr,
unsigned int size,
......@@ -242,7 +239,7 @@ class HeapObjectsMap {
SnapshotObjectId PushHeapObjectsStats(OutputStream* stream);
size_t GetUsedMemorySize() const;
static SnapshotObjectId GenerateId(Heap* heap, v8::RetainedObjectInfo* info);
SnapshotObjectId GenerateId(v8::RetainedObjectInfo* info);
static inline SnapshotObjectId GetNthGcSubrootId(int delta);
static const int kObjectIdStep = 2;
......@@ -255,6 +252,7 @@ class HeapObjectsMap {
int FindUntrackedObjects();
void UpdateHeapObjectsMap();
void RemoveDeadEntries();
private:
struct EntryInfo {
......@@ -274,8 +272,6 @@ class HeapObjectsMap {
uint32_t count;
};
void RemoveDeadEntries();
SnapshotObjectId next_id_;
HashMap entries_map_;
List<EntryInfo> entries_;
......@@ -286,59 +282,6 @@ class HeapObjectsMap {
};
class HeapSnapshotsCollection {
public:
explicit HeapSnapshotsCollection(Heap* heap);
~HeapSnapshotsCollection();
Heap* heap() const { return ids_.heap(); }
SnapshotObjectId PushHeapObjectsStats(OutputStream* stream) {
return ids_.PushHeapObjectsStats(stream);
}
void StartHeapObjectsTracking(bool track_allocations);
void StopHeapObjectsTracking();
HeapSnapshot* NewSnapshot(const char* name, unsigned uid);
void SnapshotGenerationFinished(HeapSnapshot* snapshot);
List<HeapSnapshot*>* snapshots() { return &snapshots_; }
void RemoveSnapshot(HeapSnapshot* snapshot);
StringsStorage* names() { return &names_; }
AllocationTracker* allocation_tracker() { return allocation_tracker_; }
SnapshotObjectId FindObjectId(Address object_addr) {
return ids_.FindEntry(object_addr);
}
SnapshotObjectId GetObjectId(Address object_addr, int object_size) {
return ids_.FindOrAddEntry(object_addr, object_size);
}
Handle<HeapObject> FindHeapObjectById(SnapshotObjectId id);
void ObjectMoveEvent(Address from, Address to, int size) {
ids_.MoveObject(from, to, size);
}
void AllocationEvent(Address addr, int size);
void UpdateObjectSizeEvent(Address addr, int size) {
ids_.UpdateObjectSize(addr, size);
}
SnapshotObjectId last_assigned_id() const {
return ids_.last_assigned_id();
}
size_t GetUsedMemorySize() const;
int FindUntrackedObjects() { return ids_.FindUntrackedObjects(); }
private:
List<HeapSnapshot*> snapshots_;
StringsStorage names_;
// Mapping from HeapObject addresses to objects' uids.
HeapObjectsMap ids_;
AllocationTracker* allocation_tracker_;
DISALLOW_COPY_AND_ASSIGN(HeapSnapshotsCollection);
};
// A typedef for referencing anything that can be snapshotted living
// in any kind of heap memory.
typedef void* HeapThing;
......@@ -531,7 +474,8 @@ class V8HeapExplorer : public HeapEntriesAllocator {
Heap* heap_;
HeapSnapshot* snapshot_;
HeapSnapshotsCollection* collection_;
StringsStorage* names_;
HeapObjectsMap* heap_object_map_;
SnapshottingProgressReportingInterface* progress_;
SnapshotFillerInterface* filler_;
HeapObjectsSet objects_tags_;
......@@ -592,7 +536,7 @@ class NativeObjectsExplorer {
Isolate* isolate_;
HeapSnapshot* snapshot_;
HeapSnapshotsCollection* collection_;
StringsStorage* names_;
SnapshottingProgressReportingInterface* progress_;
bool embedder_queried_;
HeapObjectsSet in_groups_;
......
......@@ -196,6 +196,13 @@ class List {
DISALLOW_COPY_AND_ASSIGN(List);
};
template<typename T, class P>
size_t GetMemoryUsedByList(const List<T, P>& list) {
return list.length() * sizeof(T) + sizeof(list);
}
class Map;
class Type;
class Code;
......
......@@ -363,7 +363,7 @@ class HeapObjectsTracker {
~HeapObjectsTracker() {
i::Isolate::Current()->heap()->CollectAllAvailableGarbage();
CHECK_EQ(0, heap_profiler_->FindUntrackedObjects());
CHECK_EQ(0, heap_profiler_->heap_object_map()->FindUntrackedObjects());
heap_profiler_->StopHeapObjectsTracking();
}
......
......@@ -2055,7 +2055,8 @@ void HeapProfilerExtension::FindUntrackedObjects(
const v8::FunctionCallbackInfo<v8::Value>& args) {
i::HeapProfiler* heap_profiler =
reinterpret_cast<i::HeapProfiler*>(args.GetIsolate()->GetHeapProfiler());
int untracked_objects = heap_profiler->FindUntrackedObjects();
int untracked_objects =
heap_profiler->heap_object_map()->FindUntrackedObjects();
args.GetReturnValue().Set(untracked_objects);
CHECK_EQ(0, untracked_objects);
}
......@@ -2161,12 +2162,6 @@ static const char* record_trace_tree_source =
"for (var i = 0; i < 100; i++) start();\n";
static i::HeapSnapshot* ToInternal(const v8::HeapSnapshot* snapshot) {
return const_cast<i::HeapSnapshot*>(
reinterpret_cast<const i::HeapSnapshot*>(snapshot));
}
static AllocationTraceNode* FindNode(
AllocationTracker* tracker, const Vector<const char*>& names) {
AllocationTraceNode* node = tracker->trace_tree()->root();
......@@ -2201,10 +2196,8 @@ TEST(ArrayGrowLeftTrim) {
" a.shift();\n");
const char* names[] = { "(anonymous function)" };
const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(
v8::String::NewFromUtf8(env->GetIsolate(), "Test1"));
i::HeapSnapshotsCollection* collection = ToInternal(snapshot)->collection();
AllocationTracker* tracker = collection->allocation_tracker();
AllocationTracker* tracker =
reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker();
CHECK_NE(NULL, tracker);
// Resolve all function locations.
tracker->PrepareForSerialization();
......@@ -2229,10 +2222,8 @@ TEST(TrackHeapAllocations) {
CompileRun(record_trace_tree_source);
const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(
v8::String::NewFromUtf8(env->GetIsolate(), "Test"));
i::HeapSnapshotsCollection* collection = ToInternal(snapshot)->collection();
AllocationTracker* tracker = collection->allocation_tracker();
AllocationTracker* tracker =
reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker();
CHECK_NE(NULL, tracker);
// Resolve all function locations.
tracker->PrepareForSerialization();
......@@ -2282,10 +2273,8 @@ TEST(TrackBumpPointerAllocations) {
CompileRun(inline_heap_allocation_source);
const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(
v8::String::NewFromUtf8(env->GetIsolate(), "Test2"));
i::HeapSnapshotsCollection* collection = ToInternal(snapshot)->collection();
AllocationTracker* tracker = collection->allocation_tracker();
AllocationTracker* tracker =
reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker();
CHECK_NE(NULL, tracker);
// Resolve all function locations.
tracker->PrepareForSerialization();
......@@ -2310,10 +2299,8 @@ TEST(TrackBumpPointerAllocations) {
CompileRun(inline_heap_allocation_source);
const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(
v8::String::NewFromUtf8(env->GetIsolate(), "Test1"));
i::HeapSnapshotsCollection* collection = ToInternal(snapshot)->collection();
AllocationTracker* tracker = collection->allocation_tracker();
AllocationTracker* tracker =
reinterpret_cast<i::HeapProfiler*>(heap_profiler)->allocation_tracker();
CHECK_NE(NULL, tracker);
// Resolve all function locations.
tracker->PrepareForSerialization();
......
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