ART: Log approximate arena usage for slow verifier runs

Add ArenaStack::ApproximatePeakBytes and ScopedArenaAllocator::ApproximatePeakBytes
to get an approximate use when arena tracking is not enabled.

Print the approximate use for slow verifications.

Bug: 110852609
Test: m test-art-host
Test: manual
Change-Id: I529838410cdf4fe8247ddf4a6196a8186b0c4f3a
diff --git a/libartbase/base/scoped_arena_allocator.cc b/libartbase/base/scoped_arena_allocator.cc
index a54f350..a87064f 100644
--- a/libartbase/base/scoped_arena_allocator.cc
+++ b/libartbase/base/scoped_arena_allocator.cc
@@ -106,6 +106,15 @@
   return ptr;
 }
 
+size_t ArenaStack::ApproximatePeakBytes() {
+  UpdateBytesAllocated();
+  size_t sum = 0;
+  for (Arena* arena = bottom_arena_; arena != nullptr; arena = arena->next_) {
+    sum += arena->bytes_allocated_;
+  }
+  return sum;
+}
+
 ScopedArenaAllocator::ScopedArenaAllocator(ScopedArenaAllocator&& other) noexcept
     : DebugStackReference(std::move(other)),
       DebugStackRefCounter(),
@@ -158,4 +167,29 @@
   }
 }
 
+size_t ScopedArenaAllocator::ApproximatePeakBytes() {
+  size_t subtract;
+  Arena* start;
+  if (LIKELY(mark_arena_ != nullptr)) {
+    start = mark_arena_;
+    size_t mark_free = static_cast<size_t>(mark_end_ - mark_ptr_);
+    DCHECK_GE(mark_arena_->bytes_allocated_, mark_arena_->size_ - mark_free);
+    subtract = mark_arena_->bytes_allocated_ - (mark_arena_->size_ - mark_free);
+  } else {
+    start = arena_stack_->bottom_arena_;
+    subtract = 0;
+  }
+
+  size_t sum = 0;
+  for (Arena* arena = start; arena != nullptr; arena = arena->next_) {
+    if (arena == arena_stack_->top_arena_) {
+      sum += static_cast<size_t>(arena_stack_->top_ptr_ - arena->Begin());
+      break;
+    } else {
+      sum += arena->bytes_allocated_;
+    }
+  }
+  return sum - subtract;
+}
+
 }  // namespace art
diff --git a/libartbase/base/scoped_arena_allocator.h b/libartbase/base/scoped_arena_allocator.h
index 52d0361..6de0192 100644
--- a/libartbase/base/scoped_arena_allocator.h
+++ b/libartbase/base/scoped_arena_allocator.h
@@ -59,6 +59,8 @@
     return PeakStats()->BytesAllocated();
   }
 
+  size_t ApproximatePeakBytes();
+
   MemStats GetPeakStats() const;
 
   // Return the arena tag associated with a pointer.
@@ -166,6 +168,8 @@
   // Get adapter for use in STL containers. See scoped_arena_containers.h .
   ScopedArenaAllocatorAdapter<void> Adapter(ArenaAllocKind kind = kArenaAllocSTL);
 
+  size_t ApproximatePeakBytes();
+
   // Allow a delete-expression to destroy but not deallocate allocators created by Create().
   static void operator delete(void* ptr ATTRIBUTE_UNUSED) {}
 
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index ee91efa..4a3b5d1 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -5348,7 +5348,9 @@
       LOG(WARNING) << "Verification of " << dex_file->PrettyMethod(method_idx)
                    << " took " << PrettyDuration(duration_ns)
                    << (impl::IsLargeMethod(verifier.CodeItem()) ? " (large method)" : "")
-                   << " (" << StringPrintf("%.2f", bytecodes_per_second) << " bytecodes/s)";
+                   << " (" << StringPrintf("%.2f", bytecodes_per_second) << " bytecodes/s)"
+                   << " (" << verifier.allocator_.ApproximatePeakBytes()
+                   << "B approximate peak alloc)";
     }
   }
   result.types = verifier.encountered_failure_types_;