[heap-snapshot] Preventing overflow in progress counter

This prevents an overflow to happen in the heap snapshot generator.
Furthermore it changes the relation of progress_counter_ and
progress_total_ to always adhere to:
* progress_counter_ <= progress_total_,
* if: progress_counter_ == progress_total_, then it is done.

With this change, if progress_counter_ happens to be bigger
than progress_total_ (latter is an estimate), it will continue
to report the same progress (<100%) until it is done. Before,
it would repeatedly report 100% until it is done.

Fixed: chromium:1246860
Change-Id: Iffd3f52355632f2b35abdbb3752912ba7b8bd821
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3250310
Reviewed-by: Yang Guo <yangguo@chromium.org>
Commit-Queue: Kim-Anh Tran <kimanh@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77589}
This commit is contained in:
Kim-Anh Tran 2021-10-28 11:43:30 +02:00 committed by V8 LUCI CQ
parent e00b23d16c
commit 0e006a1527
2 changed files with 21 additions and 11 deletions

View File

@ -711,10 +711,15 @@ const char* V8HeapExplorer::GetSystemEntryName(HeapObject object) {
}
}
int V8HeapExplorer::EstimateObjectsCount() {
uint32_t V8HeapExplorer::EstimateObjectsCount() {
CombinedHeapObjectIterator it(heap_, HeapObjectIterator::kFilterUnreachable);
int objects_count = 0;
while (!it.Next().is_null()) ++objects_count;
uint32_t objects_count = 0;
// Avoid overflowing the objects count. In worst case, we will show the same
// progress for a longer period of time, but we do not expect to have that
// many objects.
while (!it.Next().is_null() &&
objects_count != std::numeric_limits<uint32_t>::max())
++objects_count;
return objects_count;
}
@ -2260,7 +2265,17 @@ bool HeapSnapshotGenerator::GenerateSnapshot() {
}
void HeapSnapshotGenerator::ProgressStep() {
++progress_counter_;
// Only increment the progress_counter_ until
// equal to progress_total -1 == progress_counter.
// This ensures that intermediate ProgressReport calls will never signal
// that the work is finished (i.e. progress_counter_ == progress_total_).
// Only the forced ProgressReport() at the end of GenerateSnapshot() should,
// after setting progress_counter_ = progress_total_, signal that the
// work is finished because signalling finished twice
// breaks the DevTools frontend.
if (progress_total_ > progress_counter_ + 1) {
++progress_counter_;
}
}
bool HeapSnapshotGenerator::ProgressReport(bool force) {
@ -2275,12 +2290,7 @@ bool HeapSnapshotGenerator::ProgressReport(bool force) {
void HeapSnapshotGenerator::InitProgressCounter() {
if (control_ == nullptr) return;
// The +1 ensures that intermediate ProgressReport calls will never signal
// that the work is finished (i.e. progress_counter_ == progress_total_).
// Only the forced ProgressReport() at the end of GenerateSnapshot()
// should signal that the work is finished because signalling finished twice
// breaks the DevTools frontend.
progress_total_ = v8_heap_explorer_.EstimateObjectsCount() + 1;
progress_total_ = v8_heap_explorer_.EstimateObjectsCount();
progress_counter_ = 0;
}

View File

@ -354,7 +354,7 @@ class V8_EXPORT_PRIVATE V8HeapExplorer : public HeapEntriesAllocator {
HeapEntry* AllocateEntry(HeapThing ptr) override;
HeapEntry* AllocateEntry(Smi smi) override;
int EstimateObjectsCount();
uint32_t EstimateObjectsCount();
bool IterateAndExtractReferences(HeapSnapshotGenerator* generator);
void CollectGlobalObjectsTags();
void MakeGlobalObjectTagMap(const SafepointScope& safepoint_scope);