xo-gc: refactor: move forward_inplace_aux() to GCObjectStore
This commit is contained in:
parent
1f0aa5f6a6
commit
99593c4d72
4 changed files with 217 additions and 8 deletions
|
|
@ -392,7 +392,8 @@ namespace xo {
|
|||
/** Evacuate object at @p *lhs_data to to-space.
|
||||
* Replace original with forwarding pointer to new location
|
||||
**/
|
||||
void _forward_inplace_aux(AGCObject * lhs_iface, void ** lhs_data);
|
||||
void _forward_inplace_aux(AGCObject * lhs_iface, void ** lhs_data, Generation upto);
|
||||
|
||||
/** Verify that pointer {@p iface, @p data} is valid:
|
||||
* destination either in to-space, or somewhere outside this collector
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -135,6 +135,18 @@ namespace xo {
|
|||
void * gco_data,
|
||||
Generation upto) const noexcept;
|
||||
|
||||
/** Evacuate object at @p *lhs_data to to-space, during collection phase
|
||||
* acting on generations g in [0 ,.., upto).
|
||||
* Need @p gc to pass to invoke AGCObject methods shallow_copy() and
|
||||
* forward_children()
|
||||
*
|
||||
* Replace original with forwarding pointer to new location
|
||||
**/
|
||||
void _forward_inplace_aux(DX1Collector * gc,
|
||||
AGCObject * lhs_iface,
|
||||
void ** lhs_data,
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -1094,9 +1094,11 @@ namespace xo {
|
|||
DX1Collector::forward_inplace(AGCObject * lhs_iface,
|
||||
void ** lhs_data)
|
||||
{
|
||||
Generation upto = runstate_.gc_upto();
|
||||
|
||||
if (runstate_.is_running()) {
|
||||
// called during collection phase
|
||||
this->_forward_inplace_aux(lhs_iface, lhs_data);
|
||||
this->_forward_inplace_aux(lhs_iface, lhs_data, upto);
|
||||
} else if (runstate_.is_verify()) {
|
||||
// called during verify_ok
|
||||
this->_verify_aux(lhs_iface, *lhs_data);
|
||||
|
|
@ -1108,8 +1110,14 @@ namespace xo {
|
|||
|
||||
void
|
||||
DX1Collector::_forward_inplace_aux(AGCObject * lhs_iface,
|
||||
void ** lhs_data)
|
||||
void ** lhs_data,
|
||||
Generation upto)
|
||||
{
|
||||
// upto == runstate_.gc_upto()
|
||||
|
||||
gco_store_._forward_inplace_aux(this, lhs_iface, lhs_data, upto);
|
||||
|
||||
#ifdef MARKED
|
||||
scope log(XO_DEBUG(config_.debug_flag_),
|
||||
xtag("lhs_data", lhs_data),
|
||||
xtag("*lhs_data", lhs_data ? *lhs_data : nullptr));
|
||||
|
|
@ -1137,7 +1145,7 @@ namespace xo {
|
|||
if (!object_data) {
|
||||
/* trivial to forward nullptr */
|
||||
return;
|
||||
} else if (!this->contains(role::from_space(), object_data)) {
|
||||
} else if (!gco_store_.contains(role::from_space(), object_data)) {
|
||||
/* *lhs_data either:
|
||||
* 1. already in to-space
|
||||
* 2. not in GC-allocated space at all
|
||||
|
|
@ -1162,7 +1170,7 @@ namespace xo {
|
|||
* allocated object data.
|
||||
* Only using this to get alloc header
|
||||
**/
|
||||
DArena * some_arena = this->from_space(Generation(0));
|
||||
DArena * some_arena = gco_store_.from_space(Generation(0));
|
||||
|
||||
DArena::header_type * p_header
|
||||
= some_arena->obj2hdr(object_data);
|
||||
|
|
@ -1192,7 +1200,7 @@ namespace xo {
|
|||
*/
|
||||
assert(alloc_z >= sizeof(uintptr_t));
|
||||
|
||||
if (this->is_forwarding_header(alloc_hdr)) {
|
||||
if (gco_store_.is_forwarding_header(alloc_hdr)) {
|
||||
/* *lhs_data already refers to a forwarding pointer */
|
||||
|
||||
/*
|
||||
|
|
@ -1245,7 +1253,7 @@ namespace xo {
|
|||
xtag("tname", TypeRegistry::id2name(typeseq(info.tseq()))),
|
||||
xtag("age", info.age()), xtag("size", info.size()));
|
||||
}
|
||||
} else if (this->check_move_policy(alloc_hdr, object_data)) {
|
||||
} else if (gco_store_._check_move_policy(alloc_hdr, object_data, upto)) {
|
||||
/* copy object *lhs + replace with forwarding pointer */
|
||||
|
||||
log && log("forward object now");
|
||||
|
|
@ -1289,7 +1297,8 @@ namespace xo {
|
|||
* e.g. incremental collection + object is tenured
|
||||
*/
|
||||
}
|
||||
} /*_forward_inplace*/
|
||||
#endif
|
||||
} /*_forward_inplace_aux*/
|
||||
|
||||
void
|
||||
DX1Collector::_verify_aux(AGCObject * iface, void * data)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
**/
|
||||
|
||||
#include "GCObjectStore.hpp"
|
||||
#include "X1Collector.hpp"
|
||||
|
||||
#include <xo/object2/Dictionary.hpp>
|
||||
#include <xo/object2/Array.hpp>
|
||||
|
|
@ -371,6 +372,192 @@ namespace xo {
|
|||
return (g < upto);
|
||||
}
|
||||
|
||||
void
|
||||
GCObjectStore::_forward_inplace_aux(DX1Collector * gc,
|
||||
AGCObject * lhs_iface,
|
||||
void ** lhs_data,
|
||||
Generation upto)
|
||||
{
|
||||
// upto == runstate_.gc_upto()
|
||||
|
||||
scope log(XO_DEBUG(config_.debug_flag_),
|
||||
xtag("lhs_data", lhs_data),
|
||||
xtag("*lhs_data", lhs_data ? *lhs_data : nullptr));
|
||||
|
||||
/* coordinates with DX1Collector::_deep_move() */
|
||||
|
||||
/*
|
||||
* lhs obj<AGCObject>
|
||||
* | +---------+ +---+-+----+
|
||||
* \--->| .iface | | T |G|size| header
|
||||
* +---------+ object_data +---+-+----+
|
||||
* | .data x----------------->| alloc |
|
||||
* +---------+ | data |
|
||||
* | for |
|
||||
* | instance |
|
||||
* | ... |
|
||||
* +----------+
|
||||
*/
|
||||
|
||||
void * object_data = (std::byte *)*lhs_data;
|
||||
|
||||
if (!object_data) {
|
||||
/* trivial to forward nullptr */
|
||||
return;
|
||||
} else if (!this->contains(role::from_space(), object_data)) {
|
||||
/* *lhs_data either:
|
||||
* 1. already in to-space
|
||||
* 2. not in GC-allocated space at all
|
||||
* (small number of niche examples of this)
|
||||
*
|
||||
* It's important we recognize case (2) up front.
|
||||
* Since not allocated from GC, they don't have
|
||||
* an alloc-header.
|
||||
*/
|
||||
log && log("disposition: not in from-space. Don't forward, but check children");
|
||||
|
||||
obj<AGCObject> gco(lhs_iface, object_data);
|
||||
gco.forward_children(gc->ref<ACollector>());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
log && log("disposition: in from-space");
|
||||
|
||||
/** NOTE: for form's sake:
|
||||
* lookup actual arena that
|
||||
* allocated object data.
|
||||
* Only using this to get alloc header
|
||||
**/
|
||||
DArena * some_arena = this->from_space(Generation(0));
|
||||
|
||||
DArena::header_type * p_header
|
||||
= some_arena->obj2hdr(object_data);
|
||||
|
||||
DArena::header_type alloc_hdr = *p_header;
|
||||
|
||||
/* recover allocation size */
|
||||
std::size_t alloc_z = some_arena->config_.header_.size_with_padding(alloc_hdr);
|
||||
|
||||
if (log) {
|
||||
log(xtag("some_arena.lo", some_arena->lo_),
|
||||
xtag("p_header", p_header),
|
||||
xtag("alloc_z", alloc_z));
|
||||
|
||||
AllocInfo info = this->alloc_info((std::byte *)object_data);
|
||||
log(xtag("tseq", info.tseq()),
|
||||
xtag("tname", TypeRegistry::id2name(typeseq(info.tseq()))),
|
||||
xtag("is_forwarding_tseq", info.is_forwarding_tseq()),
|
||||
xtag("age", info.age()),
|
||||
xtag("size", info.size()));
|
||||
}
|
||||
|
||||
/* need to be able to fit forwarding pointer
|
||||
* in place of forwarded object.
|
||||
*
|
||||
* This is guaranteed anyway, by alignment rules
|
||||
*/
|
||||
assert(alloc_z >= sizeof(uintptr_t));
|
||||
|
||||
if (this->is_forwarding_header(alloc_hdr)) {
|
||||
/* *lhs_data already refers to a forwarding pointer */
|
||||
|
||||
/*
|
||||
* lhs obj<AGCObject> (from-space)
|
||||
* | +---------+ +---+-+----+
|
||||
* \--->| .iface | |FWD|G|size| alloc_hdr
|
||||
* +---------+ object_data +---+-+----+
|
||||
* | .data x----------------->| x--------\
|
||||
* +---------+ | | | dest
|
||||
* | | |
|
||||
* +----------+ |
|
||||
* |
|
||||
* (to-space) |
|
||||
* +---+-+----+ |
|
||||
* |TSQ|G|size| |
|
||||
* +---+-+----+ |
|
||||
* | | <-/
|
||||
* | |
|
||||
* | |
|
||||
* +----------+
|
||||
*/
|
||||
void * dest = *(void**)object_data;
|
||||
|
||||
*lhs_data = dest;
|
||||
/*
|
||||
* lhs obj<AGCObject>
|
||||
* | +---------+
|
||||
* \--->| .iface |
|
||||
* +---------+
|
||||
* | .data x------------\
|
||||
* +---------+ |
|
||||
* | dest
|
||||
* |
|
||||
* |
|
||||
* | (to-space)
|
||||
* | +---+-+----+
|
||||
* | |TSQ|G|size|
|
||||
* | +---+-+----+
|
||||
* \---> | |
|
||||
* | |
|
||||
* | |
|
||||
* +----------+
|
||||
*/
|
||||
|
||||
if (log) {
|
||||
log("lhs_data already forwarded", xtag("dest", dest));
|
||||
|
||||
AllocInfo info = this->alloc_info((std::byte *)dest);
|
||||
log(xtag("tseq", info.tseq()),
|
||||
xtag("tname", TypeRegistry::id2name(typeseq(info.tseq()))),
|
||||
xtag("age", info.age()), xtag("size", info.size()));
|
||||
}
|
||||
} else if (this->_check_move_policy(alloc_hdr, object_data, upto)) {
|
||||
/* copy object *lhs + replace with forwarding pointer */
|
||||
|
||||
log && log("forward object now");
|
||||
|
||||
/*
|
||||
* lhs obj<AGCObject> (from-space)
|
||||
* | +---------+ +---+-+----+
|
||||
* \--->| .iface | |TSQ|G|size| alloc_hdr
|
||||
* +---------+ object_data +---+-+----+
|
||||
* | .data x----------------> | |
|
||||
* +---------+ | |
|
||||
* | |
|
||||
* +----------+
|
||||
*/
|
||||
|
||||
*lhs_data = this->_shallow_move(gc->ref<AAllocator>(), lhs_iface, *lhs_data);
|
||||
|
||||
/*
|
||||
* lhs obj<AGCObject> (from-space)
|
||||
* | +---------+ +---+-+----+
|
||||
* \--->| .iface | |FWD|G|SIZE|
|
||||
* +---------+ +---+-+----+
|
||||
* | .data x------------\ | x--------\
|
||||
* +---------+ | | | |
|
||||
* | | | |
|
||||
* dest | +----------+ |
|
||||
* | |
|
||||
* | (to-space) |
|
||||
* | +---+-+----+ |
|
||||
* | |TSQ|G|size| |
|
||||
* | +---+-+----+ |
|
||||
* \---> | | <-/
|
||||
* | |
|
||||
* | |
|
||||
* +----------+
|
||||
*/
|
||||
} else {
|
||||
log && log("object not eligible/required to forward");
|
||||
|
||||
/* object doesn't need to move.
|
||||
* e.g. incremental collection + object is tenured
|
||||
*/
|
||||
}
|
||||
} /*_forward_inplace_aux*/
|
||||
|
||||
void
|
||||
GCObjectStore::swap_roles(Generation upto) noexcept
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue