xo-gc: refactor: demote GCObjectVisitor to GCObjectStore
No longer needed by DX1Collector Also retires utest/MockCollector
This commit is contained in:
parent
f09ec770aa
commit
456ea4dbb9
21 changed files with 242 additions and 331 deletions
|
|
@ -27,9 +27,9 @@ xo_add_genfacetimpl(
|
||||||
|
|
||||||
# note: manual target; generated code committed to git
|
# note: manual target; generated code committed to git
|
||||||
xo_add_genfacetimpl(
|
xo_add_genfacetimpl(
|
||||||
TARGET xo-gc-facetimpl-gcobjectvisitor-x1collector
|
TARGET xo-gc-facetimpl-gcobjectvisitor-gcobjectstorevisitor
|
||||||
FACET_PKG xo_alloc2
|
FACET_PKG xo_alloc2
|
||||||
INPUT idl/IGCObjectVisitor_DX1Collector.json5
|
INPUT idl/IGCObjectVisitor_DGCObjectStoreVisitor.json5
|
||||||
)
|
)
|
||||||
|
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|
|
||||||
28
xo-gc/idl/IGCObjectVisitor_DGCObjectStoreVisitor.json5
Normal file
28
xo-gc/idl/IGCObjectVisitor_DGCObjectStoreVisitor.json5
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
mode: "implementation",
|
||||||
|
output_cpp_dir: "src/gc/facet",
|
||||||
|
output_hpp_dir: "include/xo/gc",
|
||||||
|
output_impl_subdir: "detail",
|
||||||
|
includes: [
|
||||||
|
// "<xo/alloc2/GCObject.hpp>",
|
||||||
|
// "<xo/alloc2/Allocator.hpp>"
|
||||||
|
],
|
||||||
|
local_types: [
|
||||||
|
// {
|
||||||
|
// name: "typeseq",
|
||||||
|
// doc: ["identifies a c++ type"],
|
||||||
|
// definition: "xo::reflect::typeseq"
|
||||||
|
// },
|
||||||
|
],
|
||||||
|
namespace1: "xo",
|
||||||
|
namespace2: "mm",
|
||||||
|
facet_idl: "idl/GCObjectVisitor.json5",
|
||||||
|
brief: "provide AGCObjectVisitor interface for DGCObjectStoreVisitor",
|
||||||
|
using_doxygen: true,
|
||||||
|
repr: "DGCObjectStoreVisitor",
|
||||||
|
doc: [
|
||||||
|
"Implement AGCObjectVisitor for DGCObjectStoreVisitor.",
|
||||||
|
"Visit a gc-aware object. Either evacuate+forward (for gc cycle),",
|
||||||
|
"or check consistency (for verify_ok)",
|
||||||
|
],
|
||||||
|
}
|
||||||
49
xo-gc/include/xo/gc/DGCObjectStoreVisitor.hpp
Normal file
49
xo-gc/include/xo/gc/DGCObjectStoreVisitor.hpp
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
/** @file DGCObjectStoreVisitor.hpp
|
||||||
|
*
|
||||||
|
* @author Roland Conybeare, Apr 2026
|
||||||
|
**/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xo/alloc2/GCObjectVisitor.hpp>
|
||||||
|
#include <xo/alloc2/VisitReason.hpp>
|
||||||
|
#include <xo/alloc2/Generation.hpp>
|
||||||
|
#include <xo/alloc2/role.hpp>
|
||||||
|
#include <xo/arena/AllocInfo.hpp>
|
||||||
|
#include <xo/facet/obj.hpp>
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
namespace mm {
|
||||||
|
|
||||||
|
class GCObjectStore; // see GCObjectStore.hpp
|
||||||
|
class AGCObject; // see AGCObject.hpp
|
||||||
|
|
||||||
|
/** @brief visitor shim for GCObjectStore
|
||||||
|
*
|
||||||
|
* For a GC cycle, remembers which generations
|
||||||
|
* are being collected
|
||||||
|
**/
|
||||||
|
class DGCObjectStoreVisitor {
|
||||||
|
public:
|
||||||
|
DGCObjectStoreVisitor(GCObjectStore * gcos, Generation upto);
|
||||||
|
|
||||||
|
template <typename AFacet = AGCObjectVisitor>
|
||||||
|
obj<AFacet,DGCObjectStoreVisitor> ref() { return obj<AFacet,DGCObjectStoreVisitor>(this); }
|
||||||
|
|
||||||
|
Generation generation_of(Role r, const void * addr) const noexcept;
|
||||||
|
AllocInfo alloc_info(void * mem) const noexcept;
|
||||||
|
|
||||||
|
void visit_child(VisitReason reason, AGCObject * lhs_iface, void ** lhs_data);
|
||||||
|
std::byte * alloc_copy(void * src) noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** object storage **/
|
||||||
|
GCObjectStore * p_gco_store_ = nullptr;
|
||||||
|
/** collecting generations up to this bound **/
|
||||||
|
Generation upto_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /*namespace mm*/
|
||||||
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
/* end DGCObjectVisitor.hpp */
|
||||||
|
|
@ -134,7 +134,7 @@ namespace xo {
|
||||||
* to call AGCObject visitor method (forward_children()) on each
|
* to call AGCObject visitor method (forward_children()) on each
|
||||||
* object stored here.
|
* object stored here.
|
||||||
**/
|
**/
|
||||||
void verify_ok(obj<AGCObjectVisitor> gc) noexcept;
|
void verify_ok() noexcept;
|
||||||
|
|
||||||
/** Register object type with this collector.
|
/** Register object type with this collector.
|
||||||
* Provides shallow copy and pointer forwarding for instances of this
|
* Provides shallow copy and pointer forwarding for instances of this
|
||||||
|
|
@ -156,8 +156,7 @@ namespace xo {
|
||||||
*
|
*
|
||||||
* Require: runstate_.is_running()
|
* Require: runstate_.is_running()
|
||||||
**/
|
**/
|
||||||
void * deep_move_root(obj<AGCObjectVisitor> gc,
|
void * deep_move_root(const AGCObject * root_iface,
|
||||||
const AGCObject * root_iface,
|
|
||||||
void ** root_data,
|
void ** root_data,
|
||||||
Generation upto);
|
Generation upto);
|
||||||
|
|
||||||
|
|
@ -170,15 +169,16 @@ namespace xo {
|
||||||
void * from_src,
|
void * from_src,
|
||||||
Generation upto);
|
Generation upto);
|
||||||
|
|
||||||
#ifdef NOT_YET
|
|
||||||
/** Target for GCObjectVisitor facet
|
/** Target for GCObjectVisitor facet
|
||||||
* During gc phase (@p reason is 'forward')
|
* During gc phase (@p reason is 'forward')
|
||||||
* 1. evacuate object at @p *lhs_data to to-space.
|
* 1. evacuate object at @p *lhs_data to to-space.
|
||||||
* 2. replace @p *lhs_data with forwarding pointer
|
* 2. replace @p *lhs_data with forwarding pointer
|
||||||
* to new location.
|
* to new location.
|
||||||
**/
|
**/
|
||||||
void visit_child(VisitReason reason, AGCObject * lhs_iface, void ** lhs_data);
|
void visit_child_aux(VisitReason reason,
|
||||||
#endif
|
AGCObject * lhs_iface,
|
||||||
|
void ** lhs_data,
|
||||||
|
Generation upto);
|
||||||
|
|
||||||
/** Evacuate object at @p *lhs_data to to-space, during collection phase
|
/** Evacuate object at @p *lhs_data to to-space, during collection phase
|
||||||
* acting on generations g in [0 ,.., upto).
|
* acting on generations g in [0 ,.., upto).
|
||||||
|
|
|
||||||
11
xo-gc/include/xo/gc/GCObjectStoreVisitor.hpp
Normal file
11
xo-gc/include/xo/gc/GCObjectStoreVisitor.hpp
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
/** @file GCObjectStoreVisitor.hpp
|
||||||
|
*
|
||||||
|
* @author Roland Conybeare, Apr 2026
|
||||||
|
**/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DGCObjectStoreVisitor.hpp"
|
||||||
|
#include "detail/IGCObjectVisitor_DGCObjectStoreVisitor.hpp"
|
||||||
|
|
||||||
|
/* end GCObjectStoreVisitor.hpp */
|
||||||
|
|
@ -8,6 +8,5 @@
|
||||||
#include "DX1Collector.hpp"
|
#include "DX1Collector.hpp"
|
||||||
#include "detail/ICollector_DX1Collector.hpp"
|
#include "detail/ICollector_DX1Collector.hpp"
|
||||||
#include "detail/IAllocator_DX1Collector.hpp"
|
#include "detail/IAllocator_DX1Collector.hpp"
|
||||||
#include "detail/IGCObjectVisitor_DX1Collector.hpp"
|
|
||||||
|
|
||||||
/* end X1Collector.hpp */
|
/* end X1Collector.hpp */
|
||||||
|
|
|
||||||
|
|
@ -1,64 +1,64 @@
|
||||||
/** @file IGCObjectVisitor_DX1Collector.hpp
|
/** @file IGCObjectVisitor_DGCObjectStoreVisitor.hpp
|
||||||
*
|
*
|
||||||
* Generated automagically from ingredients:
|
* Generated automagically from ingredients:
|
||||||
* 1. code generator:
|
* 1. code generator:
|
||||||
* [xo-facet/codegen/genfacet]
|
* [xo-facet/codegen/genfacet]
|
||||||
* arguments:
|
* arguments:
|
||||||
* --input [idl/IGCObjectVisitor_DX1Collector.json5]
|
* --input [idl/IGCObjectVisitor_DGCObjectStoreVisitor.json5]
|
||||||
* 2. jinja2 template for abstract facet .hpp file:
|
* 2. jinja2 template for abstract facet .hpp file:
|
||||||
* [iface_facet_repr.hpp.j2]
|
* [iface_facet_repr.hpp.j2]
|
||||||
* 3. idl for facet methods
|
* 3. idl for facet methods
|
||||||
* [idl/IGCObjectVisitor_DX1Collector.json5]
|
* [idl/IGCObjectVisitor_DGCObjectStoreVisitor.json5]
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "GCObjectVisitor.hpp"
|
#include "GCObjectVisitor.hpp"
|
||||||
#include "DX1Collector.hpp"
|
#include "DGCObjectStoreVisitor.hpp"
|
||||||
|
|
||||||
namespace xo { namespace mm { class IGCObjectVisitor_DX1Collector; } }
|
namespace xo { namespace mm { class IGCObjectVisitor_DGCObjectStoreVisitor; } }
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
namespace facet {
|
namespace facet {
|
||||||
template <>
|
template <>
|
||||||
struct FacetImplementation<xo::mm::AGCObjectVisitor,
|
struct FacetImplementation<xo::mm::AGCObjectVisitor,
|
||||||
xo::mm::DX1Collector>
|
xo::mm::DGCObjectStoreVisitor>
|
||||||
{
|
{
|
||||||
using ImplType = xo::mm::IGCObjectVisitor_Xfer
|
using ImplType = xo::mm::IGCObjectVisitor_Xfer
|
||||||
<xo::mm::DX1Collector,
|
<xo::mm::DGCObjectStoreVisitor,
|
||||||
xo::mm::IGCObjectVisitor_DX1Collector>;
|
xo::mm::IGCObjectVisitor_DGCObjectStoreVisitor>;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
namespace mm {
|
namespace mm {
|
||||||
/** @class IGCObjectVisitor_DX1Collector
|
/** @class IGCObjectVisitor_DGCObjectStoreVisitor
|
||||||
**/
|
**/
|
||||||
class IGCObjectVisitor_DX1Collector {
|
class IGCObjectVisitor_DGCObjectStoreVisitor {
|
||||||
public:
|
public:
|
||||||
/** @defgroup mm-gcobjectvisitor-dx1collector-type-traits **/
|
/** @defgroup mm-gcobjectvisitor-dgcobjectstorevisitor-type-traits **/
|
||||||
///@{
|
///@{
|
||||||
using Copaque = xo::mm::AGCObjectVisitor::Copaque;
|
using Copaque = xo::mm::AGCObjectVisitor::Copaque;
|
||||||
using Opaque = xo::mm::AGCObjectVisitor::Opaque;
|
using Opaque = xo::mm::AGCObjectVisitor::Opaque;
|
||||||
///@}
|
///@}
|
||||||
/** @defgroup mm-gcobjectvisitor-dx1collector-methods **/
|
/** @defgroup mm-gcobjectvisitor-dgcobjectstorevisitor-methods **/
|
||||||
///@{
|
///@{
|
||||||
// const methods
|
// const methods
|
||||||
/** allocation metadata for gc-aware data at address @p gco.
|
/** allocation metadata for gc-aware data at address @p gco.
|
||||||
@p gco must be the result of a call to collector's alloc() function **/
|
@p gco must be the result of a call to collector's alloc() function **/
|
||||||
static AllocInfo alloc_info(const DX1Collector & self, void * addr);
|
static AllocInfo alloc_info(const DGCObjectStoreVisitor & self, void * addr);
|
||||||
/** generation to which pointer @p addr belongs, given role @p r;
|
/** generation to which pointer @p addr belongs, given role @p r;
|
||||||
sentinel if @p addr is not owned by collector **/
|
sentinel if @p addr is not owned by collector **/
|
||||||
static Generation generation_of(const DX1Collector & self, Role r, const void * addr) noexcept;
|
static Generation generation_of(const DGCObjectStoreVisitor & self, Role r, const void * addr) noexcept;
|
||||||
|
|
||||||
// non-const methods
|
// non-const methods
|
||||||
/** allocate copy of source object at address @p src.
|
/** allocate copy of source object at address @p src.
|
||||||
Source must be owned by this collector.
|
Source must be owned by this collector.
|
||||||
Increments object age **/
|
Increments object age **/
|
||||||
static void * alloc_copy(DX1Collector & self, std::byte * src);
|
static void * alloc_copy(DGCObjectStoreVisitor & self, std::byte * src);
|
||||||
/** visit child of a gc-aware object. May update child in-place! **/
|
/** visit child of a gc-aware object. May update child in-place! **/
|
||||||
static void visit_child(DX1Collector & self, VisitReason reason, AGCObject * iface, void ** pp_data) noexcept;
|
static void visit_child(DGCObjectStoreVisitor & self, VisitReason reason, AGCObject * iface, void ** pp_data) noexcept;
|
||||||
///@}
|
///@}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -12,10 +12,12 @@ set(SELF_SRCS
|
||||||
X1CollectorConfig.cpp
|
X1CollectorConfig.cpp
|
||||||
DX1Collector.cpp
|
DX1Collector.cpp
|
||||||
facet/ICollector_DX1Collector.cpp
|
facet/ICollector_DX1Collector.cpp
|
||||||
facet/IGCObjectVisitor_DX1Collector.cpp
|
|
||||||
|
|
||||||
DX1CollectorIterator.cpp
|
DX1CollectorIterator.cpp
|
||||||
|
|
||||||
|
DGCObjectStoreVisitor.cpp
|
||||||
|
facet/IGCObjectVisitor_DGCObjectStoreVisitor.cpp
|
||||||
|
|
||||||
GCObjectStoreConfig.cpp
|
GCObjectStoreConfig.cpp
|
||||||
GCObjectStore.cpp
|
GCObjectStore.cpp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,34 @@
|
||||||
/** @file DMockCollector.cpp
|
/** @file DGCObjectStoreVisitor.cpp
|
||||||
*
|
*
|
||||||
* @author Roland Conybeare, Apr 2026
|
* @author Roland Conybeare, Apr 2026
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include "MockCollector.hpp"
|
#include "GCObjectStoreVisitor.hpp"
|
||||||
|
#include "GCObjectStore.hpp"
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
namespace mm {
|
namespace mm {
|
||||||
|
|
||||||
|
DGCObjectStoreVisitor::DGCObjectStoreVisitor(GCObjectStore * gcos,
|
||||||
|
Generation upto)
|
||||||
|
: p_gco_store_{gcos}, upto_{upto}
|
||||||
|
{}
|
||||||
|
|
||||||
Generation
|
Generation
|
||||||
DMockCollector::generation_of(Role r, const void * addr) const noexcept
|
DGCObjectStoreVisitor::generation_of(Role r, const void * addr) const noexcept
|
||||||
{
|
{
|
||||||
return p_gco_store_->generation_of(r, addr);
|
return p_gco_store_->generation_of(r, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
AllocInfo
|
AllocInfo
|
||||||
DMockCollector::alloc_info(void * mem) const noexcept
|
DGCObjectStoreVisitor::alloc_info(void * mem) const noexcept
|
||||||
{
|
{
|
||||||
return p_gco_store_->alloc_info((std::byte *)mem);
|
return p_gco_store_->alloc_info((std::byte *)mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DMockCollector::visit_child(VisitReason reason, AGCObject * lhs_iface, void ** lhs_data)
|
DGCObjectStoreVisitor::visit_child(VisitReason reason,
|
||||||
|
AGCObject * lhs_iface, void ** lhs_data)
|
||||||
{
|
{
|
||||||
switch (reason.code()) {
|
switch (reason.code()) {
|
||||||
case VisitReason::code::forward:
|
case VisitReason::code::forward:
|
||||||
|
|
@ -37,11 +44,11 @@ namespace xo {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::byte *
|
std::byte *
|
||||||
DMockCollector::alloc_copy(void * src) noexcept {
|
DGCObjectStoreVisitor::alloc_copy(void * src) noexcept {
|
||||||
return p_gco_store_->new_space()->alloc_copy((std::byte *)src);
|
return p_gco_store_->new_space()->alloc_copy((std::byte *)src);
|
||||||
}
|
}
|
||||||
|
|
||||||
} /*namespace mm*/
|
} /*namespace mm*/
|
||||||
} /*namespace xo*/
|
} /*namespace xo*/
|
||||||
|
|
||||||
/* end DMockCollector.cpp */
|
/* end DGCObjectVisitor.cpp */
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include "X1Collector.hpp"
|
#include "X1Collector.hpp"
|
||||||
|
#include "GCObjectStoreVisitor.hpp"
|
||||||
#include <xo/gc/DX1CollectorIterator.hpp>
|
#include <xo/gc/DX1CollectorIterator.hpp>
|
||||||
|
|
||||||
#include <xo/object2/Dictionary.hpp>
|
#include <xo/object2/Dictionary.hpp>
|
||||||
|
|
@ -13,7 +14,6 @@
|
||||||
#include <xo/stringtable2/String.hpp>
|
#include <xo/stringtable2/String.hpp>
|
||||||
|
|
||||||
#include <xo/alloc2/GCObject.hpp>
|
#include <xo/alloc2/GCObject.hpp>
|
||||||
#include <xo/alloc2/GCObjectVisitor.hpp>
|
|
||||||
#include <xo/alloc2/Allocator.hpp>
|
#include <xo/alloc2/Allocator.hpp>
|
||||||
#include <xo/alloc2/Arena.hpp>
|
#include <xo/alloc2/Arena.hpp>
|
||||||
#include "object_age.hpp"
|
#include "object_age.hpp"
|
||||||
|
|
@ -383,7 +383,8 @@ namespace xo {
|
||||||
// Add run state so DX1Collector can recognize forward_inplace()
|
// Add run state so DX1Collector can recognize forward_inplace()
|
||||||
// calls made for the purpose of checking child pointers.
|
// calls made for the purpose of checking child pointers.
|
||||||
|
|
||||||
auto self = this->ref<AGCObjectVisitor>();
|
DGCObjectStoreVisitor visitor(&gco_store_,
|
||||||
|
Generation{0} /*not used for verify*/);
|
||||||
|
|
||||||
GCRunState saved_runstate = runstate_;
|
GCRunState saved_runstate = runstate_;
|
||||||
{
|
{
|
||||||
|
|
@ -404,8 +405,7 @@ namespace xo {
|
||||||
// - X1Collector::forward_inplace() -> _verify_aux()
|
// - X1Collector::forward_inplace() -> _verify_aux()
|
||||||
//
|
//
|
||||||
|
|
||||||
gco.visit_gco_children(VisitReason::verify(), self);
|
gco.visit_gco_children(VisitReason::verify(), visitor.ref());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
X1VerifyStats post = verify_stats_;
|
X1VerifyStats post = verify_stats_;
|
||||||
|
|
@ -417,7 +417,7 @@ namespace xo {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. scan to-space for each generation
|
// 3. scan to-space for each generation
|
||||||
gco_store_.verify_ok(this->ref<AGCObjectVisitor>());
|
gco_store_.verify_ok();
|
||||||
|
|
||||||
// 4. scan mutation logs
|
// 4. scan mutation logs
|
||||||
mlog_store_.verify_ok(&gco_store_,
|
mlog_store_.verify_ok(&gco_store_,
|
||||||
|
|
@ -483,7 +483,7 @@ namespace xo {
|
||||||
//auto t0 = std::chrono::steady_clock::now();
|
//auto t0 = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
log && log("memory");
|
log && log("memory");
|
||||||
auto visitor = [&log](const MemorySizeInfo & info) {
|
auto resource_visitor = [&log](const MemorySizeInfo & info) {
|
||||||
log && log(xtag("resource", info.resource_name_),
|
log && log(xtag("resource", info.resource_name_),
|
||||||
xtag("used", info.used_),
|
xtag("used", info.used_),
|
||||||
xtag("alloc", info.allocated_),
|
xtag("alloc", info.allocated_),
|
||||||
|
|
@ -492,7 +492,7 @@ namespace xo {
|
||||||
xtag("lo", info.lo_),
|
xtag("lo", info.lo_),
|
||||||
xtag("hi", info.hi_));
|
xtag("hi", info.hi_));
|
||||||
};
|
};
|
||||||
this->visit_pools(visitor);
|
this->visit_pools(resource_visitor);
|
||||||
|
|
||||||
if (config_.sanitize_flag_) {
|
if (config_.sanitize_flag_) {
|
||||||
log && log("step 0a : verify");
|
log && log("step 0a : verify");
|
||||||
|
|
@ -500,6 +500,8 @@ namespace xo {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DGCObjectStoreVisitor gco_visitor(&gco_store_, upto);
|
||||||
|
|
||||||
log && log("step 0b : update run state");
|
log && log("step 0b : update run state");
|
||||||
this->runstate_ = GCRunState::gc_upto(upto);
|
this->runstate_ = GCRunState::gc_upto(upto);
|
||||||
|
|
||||||
|
|
@ -519,7 +521,7 @@ namespace xo {
|
||||||
log && log("step 2b : [STUB] copy pinned");
|
log && log("step 2b : [STUB] copy pinned");
|
||||||
|
|
||||||
log && log("step 3 : [STUB] forward mutation log");
|
log && log("step 3 : [STUB] forward mutation log");
|
||||||
mlog_store_.forward_mutation_log(this->ref<AGCObjectVisitor>(), upto);
|
mlog_store_.forward_mutation_log(gco_visitor.ref(), upto);
|
||||||
|
|
||||||
log && log("step 4a : [STUB] run destructors");
|
log && log("step 4a : [STUB] run destructors");
|
||||||
log && log("step 4b : [STUB] keep reachable weak pointers");
|
log && log("step 4b : [STUB] keep reachable weak pointers");
|
||||||
|
|
@ -576,8 +578,7 @@ namespace xo {
|
||||||
xtag("slot.root()", slot.root()),
|
xtag("slot.root()", slot.root()),
|
||||||
xtag("slot.root()->data_", slot.root()->data_));
|
xtag("slot.root()->data_", slot.root()->data_));
|
||||||
|
|
||||||
void * root_to = gco_store_.deep_move_root(this->ref<AGCObjectVisitor>(),
|
void * root_to = gco_store_.deep_move_root(slot.root()->iface(),
|
||||||
slot.root()->iface(),
|
|
||||||
(void **)&(slot.root()->data_), upto);
|
(void **)&(slot.root()->data_), upto);
|
||||||
|
|
||||||
slot.root()->reset_opaque(root_to);
|
slot.root()->reset_opaque(root_to);
|
||||||
|
|
@ -594,24 +595,9 @@ namespace xo {
|
||||||
// MAYBE: adapter distinct from DX1Collector that supports GCObjectVisitor facet,
|
// MAYBE: adapter distinct from DX1Collector that supports GCObjectVisitor facet,
|
||||||
// calls DX1Collector::_verify_aux()
|
// calls DX1Collector::_verify_aux()
|
||||||
|
|
||||||
switch (reason.code()) {
|
Generation upto = runstate_.gc_upto();
|
||||||
case VisitReason::code::forward:
|
|
||||||
{
|
|
||||||
Generation upto = runstate_.gc_upto();
|
|
||||||
|
|
||||||
// called during collection phase
|
gco_store_.visit_child_aux(reason, lhs_iface, lhs_data, upto);
|
||||||
gco_store_.forward_inplace_aux
|
|
||||||
(this->ref<AGCObjectVisitor>(), lhs_iface, lhs_data, upto);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case VisitReason::code::verify:
|
|
||||||
// called during verify_ok
|
|
||||||
gco_store_.verify_aux(lhs_iface, *lhs_data);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// should be unreachable
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto
|
auto
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include "GCObjectStore.hpp"
|
#include "GCObjectStore.hpp"
|
||||||
|
#include "GCObjectStoreVisitor.hpp"
|
||||||
#include "X1VerifyStats.hpp"
|
#include "X1VerifyStats.hpp"
|
||||||
|
|
||||||
#include <xo/object2/Dictionary.hpp>
|
#include <xo/object2/Dictionary.hpp>
|
||||||
|
|
@ -475,35 +476,33 @@ namespace xo {
|
||||||
return (g < upto);
|
return (g < upto);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NOT_YET
|
|
||||||
void
|
void
|
||||||
GCObjectStore::visit_child(VisitReason reason,
|
GCObjectStore::visit_child_aux(VisitReason reason,
|
||||||
AGCObject * lhs_iface,
|
AGCObject * lhs_iface,
|
||||||
void ** lhs_data)
|
void ** lhs_data,
|
||||||
|
Generation upto)
|
||||||
{
|
{
|
||||||
// MAYBE: adapter distinct from DX1Collector that supports GCObjectVisitor facet,
|
|
||||||
// calls DX1Collector::_verify_aux()
|
|
||||||
|
|
||||||
switch (reason.code()) {
|
switch (reason.code()) {
|
||||||
case VisitReason::code::forward:
|
case VisitReason::code::forward:
|
||||||
{
|
{
|
||||||
Generation upto = runstate_.gc_upto();
|
DGCObjectStoreVisitor gcos_visitor(this, upto);
|
||||||
|
auto gcos_visitor_obj
|
||||||
|
= obj<AGCObjectVisitor,DGCObjectStoreVisitor>(&gcos_visitor);
|
||||||
|
|
||||||
// called during collection phase
|
// called during collection phase
|
||||||
this->forward_inplace_aux
|
this->forward_inplace_aux
|
||||||
(this->ref<AGCObjectVisitor>(), lhs_iface, lhs_data, upto);
|
(gcos_visitor_obj, lhs_iface, lhs_data, upto);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VisitReason::code::verify:
|
case VisitReason::code::verify:
|
||||||
// called during verify_ok
|
// called during verify_ok
|
||||||
gco_store_.verify_aux(lhs_iface, *lhs_data);
|
this->verify_aux(lhs_iface, *lhs_data);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// should be unreachable
|
// should be unreachable
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
GCObjectStore::forward_inplace_aux(obj<AGCObjectVisitor> gc,
|
GCObjectStore::forward_inplace_aux(obj<AGCObjectVisitor> gc,
|
||||||
|
|
@ -768,8 +767,11 @@ namespace xo {
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GCObjectStore::verify_ok(obj<AGCObjectVisitor> gc) noexcept
|
GCObjectStore::verify_ok() noexcept
|
||||||
{
|
{
|
||||||
|
Generation unused_gen;
|
||||||
|
DGCObjectStoreVisitor visitor{this, unused_gen};
|
||||||
|
|
||||||
for (Generation g(0); g < config_.n_generation_; ++g) {
|
for (Generation g(0); g < config_.n_generation_; ++g) {
|
||||||
const DArena * space = this->get_space(Role::to_space(), g);
|
const DArena * space = this->get_space(Role::to_space(), g);
|
||||||
|
|
||||||
|
|
@ -789,7 +791,7 @@ namespace xo {
|
||||||
// assembled fop for gc-aware object
|
// assembled fop for gc-aware object
|
||||||
obj<AGCObject> gco(iface, const_cast<void *>(data));
|
obj<AGCObject> gco(iface, const_cast<void *>(data));
|
||||||
|
|
||||||
gco.visit_gco_children(VisitReason::verify(), gc);
|
gco.visit_gco_children(VisitReason::verify(), visitor.ref());
|
||||||
} else {
|
} else {
|
||||||
++(p_verify_stats_->n_no_iface_);
|
++(p_verify_stats_->n_no_iface_);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -830,8 +832,7 @@ namespace xo {
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
GCObjectStore::deep_move_root(obj<AGCObjectVisitor> gc,
|
GCObjectStore::deep_move_root(const AGCObject * root_iface,
|
||||||
const AGCObject * root_iface,
|
|
||||||
void ** root_data,
|
void ** root_data,
|
||||||
Generation upto)
|
Generation upto)
|
||||||
{
|
{
|
||||||
|
|
@ -849,8 +850,10 @@ namespace xo {
|
||||||
|
|
||||||
bool src_in_from_space = this->contains(Role::from_space(), *root_data);
|
bool src_in_from_space = this->contains(Role::from_space(), *root_data);
|
||||||
|
|
||||||
|
DGCObjectStoreVisitor visitor(this, upto);
|
||||||
|
|
||||||
if (src_in_from_space) {
|
if (src_in_from_space) {
|
||||||
*root_data = this->_deep_move_gc_owned(gc, *root_data, upto);
|
*root_data = this->_deep_move_gc_owned(visitor.ref(), *root_data, upto);
|
||||||
} else {
|
} else {
|
||||||
// we aren't moving from_src, it's not gc-owned.
|
// we aren't moving from_src, it's not gc-owned.
|
||||||
// However we are moving all its gc-owned children
|
// However we are moving all its gc-owned children
|
||||||
|
|
@ -860,7 +863,7 @@ namespace xo {
|
||||||
|
|
||||||
auto root = obj<AGCObject>(root_iface, *root_data);
|
auto root = obj<AGCObject>(root_iface, *root_data);
|
||||||
|
|
||||||
root.visit_gco_children(VisitReason::forward(), gc);
|
root.visit_gco_children(VisitReason::forward(), visitor.ref());
|
||||||
|
|
||||||
// For each generation g:
|
// For each generation g:
|
||||||
// traverse objects newer than gray_lo_v[g], to make sure children
|
// traverse objects newer than gray_lo_v[g], to make sure children
|
||||||
|
|
@ -868,7 +871,7 @@ namespace xo {
|
||||||
// Remember that forwarding may promote objects to older generation,
|
// Remember that forwarding may promote objects to older generation,
|
||||||
// so need multiple passes
|
// so need multiple passes
|
||||||
//
|
//
|
||||||
this->_forward_children_until_fixpoint(gc, upto, gray_lo_v);
|
this->_forward_children_until_fixpoint(visitor.ref(), upto, gray_lo_v);
|
||||||
|
|
||||||
// reminder: *root_data preserved
|
// reminder: *root_data preserved
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "SetupGc.hpp"
|
#include "SetupGc.hpp"
|
||||||
#include "X1Collector.hpp"
|
#include "X1Collector.hpp"
|
||||||
|
#include "GCObjectStoreVisitor.hpp"
|
||||||
#include <xo/facet/FacetRegistry.hpp>
|
#include <xo/facet/FacetRegistry.hpp>
|
||||||
#include <xo/indentlog/scope.hpp>
|
#include <xo/indentlog/scope.hpp>
|
||||||
|
|
||||||
|
|
@ -24,9 +25,11 @@ namespace xo {
|
||||||
|
|
||||||
FacetRegistry::register_impl<AAllocator, DX1Collector>();
|
FacetRegistry::register_impl<AAllocator, DX1Collector>();
|
||||||
FacetRegistry::register_impl<ACollector, DX1Collector>();
|
FacetRegistry::register_impl<ACollector, DX1Collector>();
|
||||||
FacetRegistry::register_impl<AGCObjectVisitor, DX1Collector>();
|
|
||||||
|
FacetRegistry::register_impl<AGCObjectVisitor, DGCObjectStoreVisitor>();
|
||||||
|
|
||||||
log && log(xtag("DX1Collector.tseq", typeseq::id<DX1Collector>()));
|
log && log(xtag("DX1Collector.tseq", typeseq::id<DX1Collector>()));
|
||||||
|
log && log(xtag("DGCObjectStoreVisitor.tseq", typeseq::id<DGCObjectStoreVisitor>()));
|
||||||
|
|
||||||
log && log(xtag("ACollector.tseq", typeseq::id<ACollector>()));
|
log && log(xtag("ACollector.tseq", typeseq::id<ACollector>()));
|
||||||
log && log(xtag("AGCObjectVisitor.tseq", typeseq::id<AGCObjectVisitor>()));
|
log && log(xtag("AGCObjectVisitor.tseq", typeseq::id<AGCObjectVisitor>()));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/** @file IGCObjectVisitor_DGCObjectStoreVisitor.cpp
|
||||||
|
*
|
||||||
|
* Generated automagically from ingredients:
|
||||||
|
* 1. code generator:
|
||||||
|
* [xo-facet/codegen/genfacet]
|
||||||
|
* arguments:
|
||||||
|
* --input [idl/IGCObjectVisitor_DGCObjectStoreVisitor.json5]
|
||||||
|
* 2. jinja2 template for abstract facet .hpp file:
|
||||||
|
* [iface_facet_any.hpp.j2]
|
||||||
|
* 3. idl for facet methods
|
||||||
|
* [idl/IGCObjectVisitor_DGCObjectStoreVisitor.json5]
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "detail/IGCObjectVisitor_DGCObjectStoreVisitor.hpp"
|
||||||
|
|
||||||
|
namespace xo {
|
||||||
|
namespace mm {
|
||||||
|
auto
|
||||||
|
IGCObjectVisitor_DGCObjectStoreVisitor::alloc_info(const DGCObjectStoreVisitor & self, void * addr) -> AllocInfo
|
||||||
|
{
|
||||||
|
return self.alloc_info(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto
|
||||||
|
IGCObjectVisitor_DGCObjectStoreVisitor::generation_of(const DGCObjectStoreVisitor & self, Role r, const void * addr) noexcept -> Generation
|
||||||
|
{
|
||||||
|
return self.generation_of(r, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto
|
||||||
|
IGCObjectVisitor_DGCObjectStoreVisitor::alloc_copy(DGCObjectStoreVisitor & self, std::byte * src) -> void *
|
||||||
|
{
|
||||||
|
return self.alloc_copy(src);
|
||||||
|
}
|
||||||
|
auto
|
||||||
|
IGCObjectVisitor_DGCObjectStoreVisitor::visit_child(DGCObjectStoreVisitor & self, VisitReason reason, AGCObject * iface, void ** pp_data) noexcept -> void
|
||||||
|
{
|
||||||
|
self.visit_child(reason, iface, pp_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
} /*namespace mm*/
|
||||||
|
} /*namespace xo*/
|
||||||
|
|
||||||
|
/* end IGCObjectVisitor_DGCObjectStoreVisitor.cpp */
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
/** @file IGCObjectVisitor_DX1Collector.cpp
|
|
||||||
*
|
|
||||||
* Generated automagically from ingredients:
|
|
||||||
* 1. code generator:
|
|
||||||
* [xo-facet/codegen/genfacet]
|
|
||||||
* arguments:
|
|
||||||
* --input [idl/IGCObjectVisitor_DX1Collector.json5]
|
|
||||||
* 2. jinja2 template for abstract facet .hpp file:
|
|
||||||
* [iface_facet_any.hpp.j2]
|
|
||||||
* 3. idl for facet methods
|
|
||||||
* [idl/IGCObjectVisitor_DX1Collector.json5]
|
|
||||||
**/
|
|
||||||
|
|
||||||
#include "detail/IGCObjectVisitor_DX1Collector.hpp"
|
|
||||||
|
|
||||||
namespace xo {
|
|
||||||
namespace mm {
|
|
||||||
auto
|
|
||||||
IGCObjectVisitor_DX1Collector::alloc_info(const DX1Collector & self, void * addr) -> AllocInfo
|
|
||||||
{
|
|
||||||
return self.alloc_info(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
IGCObjectVisitor_DX1Collector::generation_of(const DX1Collector & self, Role r, const void * addr) noexcept -> Generation
|
|
||||||
{
|
|
||||||
return self.generation_of(r, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
IGCObjectVisitor_DX1Collector::alloc_copy(DX1Collector & self, std::byte * src) -> void *
|
|
||||||
{
|
|
||||||
return self.alloc_copy(src);
|
|
||||||
}
|
|
||||||
auto
|
|
||||||
IGCObjectVisitor_DX1Collector::visit_child(DX1Collector & self, VisitReason reason, AGCObject * iface, void ** pp_data) noexcept -> void
|
|
||||||
{
|
|
||||||
self.visit_child(reason, iface, pp_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
} /*namespace mm*/
|
|
||||||
} /*namespace xo*/
|
|
||||||
|
|
||||||
/* end IGCObjectVisitor_DX1Collector.cpp */
|
|
||||||
|
|
@ -10,20 +10,10 @@ set(UTEST_SRCS
|
||||||
GCObjectStore.test.cpp
|
GCObjectStore.test.cpp
|
||||||
Object2.test.cpp
|
Object2.test.cpp
|
||||||
|
|
||||||
DMockCollector.cpp
|
|
||||||
IGCObjectVisitor_DMockCollector.cpp
|
|
||||||
|
|
||||||
init_gc_utest.cpp
|
init_gc_utest.cpp
|
||||||
random_allocs.cpp
|
random_allocs.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# mock collector for unit test
|
|
||||||
xo_add_genfacetimpl(
|
|
||||||
TARGET xo-gc-facetimpl-gcobjectvisitor-mockcollector
|
|
||||||
FACET_PKG xo_alloc2
|
|
||||||
INPUT idl/IGCObjectVisitor_DMockCollector.json5
|
|
||||||
)
|
|
||||||
|
|
||||||
if (ENABLE_TESTING)
|
if (ENABLE_TESTING)
|
||||||
xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS})
|
xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS})
|
||||||
xo_headeronly_dependency(${UTEST_EXE} randomgen)
|
xo_headeronly_dependency(${UTEST_EXE} randomgen)
|
||||||
|
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
/** @file DMockCollector.hpp
|
|
||||||
*
|
|
||||||
* @author Roland Conybeare, Apr 2026
|
|
||||||
**/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <xo/gc/GCObjectStore.hpp>
|
|
||||||
#include <xo/arena/AllocInfo.hpp>
|
|
||||||
|
|
||||||
namespace xo {
|
|
||||||
namespace mm {
|
|
||||||
|
|
||||||
/** @brief Mock Collector
|
|
||||||
*
|
|
||||||
* Intended to help unit test a GCObjectSotre instance.
|
|
||||||
* Mock a Collector in collection phase for generations 0 <= g < @ref upto_.
|
|
||||||
**/
|
|
||||||
class DMockCollector {
|
|
||||||
public:
|
|
||||||
explicit DMockCollector(GCObjectStore * gcos, Generation upto) : p_gco_store_{gcos}, upto_{upto} {}
|
|
||||||
|
|
||||||
template <typename AFacet>
|
|
||||||
obj<AFacet,DMockCollector> ref() { return obj<AFacet,DMockCollector>(this); }
|
|
||||||
|
|
||||||
Generation generation_of(Role r, const void * addr) const noexcept;
|
|
||||||
AllocInfo alloc_info(void * mem) const noexcept;
|
|
||||||
|
|
||||||
void visit_child(VisitReason reason, AGCObject * lhs_iface, void ** lhs_data);
|
|
||||||
std::byte * alloc_copy(void * src) noexcept;
|
|
||||||
|
|
||||||
private:
|
|
||||||
GCObjectStore * p_gco_store_ = nullptr;
|
|
||||||
Generation upto_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} /*namespace mm*/
|
|
||||||
} /*namespaace xo*/
|
|
||||||
|
|
||||||
/* end DMockCollector.hpp */
|
|
||||||
|
|
@ -5,8 +5,6 @@
|
||||||
|
|
||||||
#include <xo/gc/GCObjectStore.hpp>
|
#include <xo/gc/GCObjectStore.hpp>
|
||||||
#include <xo/gc/X1VerifyStats.hpp>
|
#include <xo/gc/X1VerifyStats.hpp>
|
||||||
#include "MockCollector.hpp"
|
|
||||||
|
|
||||||
#include <xo/object2/ListOps.hpp>
|
#include <xo/object2/ListOps.hpp>
|
||||||
#include <xo/object2/List.hpp>
|
#include <xo/object2/List.hpp>
|
||||||
#include <xo/object2/Integer.hpp>
|
#include <xo/object2/Integer.hpp>
|
||||||
|
|
@ -27,7 +25,6 @@ namespace ut {
|
||||||
using xo::scm::DList;
|
using xo::scm::DList;
|
||||||
using xo::scm::DInteger;
|
using xo::scm::DInteger;
|
||||||
using xo::scm::DBoolean;
|
using xo::scm::DBoolean;
|
||||||
using xo::mm::DMockCollector;
|
|
||||||
using xo::mm::GCObjectStoreConfig;
|
using xo::mm::GCObjectStoreConfig;
|
||||||
using xo::mm::GCObjectStore;
|
using xo::mm::GCObjectStore;
|
||||||
using xo::mm::X1VerifyStats;
|
using xo::mm::X1VerifyStats;
|
||||||
|
|
@ -395,7 +392,6 @@ namespace ut {
|
||||||
const GCObjectStore & gcos)
|
const GCObjectStore & gcos)
|
||||||
{
|
{
|
||||||
Generation g0{0};
|
Generation g0{0};
|
||||||
//Generation g1{1};
|
|
||||||
Generation gn{tc.n_gen_};
|
Generation gn{tc.n_gen_};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -413,6 +409,13 @@ namespace ut {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Generate two copies of a random object graph for test case @p tc.
|
||||||
|
* Store first graph in @p *p_x1_v, allocating
|
||||||
|
* entirely from @p p_gcos new-space.
|
||||||
|
* Store second graph in @p *p_x2_v, allocating
|
||||||
|
* entirely from @p p_arena2.
|
||||||
|
* Use random number generator @p_rgen
|
||||||
|
**/
|
||||||
void
|
void
|
||||||
gcos_construct_ab_object_graphs(const Testcase & tc,
|
gcos_construct_ab_object_graphs(const Testcase & tc,
|
||||||
GCObjectStore * p_gcos,
|
GCObjectStore * p_gcos,
|
||||||
|
|
@ -444,24 +447,26 @@ namespace ut {
|
||||||
// typeseq::id<DBoolean>()));
|
// typeseq::id<DBoolean>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Invoke built-in consistency verification for @p *p_gcos.
|
||||||
|
**/
|
||||||
void
|
void
|
||||||
gcos_verify_consistency(obj<AGCObjectVisitor> mock_gc_visitor,
|
gcos_verify_consistency(GCObjectStore * p_gcos)
|
||||||
GCObjectStore * p_gcos,
|
|
||||||
const X1VerifyStats & verify_stats)
|
|
||||||
{
|
{
|
||||||
// traverses stored objects, updates counters
|
// traverses stored objects, updates counters
|
||||||
// in verify_stats (= gco.p_verify_stats_, via ctor)
|
// in verify_stats (= gco.p_verify_stats_, via ctor)
|
||||||
//
|
//
|
||||||
p_gcos->verify_ok(mock_gc_visitor);
|
p_gcos->verify_ok();
|
||||||
|
|
||||||
INFO(tostr(xtag("n_gc_root", verify_stats.n_gc_root_),
|
X1VerifyStats * verify_stats = p_gcos->verify_stats();
|
||||||
xtag("n_ext", verify_stats.n_ext_),
|
|
||||||
xtag("n_from", verify_stats.n_from_),
|
|
||||||
xtag("n_to", verify_stats.n_to_),
|
|
||||||
xtag("n_fwd", verify_stats.n_fwd_),
|
|
||||||
xtag("n_no_iface", verify_stats.n_no_iface_)));
|
|
||||||
|
|
||||||
REQUIRE(verify_stats.is_ok());
|
INFO(tostr(xtag("n_gc_root", verify_stats->n_gc_root_),
|
||||||
|
xtag("n_ext", verify_stats->n_ext_),
|
||||||
|
xtag("n_from", verify_stats->n_from_),
|
||||||
|
xtag("n_to", verify_stats->n_to_),
|
||||||
|
xtag("n_fwd", verify_stats->n_fwd_),
|
||||||
|
xtag("n_no_iface", verify_stats->n_no_iface_)));
|
||||||
|
|
||||||
|
REQUIRE(verify_stats->is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -635,7 +640,7 @@ namespace ut {
|
||||||
void
|
void
|
||||||
gcos_move_roots_and_verify(const Testcase & tc,
|
gcos_move_roots_and_verify(const Testcase & tc,
|
||||||
GCObjectStore * p_gcos,
|
GCObjectStore * p_gcos,
|
||||||
obj<AGCObjectVisitor> mock_gc_visitor,
|
Generation upto,
|
||||||
const std::vector<Recd> & x1_v,
|
const std::vector<Recd> & x1_v,
|
||||||
const std::vector<Recd> & x2_v,
|
const std::vector<Recd> & x2_v,
|
||||||
bool debug_flag)
|
bool debug_flag)
|
||||||
|
|
@ -690,9 +695,9 @@ namespace ut {
|
||||||
obj<AGCObject> x1_gco = x1.gco_;
|
obj<AGCObject> x1_gco = x1.gco_;
|
||||||
|
|
||||||
// modifies x1.gco_ in place
|
// modifies x1.gco_ in place
|
||||||
auto x1p_data = p_gcos->deep_move_root(mock_gc_visitor,
|
auto x1p_data
|
||||||
x1p_iface, (void **)&(x1.gco_.data_),
|
= p_gcos->deep_move_root(x1p_iface, (void **)&(x1.gco_.data_), upto);
|
||||||
g1);
|
|
||||||
REQUIRE(x1p_data);
|
REQUIRE(x1p_data);
|
||||||
REQUIRE(x1p_data == x1.gco_.data_);
|
REQUIRE(x1p_data == x1.gco_.data_);
|
||||||
|
|
||||||
|
|
@ -713,8 +718,7 @@ namespace ut {
|
||||||
// but will fail since type isn't registered
|
// but will fail since type isn't registered
|
||||||
|
|
||||||
auto x1p_data
|
auto x1p_data
|
||||||
= p_gcos->deep_move_root(mock_gc_visitor,
|
= p_gcos->deep_move_root(x1.gco_.iface(),
|
||||||
x1.gco_.iface(),
|
|
||||||
(void **)&(x1.gco_.data_),
|
(void **)&(x1.gco_.data_),
|
||||||
g1);
|
g1);
|
||||||
|
|
||||||
|
|
@ -812,10 +816,6 @@ namespace ut {
|
||||||
Generation g1{1};
|
Generation g1{1};
|
||||||
Generation gn{tc.n_gen_};
|
Generation gn{tc.n_gen_};
|
||||||
|
|
||||||
// scaffold mock collector doing incremental collection
|
|
||||||
DMockCollector mock_gc(&gcos, g1);
|
|
||||||
auto mock_gc_visitor = mock_gc.ref<AGCObjectVisitor>();
|
|
||||||
|
|
||||||
REQUIRE(gcos.is_type_installed(typeseq::id<DList>()) == false);
|
REQUIRE(gcos.is_type_installed(typeseq::id<DList>()) == false);
|
||||||
REQUIRE(gcos.is_type_installed(typeseq::id<DBoolean>()) == false);
|
REQUIRE(gcos.is_type_installed(typeseq::id<DBoolean>()) == false);
|
||||||
|
|
||||||
|
|
@ -836,9 +836,7 @@ namespace ut {
|
||||||
|
|
||||||
log1 && log1("verify before any gcos side effects");
|
log1 && log1("verify before any gcos side effects");
|
||||||
|
|
||||||
gcos_verify_consistency(mock_gc_visitor,
|
gcos_verify_consistency(&gcos);
|
||||||
&gcos,
|
|
||||||
verify_stats);
|
|
||||||
|
|
||||||
// someday: print the graph. Need a cycle-detecting printer
|
// someday: print the graph. Need a cycle-detecting printer
|
||||||
|
|
||||||
|
|
@ -851,7 +849,7 @@ namespace ut {
|
||||||
|
|
||||||
gcos_verify_gen0_fromspace_only_allocated(tc, gcos, x1_v);
|
gcos_verify_gen0_fromspace_only_allocated(tc, gcos, x1_v);
|
||||||
|
|
||||||
gcos_move_roots_and_verify(tc, &gcos, mock_gc_visitor, x1_v, x2_v, tc.debug_flag_);
|
gcos_move_roots_and_verify(tc, &gcos, g1, x1_v, x2_v, tc.debug_flag_);
|
||||||
|
|
||||||
// Things to test:
|
// Things to test:
|
||||||
// - deep_move_interior() // used from MutationLogStore
|
// - deep_move_interior() // used from MutationLogStore
|
||||||
|
|
@ -870,7 +868,7 @@ namespace ut {
|
||||||
// traverses stored objects, updates counters
|
// traverses stored objects, updates counters
|
||||||
// in verify_stats (= gco.p_verify_stats_, via ctor)
|
// in verify_stats (= gco.p_verify_stats_, via ctor)
|
||||||
//
|
//
|
||||||
gcos.verify_ok(mock_gc_visitor);
|
gcos.verify_ok();
|
||||||
|
|
||||||
INFO(tostr(xtag("n_gc_root", verify_stats.n_gc_root_),
|
INFO(tostr(xtag("n_gc_root", verify_stats.n_gc_root_),
|
||||||
xtag("n_ext", verify_stats.n_ext_),
|
xtag("n_ext", verify_stats.n_ext_),
|
||||||
|
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
/** @file IGCObjectVisitor_DMockCollector.cpp
|
|
||||||
*
|
|
||||||
* Generated automagically from ingredients:
|
|
||||||
* 1. code generator:
|
|
||||||
* [xo-facet/codegen/genfacet]
|
|
||||||
* arguments:
|
|
||||||
* --input [idl/IGCObjectVisitor_DMockCollector.json5]
|
|
||||||
* 2. jinja2 template for abstract facet .hpp file:
|
|
||||||
* [iface_facet_any.hpp.j2]
|
|
||||||
* 3. idl for facet methods
|
|
||||||
* [idl/IGCObjectVisitor_DMockCollector.json5]
|
|
||||||
**/
|
|
||||||
|
|
||||||
#include "./IGCObjectVisitor_DMockCollector.hpp"
|
|
||||||
|
|
||||||
namespace xo {
|
|
||||||
namespace mm {
|
|
||||||
auto
|
|
||||||
IGCObjectVisitor_DMockCollector::alloc_info(const DMockCollector & self, void * addr) -> AllocInfo
|
|
||||||
{
|
|
||||||
return self.alloc_info(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
IGCObjectVisitor_DMockCollector::generation_of(const DMockCollector & self, Role r, const void * addr) noexcept -> Generation
|
|
||||||
{
|
|
||||||
return self.generation_of(r, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto
|
|
||||||
IGCObjectVisitor_DMockCollector::alloc_copy(DMockCollector & self, std::byte * src) -> void *
|
|
||||||
{
|
|
||||||
return self.alloc_copy(src);
|
|
||||||
}
|
|
||||||
auto
|
|
||||||
IGCObjectVisitor_DMockCollector::visit_child(DMockCollector & self, VisitReason reason, AGCObject * iface, void ** pp_data) noexcept -> void
|
|
||||||
{
|
|
||||||
self.visit_child(reason, iface, pp_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
} /*namespace mm*/
|
|
||||||
} /*namespace xo*/
|
|
||||||
|
|
||||||
/* end IGCObjectVisitor_DMockCollector.cpp */
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
/** @file IGCObjectVisitor_DMockCollector.hpp
|
|
||||||
*
|
|
||||||
* Generated automagically from ingredients:
|
|
||||||
* 1. code generator:
|
|
||||||
* [xo-facet/codegen/genfacet]
|
|
||||||
* arguments:
|
|
||||||
* --input [idl/IGCObjectVisitor_DMockCollector.json5]
|
|
||||||
* 2. jinja2 template for abstract facet .hpp file:
|
|
||||||
* [iface_facet_repr.hpp.j2]
|
|
||||||
* 3. idl for facet methods
|
|
||||||
* [idl/IGCObjectVisitor_DMockCollector.json5]
|
|
||||||
**/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "GCObjectVisitor.hpp"
|
|
||||||
#include "DMockCollector.hpp"
|
|
||||||
|
|
||||||
namespace xo { namespace mm { class IGCObjectVisitor_DMockCollector; } }
|
|
||||||
|
|
||||||
namespace xo {
|
|
||||||
namespace facet {
|
|
||||||
template <>
|
|
||||||
struct FacetImplementation<xo::mm::AGCObjectVisitor,
|
|
||||||
xo::mm::DMockCollector>
|
|
||||||
{
|
|
||||||
using ImplType = xo::mm::IGCObjectVisitor_Xfer
|
|
||||||
<xo::mm::DMockCollector,
|
|
||||||
xo::mm::IGCObjectVisitor_DMockCollector>;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace xo {
|
|
||||||
namespace mm {
|
|
||||||
/** @class IGCObjectVisitor_DMockCollector
|
|
||||||
**/
|
|
||||||
class IGCObjectVisitor_DMockCollector {
|
|
||||||
public:
|
|
||||||
/** @defgroup mm-gcobjectvisitor-dmockcollector-type-traits **/
|
|
||||||
///@{
|
|
||||||
using Copaque = xo::mm::AGCObjectVisitor::Copaque;
|
|
||||||
using Opaque = xo::mm::AGCObjectVisitor::Opaque;
|
|
||||||
///@}
|
|
||||||
/** @defgroup mm-gcobjectvisitor-dmockcollector-methods **/
|
|
||||||
///@{
|
|
||||||
// const methods
|
|
||||||
/** allocation metadata for gc-aware data at address @p gco.
|
|
||||||
@p gco must be the result of a call to collector's alloc() function **/
|
|
||||||
static AllocInfo alloc_info(const DMockCollector & self, void * addr);
|
|
||||||
/** generation to which pointer @p addr belongs, given role @p r;
|
|
||||||
sentinel if @p addr is not owned by collector **/
|
|
||||||
static Generation generation_of(const DMockCollector & self, Role r, const void * addr) noexcept;
|
|
||||||
|
|
||||||
// non-const methods
|
|
||||||
/** allocate copy of source object at address @p src.
|
|
||||||
Source must be owned by this collector.
|
|
||||||
Increments object age **/
|
|
||||||
static void * alloc_copy(DMockCollector & self, std::byte * src);
|
|
||||||
/** visit child of a gc-aware object. May update child in-place! **/
|
|
||||||
static void visit_child(DMockCollector & self, VisitReason reason, AGCObject * iface, void ** pp_data) noexcept;
|
|
||||||
///@}
|
|
||||||
};
|
|
||||||
|
|
||||||
} /*namespace mm*/
|
|
||||||
} /*namespace xo*/
|
|
||||||
|
|
||||||
/* end */
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
/** @file MockCollector.hpp
|
|
||||||
*
|
|
||||||
* @author Roland Conybeare, Apr 2026
|
|
||||||
**/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "DMockCollector.hpp"
|
|
||||||
#include "IGCObjectVisitor_DMockCollector.hpp"
|
|
||||||
//#include "ICollector_DMockCollector.hpp"
|
|
||||||
//#include "IAllocator_DMockCollector.hpp"
|
|
||||||
|
|
||||||
/* end MockCollector.hpp */
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include "init_gc_utest.hpp"
|
#include "init_gc_utest.hpp"
|
||||||
#include "MockCollector.hpp"
|
//#include "MockCollector.hpp"
|
||||||
#include <xo/gc/init_gc.hpp>
|
#include <xo/gc/init_gc.hpp>
|
||||||
#include <xo/facet/FacetRegistry.hpp>
|
#include <xo/facet/FacetRegistry.hpp>
|
||||||
#include <xo/indentlog/scope.hpp>
|
#include <xo/indentlog/scope.hpp>
|
||||||
|
|
@ -19,9 +19,9 @@ namespace xo {
|
||||||
{
|
{
|
||||||
scope log(XO_DEBUG(false));
|
scope log(XO_DEBUG(false));
|
||||||
|
|
||||||
FacetRegistry::register_impl<AGCObjectVisitor, DMockCollector>();
|
//FacetRegistry::register_impl<AGCObjectVisitor, DMockCollector>();
|
||||||
|
|
||||||
log && log(xtag("DMockCollector.tseq", typeseq::id<DMockCollector>()));
|
//log && log(xtag("DMockCollector.tseq", typeseq::id<DMockCollector>()));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue