xo-interpreter2 stack: + reason arg to visit_gco_children()
Helps streamline DX1Collector in xo-gc/. Want both forward and verify entry points for the same representation.
This commit is contained in:
parent
a6d23ddb83
commit
5a0314d8d6
15 changed files with 97 additions and 28 deletions
51
include/xo/alloc2/VisitReason.hpp
Normal file
51
include/xo/alloc2/VisitReason.hpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/** @file VisitReason.hpp
|
||||
*
|
||||
* @author Roland Conybeare, Apr 2026
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace xo {
|
||||
namespace mm {
|
||||
|
||||
/** @brief tag when navigating object graph
|
||||
*
|
||||
* Used with
|
||||
* @ref DX1Collector::visit_child
|
||||
* @ref GCObject::visit_gco_children
|
||||
**/
|
||||
class VisitReason {
|
||||
public:
|
||||
enum class code {
|
||||
invalid = -1,
|
||||
|
||||
/** color not needed **/
|
||||
unspecified,
|
||||
|
||||
/** Forward child pointers inplace for GC.
|
||||
* See @ref GCObjectStore::forward_inplace_aux
|
||||
**/
|
||||
forward,
|
||||
/** verify GC store consistency
|
||||
* See @ref DX1Collector::_verify_aux
|
||||
**/
|
||||
verify,
|
||||
|
||||
N,
|
||||
};
|
||||
|
||||
explicit VisitReason(code x) : code_{x} {}
|
||||
|
||||
static VisitReason unspecified() { return VisitReason(code::unspecified); }
|
||||
static VisitReason forward() { return VisitReason(code::forward); }
|
||||
static VisitReason verify() { return VisitReason(code::verify); }
|
||||
|
||||
code code() const noexcept { return code_; }
|
||||
|
||||
enum code code_;
|
||||
};
|
||||
|
||||
} /*namespace mm*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end VisitReason.hpp */
|
||||
|
|
@ -51,6 +51,8 @@ public:
|
|||
using ACollector = xo::mm::ACollector;
|
||||
/** fomo collector type **/
|
||||
using AGCObjectVisitor = xo::mm::AGCObjectVisitor;
|
||||
/** hint arg when navigating object graph **/
|
||||
using VisitReason = xo::mm::VisitReason;
|
||||
///@}
|
||||
|
||||
/** @defgroup mm-gcobject-methods **/
|
||||
|
|
@ -73,7 +75,7 @@ Arguably abusing the word 'visitor' here **/
|
|||
/** Invoke fn.visit_child(iface,data) for each child GCObject pointer.
|
||||
Context: provides address of data pointer so it can be updated in place
|
||||
when @p fn invokes garbage collector reentry point **/
|
||||
virtual void visit_gco_children(Opaque data, obj<AGCObjectVisitor> fn) const noexcept = 0;
|
||||
virtual void visit_gco_children(Opaque data, VisitReason reason, obj<AGCObjectVisitor> fn) const noexcept = 0;
|
||||
///@}
|
||||
}; /*AGCObject*/
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
// includes (via {facet_includes})
|
||||
#include <xo/alloc2/Generation.hpp>
|
||||
#include <xo/alloc2/role.hpp>
|
||||
#include <xo/alloc2/VisitReason.hpp>
|
||||
#include <xo/arena/AllocInfo.hpp>
|
||||
#include <xo/facet/obj.hpp>
|
||||
#include <xo/facet/facet_implementation.hpp>
|
||||
|
|
@ -71,7 +72,7 @@ Source must be owned by this collector.
|
|||
Increments object age **/
|
||||
virtual void * alloc_copy(Opaque data, std::byte * src) const = 0;
|
||||
/** visit child of a gc-aware object. May update child in-place! **/
|
||||
virtual void visit_child(Opaque data, AGCObject * iface, void ** pp_data) const noexcept = 0;
|
||||
virtual void visit_child(Opaque data, VisitReason reason, AGCObject * iface, void ** pp_data) const noexcept = 0;
|
||||
///@}
|
||||
}; /*AGCObjectVisitor*/
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ namespace mm {
|
|||
|
||||
// nonconst methods
|
||||
[[noreturn]] void * alloc_copy(Opaque, std::byte *) const override;
|
||||
[[noreturn]] void visit_child(Opaque, AGCObject *, void **) const noexcept override;
|
||||
[[noreturn]] void visit_child(Opaque, VisitReason, AGCObject *, void **) const noexcept override;
|
||||
|
||||
///@}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <xo/alloc2/Generation.hpp>
|
||||
#include <xo/alloc2/role.hpp>
|
||||
#include <xo/alloc2/VisitReason.hpp>
|
||||
#include <xo/arena/AllocInfo.hpp>
|
||||
|
||||
namespace xo {
|
||||
|
|
@ -56,8 +57,8 @@ namespace mm {
|
|||
void * alloc_copy(Opaque data, std::byte * src) const override {
|
||||
return I::alloc_copy(_dcast(data), src);
|
||||
}
|
||||
void visit_child(Opaque data, AGCObject * iface, void ** pp_data) const noexcept override {
|
||||
return I::visit_child(_dcast(data), iface, pp_data);
|
||||
void visit_child(Opaque data, VisitReason reason, AGCObject * iface, void ** pp_data) const noexcept override {
|
||||
return I::visit_child(_dcast(data), reason, iface, pp_data);
|
||||
}
|
||||
|
||||
///@}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ namespace mm {
|
|||
using AAllocator = AGCObject::AAllocator;
|
||||
using ACollector = AGCObject::ACollector;
|
||||
using AGCObjectVisitor = AGCObject::AGCObjectVisitor;
|
||||
using VisitReason = AGCObject::VisitReason;
|
||||
|
||||
///@}
|
||||
/** @defgroup mm-gcobject-any-methods **/
|
||||
|
|
@ -65,7 +66,7 @@ namespace mm {
|
|||
|
||||
// nonconst methods
|
||||
[[noreturn]] Opaque gco_shallow_move(Opaque, obj<AGCObjectVisitor>) const noexcept override;
|
||||
[[noreturn]] void visit_gco_children(Opaque, obj<AGCObjectVisitor>) const noexcept override;
|
||||
[[noreturn]] void visit_gco_children(Opaque, VisitReason, obj<AGCObjectVisitor>) const noexcept override;
|
||||
|
||||
///@}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ namespace mm {
|
|||
using AAllocator = AGCObject::AAllocator;
|
||||
using ACollector = AGCObject::ACollector;
|
||||
using AGCObjectVisitor = AGCObject::AGCObjectVisitor;
|
||||
using VisitReason = AGCObject::VisitReason;
|
||||
///@}
|
||||
|
||||
/** @defgroup mm-gcobject-xfer-methods **/
|
||||
|
|
@ -56,8 +57,8 @@ namespace mm {
|
|||
Opaque gco_shallow_move(Opaque data, obj<AGCObjectVisitor> gc) const noexcept override {
|
||||
return I::gco_shallow_move(_dcast(data), gc);
|
||||
}
|
||||
void visit_gco_children(Opaque data, obj<AGCObjectVisitor> fn) const noexcept override {
|
||||
return I::visit_gco_children(_dcast(data), fn);
|
||||
void visit_gco_children(Opaque data, VisitReason reason, obj<AGCObjectVisitor> fn) const noexcept override {
|
||||
return I::visit_gco_children(_dcast(data), reason, fn);
|
||||
}
|
||||
|
||||
///@}
|
||||
|
|
|
|||
|
|
@ -24,32 +24,33 @@ namespace xo {
|
|||
template <typename Object>
|
||||
template <typename DRepr>
|
||||
void
|
||||
RGCObjectVisitor<Object>::visit_child(xo::facet::obj<AGCObject,DRepr> * p_obj)
|
||||
RGCObjectVisitor<Object>::visit_child(VisitReason reason,
|
||||
xo::facet::obj<AGCObject,DRepr> * p_obj)
|
||||
{
|
||||
this->visit_child(p_obj->iface(), (void **)&(p_obj->data_));
|
||||
this->visit_child(reason, p_obj->iface(), (void **)&(p_obj->data_));
|
||||
}
|
||||
|
||||
template <typename Object>
|
||||
template <typename DRepr>
|
||||
void
|
||||
RGCObjectVisitor<Object>::visit_child(DRepr ** p_repr)
|
||||
RGCObjectVisitor<Object>::visit_child(VisitReason reason, DRepr ** p_repr)
|
||||
{
|
||||
// fetch static interface for DRepr (strip const: FacetImplementation specializations use non-const DRepr)
|
||||
auto iface = xo::facet::impl_for<AGCObject, std::remove_const_t<DRepr>>();
|
||||
|
||||
this->visit_child(&iface, (void **)p_repr);
|
||||
this->visit_child(reason, &iface, (void **)p_repr);
|
||||
}
|
||||
|
||||
template <typename Object>
|
||||
template <typename AFacet, typename DRepr>
|
||||
requires (!std::is_same_v<AFacet, AGCObject>)
|
||||
void
|
||||
RGCObjectVisitor<Object>::visit_poly_child(obj<AFacet, DRepr> * p_objs)
|
||||
RGCObjectVisitor<Object>::visit_poly_child(VisitReason reason, obj<AFacet, DRepr> * p_objs)
|
||||
{
|
||||
if (*p_objs) {
|
||||
auto e = xo::facet::FacetRegistry::instance().variant<AGCObject,AFacet>(*p_objs);
|
||||
|
||||
this->visit_child(e.iface(), (void **)&(p_objs->data_));
|
||||
this->visit_child(reason, e.iface(), (void **)&(p_objs->data_));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ public:
|
|||
using AAllocator = AGCObject::AAllocator;
|
||||
using ACollector = AGCObject::ACollector;
|
||||
using AGCObjectVisitor = AGCObject::AGCObjectVisitor;
|
||||
using VisitReason = AGCObject::VisitReason;
|
||||
///@}
|
||||
|
||||
/** @defgroup mm-gcobject-router-ctors **/
|
||||
|
|
@ -61,8 +62,8 @@ public:
|
|||
Opaque gco_shallow_move(obj<AGCObjectVisitor> gc) noexcept {
|
||||
return O::iface()->gco_shallow_move(O::data(), gc);
|
||||
}
|
||||
void visit_gco_children(obj<AGCObjectVisitor> fn) noexcept {
|
||||
return O::iface()->visit_gco_children(O::data(), fn);
|
||||
void visit_gco_children(VisitReason reason, obj<AGCObjectVisitor> fn) noexcept {
|
||||
return O::iface()->visit_gco_children(O::data(), reason, fn);
|
||||
}
|
||||
|
||||
///@}
|
||||
|
|
|
|||
|
|
@ -67,20 +67,20 @@ public:
|
|||
(for historical reasons - coul d be in RGCObject_aux.hpp?)
|
||||
**/
|
||||
template <typename DRepr>
|
||||
void visit_child(xo::facet::obj<AGCObject,DRepr> * p_obj);
|
||||
void visit_child(VisitReason reason, xo::facet::obj<AGCObject,DRepr> * p_obj);
|
||||
|
||||
/** visit typed child data pointer in place.
|
||||
Defined in RGCObject.hpp to avoid #include cycle
|
||||
**/
|
||||
template <typename DRepr>
|
||||
void visit_child(DRepr ** pp_data);
|
||||
void visit_child(VisitReason reason, DRepr ** pp_data);
|
||||
|
||||
/** visit faceted object pointer stored using some facet
|
||||
other than AGCObject
|
||||
**/
|
||||
template <typename AFacet, typename DRepr>
|
||||
requires (!std::is_same_v<AFacet, AGCObject>)
|
||||
void visit_poly_child(obj<AFacet,DRepr> * p_pivot);
|
||||
void visit_poly_child(VisitReason reason, obj<AFacet,DRepr> * p_pivot);
|
||||
|
||||
|
||||
// builtin methods
|
||||
|
|
@ -99,8 +99,8 @@ public:
|
|||
void * alloc_copy(std::byte * src) {
|
||||
return O::iface()->alloc_copy(O::data(), src);
|
||||
}
|
||||
void visit_child(AGCObject * iface, void ** pp_data) noexcept {
|
||||
return O::iface()->visit_child(O::data(), iface, pp_data);
|
||||
void visit_child(VisitReason reason, AGCObject * iface, void ** pp_data) noexcept {
|
||||
return O::iface()->visit_child(O::data(), reason, iface, pp_data);
|
||||
}
|
||||
|
||||
///@}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ namespace xo {
|
|||
namespace mm {
|
||||
static constexpr uint32_t c_n_role = 2;
|
||||
|
||||
/** @brief identify GC half-spaces
|
||||
**/
|
||||
class Role {
|
||||
public:
|
||||
using value_type = std::uint32_t;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue