Chromium Code Reviews| Index: src/heap-profiler.cc |
| diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc |
| index 3d8e3364c90a8be445052865cf000270962a7146..9205a08cfa9515a5bd5485ce6de01c233c377ac3 100644 |
| --- a/src/heap-profiler.cc |
| +++ b/src/heap-profiler.cc |
| @@ -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(allocation_tracker_.is_empty()); |
|
Michael Starzinger
2013/12/03 08:54:51
nit: I think it makes sense to use the is_tracking
yurys
2013/12/03 09:41:31
Done.
|
| 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,26 @@ void HeapProfiler::SetRetainedObjectInfo(UniqueId id, |
| } |
| +Handle<HeapObject> HeapProfiler::FindHeapObjectById( |
| + SnapshotObjectId id) { |
| + // First perform a full GC in order to avoid dead objects. |
| + heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask, |
|
alph
2013/12/03 09:20:20
Doesn't look like a Full GC.
yurys
2013/12/03 09:41:31
This comment was moved, I think it is outdated. Re
|
| + "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 |