Index: src/profile-generator.cc |
diff --git a/src/profile-generator.cc b/src/profile-generator.cc |
index 814ff8d68dd935c43ea8a49725f4caa63bdb82e6..ee14fa92dce3e9e919cb36f14964a7feb6a67678 100644 |
--- a/src/profile-generator.cc |
+++ b/src/profile-generator.cc |
@@ -1406,6 +1406,82 @@ SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { |
} |
+SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr) { |
+ ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); |
+ HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true); |
+ if (entry->value != NULL) { |
+ int entry_index = |
+ static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
+ EntryInfo& entry_info = entries_->at(entry_index); |
+ entry_info.accessed = true; |
+ return entry_info.id; |
+ } |
+ entry->value = reinterpret_cast<void*>(entries_->length()); |
+ SnapshotObjectId id = next_id_; |
+ next_id_ += kObjectIdStep; |
+ entries_->Add(EntryInfo(id, addr)); |
+ ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); |
+ return id; |
+} |
+ |
+ |
+void HeapObjectsMap::StopHeapObjectsTracking() { |
+ time_intervals_.Clear(); |
+} |
+ |
+void HeapObjectsMap::UpdateHeapObjectsMap() { |
+ HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask, |
+ "HeapSnapshotsCollection::UpdateHeapObjectsMap"); |
+ HeapIterator iterator(HeapIterator::kFilterUnreachable); |
+ for (HeapObject* obj = iterator.next(); |
+ obj != NULL; |
+ obj = iterator.next()) { |
+ FindOrAddEntry(obj->address()); |
+ } |
+ initial_fill_mode_ = false; |
+ RemoveDeadEntries(); |
+} |
+ |
+ |
+void HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream) { |
+ UpdateHeapObjectsMap(); |
+ time_intervals_.Add(TimeInterval(next_id_)); |
+ int prefered_chunk_size = stream->GetChunkSize(); |
+ List<uint32_t> stats_buffer; |
+ ASSERT(!entries_->is_empty()); |
+ EntryInfo* entry_info = &entries_->first(); |
+ EntryInfo* end_entry_info = &entries_->last() + 1; |
+ for (int time_interval_index = 0; |
+ time_interval_index < time_intervals_.length(); |
+ ++time_interval_index) { |
+ TimeInterval& time_interval = time_intervals_[time_interval_index]; |
+ SnapshotObjectId time_interval_id = time_interval.id; |
+ uint32_t entries_count = 0; |
+ while (entry_info < end_entry_info && entry_info->id < time_interval_id) { |
+ ++entries_count; |
+ ++entry_info; |
+ } |
+ if (time_interval.count != entries_count) { |
+ stats_buffer.Add(time_interval_index); |
+ stats_buffer.Add(time_interval.count = entries_count); |
+ if (stats_buffer.length() >= prefered_chunk_size) { |
+ OutputStream::WriteResult result = stream->WriteUint32Chunk( |
+ &stats_buffer.first(), stats_buffer.length()); |
+ if (result == OutputStream::kAbort) return; |
+ stats_buffer.Clear(); |
+ } |
+ } |
+ } |
+ ASSERT(entry_info == end_entry_info); |
+ if (!stats_buffer.is_empty()) { |
+ OutputStream::WriteResult result = |
+ stream->WriteUint32Chunk(&stats_buffer.first(), stats_buffer.length()); |
+ if (result == OutputStream::kAbort) return; |
+ } |
+ stream->EndOfStream(); |
+} |
+ |
+ |
void HeapObjectsMap::RemoveDeadEntries() { |
ASSERT(entries_->length() > 0 && |
entries_->at(0).id == 0 && |