xo-gc: + ACollector.assign_member()
This commit is contained in:
parent
68999ace48
commit
f056faa0db
9 changed files with 66 additions and 3 deletions
|
|
@ -8,7 +8,6 @@
|
|||
#include <xo/arena/MemorySizeInfo.hpp>
|
||||
#include <xo/arena/AllocError.hpp>
|
||||
#include "AllocInfo.hpp"
|
||||
//#include "AllocIterator.hpp"
|
||||
#include "AllocRange.hpp"
|
||||
#include "typeseq.hpp"
|
||||
#include <xo/facet/obj.hpp>
|
||||
|
|
|
|||
|
|
@ -76,6 +76,15 @@ namespace xo {
|
|||
**/
|
||||
virtual void request_gc(Opaque d, generation upto) = 0;
|
||||
|
||||
/** Assign pointer @p p_lhs to destination @p rhs, within parent allocation @p parent
|
||||
*
|
||||
* Require: gc not in progress
|
||||
**/
|
||||
virtual void assign_member(Opaque d,
|
||||
void * parent,
|
||||
obj<AGCObject> * p_lhs,
|
||||
obj<AGCObject> & rhs) = 0;
|
||||
|
||||
/** evacuate @p *lhs, that refers to state with interface @p lhs_iface,
|
||||
* to collector @p d's to-space. Replace *lhs_data with forwarding pointer
|
||||
*
|
||||
|
|
|
|||
|
|
@ -53,6 +53,11 @@ public:
|
|||
/** @defgroup mm-gcobject-methods **/
|
||||
///@{
|
||||
// const methods
|
||||
/** An uninitialized AGCObject instance will have zero vtable pointer (per {linux,osx} abi).
|
||||
* Use case for this is narrow. We go to some lengths to avoid null vtable pointers. For example
|
||||
* obj<AFacet> will have non-null vtable (via IFacet_Any) with all methods terminating.
|
||||
**/
|
||||
bool _has_null_vptr() const noexcept { return *reinterpret_cast<const void * const *>(this) == nullptr; }
|
||||
/** RTTI: unique id# for actual runtime data representation **/
|
||||
virtual typeseq _typeseq() const noexcept = 0;
|
||||
/** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ namespace xo {
|
|||
[[noreturn]] void add_gc_root_poly(Opaque, obj<AGCObject> *) override { _fatal(); }
|
||||
[[noreturn]] void remove_gc_root_poly(Opaque, obj<AGCObject> *) override { _fatal(); }
|
||||
[[noreturn]] void request_gc(Opaque, generation) override { _fatal(); }
|
||||
[[noreturn]] void assign_member(Opaque, void *,
|
||||
obj<AGCObject> *, obj<AGCObject> &) override { _fatal(); }
|
||||
[[noreturn]] void forward_inplace(Opaque, AGCObject *, void **) override { _fatal(); }
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ namespace xo {
|
|||
void request_gc(Opaque d, generation upto) override {
|
||||
I::request_gc(_dcast(d), upto);
|
||||
}
|
||||
void assign_member(Opaque d, void * parent,
|
||||
obj<AGCObject> * p_lhs, obj<AGCObject> & rhs) override {
|
||||
I::assign_member(_dcast(d), parent, p_lhs, rhs);
|
||||
}
|
||||
void forward_inplace(Opaque d,
|
||||
AGCObject * lhs_iface, void ** lhs_data) override {
|
||||
I::forward_inplace(_dcast(d), lhs_iface, lhs_data);
|
||||
|
|
|
|||
|
|
@ -51,6 +51,11 @@ namespace xo {
|
|||
void add_gc_root_poly(obj<AGCObject> * p_root) { O::iface()->add_gc_root_poly(O::data(), p_root); }
|
||||
void remove_gc_root_poly(obj<AGCObject> * p_root) { O::iface()->remove_gc_root_poly(O::data(), p_root); }
|
||||
void request_gc(generation g) { O::iface()->request_gc(O::data(), g); }
|
||||
|
||||
void assign_member(void * parent,
|
||||
obj<AGCObject> * p_lhs,
|
||||
obj<AGCObject> & rhs) { O::iface()->assign_member(O::data(), parent, p_lhs, rhs); }
|
||||
|
||||
void forward_inplace(AGCObject * lhs_iface, void ** lhs_data) { O::iface()->forward_inplace(O::data(), lhs_iface, lhs_data); }
|
||||
|
||||
/** add root @p p_root **/
|
||||
|
|
|
|||
|
|
@ -43,9 +43,27 @@ namespace xo {
|
|||
void
|
||||
RCollector<Object>::forward_pivot_inplace(obj<AFacet, DRepr> * p_objs)
|
||||
{
|
||||
auto e = xo::facet::FacetRegistry::instance().variant<AGCObject,AFacet>(*p_objs);
|
||||
this->forward_inplace(e.iface(), (void **)&(p_objs->data_));
|
||||
if (*p_objs) {
|
||||
auto e = xo::facet::FacetRegistry::instance().variant<AGCObject,AFacet>(*p_objs);
|
||||
this->forward_inplace(e.iface(), (void **)&(p_objs->data_));
|
||||
}
|
||||
}
|
||||
|
||||
/** gc-aware assignment; engage special book-keeping for cross-gen pointers **/
|
||||
inline void mm_do_assign(obj<ACollector> & gc,
|
||||
void * parent,
|
||||
obj<AGCObject> * p_lhs,
|
||||
obj<AGCObject> & rhs)
|
||||
{
|
||||
if (gc.data()) {
|
||||
gc.assign_member(parent, p_lhs, rhs);
|
||||
} else {
|
||||
// assume null collector downstream from allocator that does not provide collection.
|
||||
// In that no additional assignment work.
|
||||
|
||||
*p_lhs = rhs;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ namespace xo {
|
|||
explicit constexpr generation(value_type x) : value_{x} {}
|
||||
|
||||
static generation nursery() { return generation{0}; }
|
||||
static generation sentinel() { return generation(c_max_generation); }
|
||||
|
||||
bool is_sentinel() const noexcept { return value_ == c_max_generation; }
|
||||
|
||||
constexpr operator value_type() const { return value_; }
|
||||
|
||||
|
|
@ -30,6 +33,19 @@ namespace xo {
|
|||
|
||||
std::uint32_t value_ = 0;
|
||||
};
|
||||
|
||||
inline bool operator==(generation lhs, generation rhs) {
|
||||
return lhs.value_ == rhs.value_;
|
||||
}
|
||||
|
||||
inline bool operator<(generation lhs, generation rhs) {
|
||||
return lhs.value_ < rhs.value_;
|
||||
}
|
||||
|
||||
inline bool operator>(generation lhs, generation rhs) {
|
||||
return lhs.value_ > rhs.value_;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,11 @@ public:
|
|||
/** @defgroup mm-resourcevisitor-methods **/
|
||||
///@{
|
||||
// const methods
|
||||
/** An uninitialized AResourceVisitor instance will have zero vtable pointer (per {linux,osx} abi).
|
||||
* Use case for this is narrow. We go to some lengths to avoid null vtable pointers. For example
|
||||
* obj<AFacet> will have non-null vtable (via IFacet_Any) with all methods terminating.
|
||||
**/
|
||||
bool _has_null_vptr() const noexcept { return *reinterpret_cast<const void * const *>(this) == nullptr; }
|
||||
/** RTTI: unique id# for actual runtime data representation **/
|
||||
virtual typeseq _typeseq() const noexcept = 0;
|
||||
/** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue