xo-gc: refactor: + GCObjectStore.verify_ok()

+ use in DX1Collector.verify_ok()
This commit is contained in:
Roland Conybeare 2026-04-03 18:04:52 -04:00
commit e08b659a73
3 changed files with 57 additions and 40 deletions

View file

@ -7,7 +7,6 @@
#include "GCObjectStoreConfig.hpp"
#include "ObjectTypeSlot.hpp"
//#include "Generation.hpp"
#include "object_age.hpp"
#include <xo/alloc2/role.hpp>
#include <array>
@ -15,6 +14,7 @@
namespace xo {
namespace mm {
class DX1Collector;
class X1VerifyStats;
/** @brief container to hold gc-aware objects for X1 collector
**/
@ -115,12 +115,28 @@ namespace xo {
**/
GCMoveCheckpoint snap_move_checkpoint(Generation upto);
/** verify consistency of this object store, on behalf of collector @p gc.
* Advancing counters in @p *p_verify_stats.
*
* @p gc argument is load-bearing so we have collector interface
* to call AGCObject visitor method (forward_children()) on each
* object stored here.
**/
void verify_ok(DX1Collector * gc,
X1VerifyStats * p_verify_stats) noexcept;
/** Register object type with this collector.
* Provides shallow copy and pointer forwarding for instances of this
* type.
**/
bool install_type(const AGCObject & meta) noexcept;
/** For each generation g in [0 ,.., upto)
* swap arenas assigned to {to-space, from-space}.
* Invoked once at the beginning of each gc cycle.
**/
void swap_roles(Generation upto) noexcept;
/** move subgraph at @p root to to-space on behalf of collector @p gc
* Special behavior relative to @ref _deep_move_interior :
* If @p root is not in gc-space, visit immediate children and move them in place (!).
@ -131,12 +147,6 @@ namespace xo {
obj<AGCObject> from_src,
Generation upto);
/** For each generation g in [0 ,.., upto)
* swap arenas assigned to {to-space, from-space}.
* Invoked once at the beginning of each gc cycle.
**/
void swap_roles(Generation upto) noexcept;
/** move interior subgraph at @p from_src to to-space.
* no-op if not in gc-space.
*

View file

@ -416,39 +416,7 @@ namespace xo {
}
// 3. scan to-space for each generation
for (Generation g(0); g < config_.n_generation_; ++g) {
const DArena * space = this->get_space(role::to_space(), g);
for (const AllocInfo & info : *space) {
if (info.is_forwarding_tseq()) {
++verify_stats_.n_fwd_;
} else {
typeseq tseq(info.tseq());
const AGCObject * iface = this->lookup_type(tseq);
if (iface && !(iface->_has_null_vptr())) {
const void * data = info.payload().first;
// assembled fop for gc-aware object
obj<AGCObject> gco(iface, const_cast<void *>(data));
// forward_children is hijacked here to verify
// child pointer validity.
//
// Nested control reenters
// X1Collector::forward_inplace() -> _verify_aux()
//
gco.forward_children(self);
} else {
++verify_stats_.n_no_iface_;
continue;
}
}
}
}
gco_store_.verify_ok(this, &(this->verify_stats_));
// 4. scan mutation logs
mlog_store_.verify_ok(&gco_store_,

View file

@ -682,6 +682,45 @@ namespace xo {
return gray_lo_v;
}
void
GCObjectStore::verify_ok(DX1Collector * gc,
X1VerifyStats * p_verify_stats) noexcept
{
for (Generation g(0); g < config_.n_generation_; ++g) {
const DArena * space = this->get_space(role::to_space(), g);
for (const AllocInfo & info : *space) {
if (info.is_forwarding_tseq()) {
++(p_verify_stats->n_fwd_);
} else {
typeseq tseq(info.tseq());
const AGCObject * iface = this->lookup_type(tseq);
if (iface && !(iface->_has_null_vptr())) {
const void * data = info.payload().first;
// assembled fop for gc-aware object
obj<AGCObject> gco(iface, const_cast<void *>(data));
// forward_children is hijacked here to verify
// child pointer validity.
//
// Nested control reenters
// X1Collector::forward_inplace() -> _verify_aux()
//
gco.forward_children(gc->ref<ACollector>());
} else {
++(p_verify_stats->n_no_iface_);
continue;
}
}
}
}
}
/* editor bait: register_type */
bool
GCObjectStore::install_type(const AGCObject & meta) noexcept