diff a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp
--- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp
@@ -1,7 +1,8 @@
 /*
  * Copyright (c) 2016, 2023, Red Hat, Inc. All rights reserved.
+ * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.
@@ -22,10 +23,11 @@
  *
  */
 
 #include "precompiled.hpp"
 
+#include "gc/shenandoah/shenandoahAgeCensus.hpp"
 #include "gc/shenandoah/shenandoahCollectionSet.hpp"
 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
 #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp"
 #include "gc/shenandoah/shenandoahHeapRegionSet.hpp"
 #include "gc/shenandoah/shenandoahUtils.hpp"
@@ -38,13 +40,17 @@
   _region_size_bytes_shift(ShenandoahHeapRegion::region_size_bytes_shift()),
   _map_space(space),
   _cset_map(_map_space.base() + ((uintx)heap_base >> _region_size_bytes_shift)),
   _biased_cset_map(_map_space.base()),
   _heap(heap),
+  _has_old_regions(false),
   _garbage(0),
   _used(0),
+  _live(0),
   _region_count(0),
+  _old_garbage(0),
+  _preselected_regions(nullptr),
   _current_index(0) {
 
   // The collection set map is reserved to cover the entire heap *and* zero addresses.
   // This is needed to accept in-cset checks for both heap oops and nulls, freeing
   // high-performance code from checking for null first.
@@ -81,34 +87,62 @@
 
 void ShenandoahCollectionSet::add_region(ShenandoahHeapRegion* r) {
   assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
   assert(Thread::current()->is_VM_thread(), "Must be VMThread");
   assert(!is_in(r), "Already in collection set");
+  assert(!r->is_humongous(), "Only add regular regions to the collection set");
+
   _cset_map[r->index()] = 1;
+  size_t live    = r->get_live_data_bytes();
+  size_t garbage = r->garbage();
+  size_t free    = r->free();
+  if (r->is_young()) {
+    _young_bytes_to_evacuate += live;
+    _young_available_bytes_collected += free;
+    if (ShenandoahHeap::heap()->mode()->is_generational() && r->age() >= ShenandoahGenerationalHeap::heap()->age_census()->tenuring_threshold()) {
+      _young_bytes_to_promote += live;
+    }
+  } else if (r->is_old()) {
+    _old_bytes_to_evacuate += live;
+    _old_garbage += garbage;
+  }
+
   _region_count++;
-  _garbage += r->garbage();
+  _has_old_regions |= r->is_old();
+  _garbage += garbage;
   _used += r->used();
-
+  _live += live;
   // Update the region status too. State transition would be checked internally.
   r->make_cset();
 }
 
 void ShenandoahCollectionSet::clear() {
   assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
+
   Copy::zero_to_bytes(_cset_map, _map_size);
 
 #ifdef ASSERT
   for (size_t index = 0; index < _heap->num_regions(); index ++) {
     assert (!_heap->get_region(index)->is_cset(), "should have been cleared before");
   }
 #endif
 
   _garbage = 0;
+  _old_garbage = 0;
   _used = 0;
+  _live = 0;
 
   _region_count = 0;
   _current_index = 0;
+
+  _young_bytes_to_evacuate = 0;
+  _young_bytes_to_promote = 0;
+  _old_bytes_to_evacuate = 0;
+
+  _young_available_bytes_collected = 0;
+
+  _has_old_regions = false;
 }
 
 ShenandoahHeapRegion* ShenandoahCollectionSet::claim_next() {
   // This code is optimized for the case when collection set contains only
   // a few regions. In this case, it is more constructive to check for is_in
@@ -148,11 +182,15 @@
 
   return nullptr;
 }
 
 void ShenandoahCollectionSet::print_on(outputStream* out) const {
-  out->print_cr("Collection Set : " SIZE_FORMAT "", count());
+  out->print_cr("Collection Set: Regions: "
+                SIZE_FORMAT ", Garbage: " SIZE_FORMAT "%s, Live: " SIZE_FORMAT "%s, Used: " SIZE_FORMAT "%s", count(),
+                byte_size_in_proper_unit(garbage()), proper_unit_for_byte_size(garbage()),
+                byte_size_in_proper_unit(live()),    proper_unit_for_byte_size(live()),
+                byte_size_in_proper_unit(used()),    proper_unit_for_byte_size(used()));
 
   debug_only(size_t regions = 0;)
   for (size_t index = 0; index < _heap->num_regions(); index ++) {
     if (is_in(index)) {
       _heap->get_region(index)->print_on(out);
