git subrepo clone git@github.com:Rconybea/xo-alloc.git xo-alloc
subrepo: subdir: "xo-alloc" merged: "fc656313" upstream: origin: "git@github.com:Rconybea/xo-alloc.git" branch: "main" commit: "fc656313" git-subrepo: version: "0.4.9" origin: "???" commit: "???"
This commit is contained in:
parent
d16545d815
commit
2c8faf6e43
49 changed files with 7196 additions and 0 deletions
230
xo-alloc/src/alloc/Object.cpp
Normal file
230
xo-alloc/src/alloc/Object.cpp
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
/* Object.cpp
|
||||
*
|
||||
* author: Roalnd Conybeare, Jul 2025
|
||||
*/
|
||||
|
||||
#include "Object.hpp"
|
||||
#include "GC.hpp"
|
||||
#include "Forwarding1.hpp"
|
||||
|
||||
using xo::obj::Forwarding1;
|
||||
|
||||
void *
|
||||
operator new (std::size_t z, const xo::Cpof & cpof)
|
||||
{
|
||||
using xo::gc::GC;
|
||||
|
||||
//GC * gc = reinterpret_cast<GC *>(cpof.mm_);
|
||||
|
||||
return cpof.mm_->alloc_gc_copy(z, cpof.src_);
|
||||
}
|
||||
|
||||
namespace xo {
|
||||
using xo::reflect::TaggedPtr;
|
||||
|
||||
gc::IAlloc *
|
||||
Object::mm = nullptr;
|
||||
|
||||
TaggedPtr
|
||||
Object::self_tp() const
|
||||
{
|
||||
assert(false);
|
||||
return TaggedPtr::universal_null();
|
||||
}
|
||||
|
||||
void
|
||||
Object::display(std::ostream & os) const
|
||||
{
|
||||
os << "<Object>";
|
||||
}
|
||||
|
||||
IObject *
|
||||
Object::_forward(IObject * src,
|
||||
gc::IAlloc * gc)
|
||||
{
|
||||
scope log(XO_DEBUG(gc->debug_flag()), xtag("src", src));
|
||||
|
||||
if (!src)
|
||||
return src;
|
||||
|
||||
if (src->_is_forwarded()) {
|
||||
log && log("already forwarded", xtag("dest", src->_offset_destination(src)));
|
||||
return src->_offset_destination(src);
|
||||
}
|
||||
|
||||
if (gc->check_move(src)) {
|
||||
log && log("needs forwarding");
|
||||
Object::_shallow_move(src, gc);
|
||||
|
||||
/* *src is now a forwarding pointer to a copy in to-space */
|
||||
return src->_offset_destination(src);
|
||||
} else {
|
||||
log && log("already tenured + incr collection");
|
||||
/* don't move tenured objects during incremental collection */
|
||||
return src;
|
||||
}
|
||||
}
|
||||
|
||||
IObject *
|
||||
Object::_deep_move(IObject * from_src, gc::GC * gc, gc::ObjectStatistics * /*stats*/)
|
||||
{
|
||||
scope log(XO_DEBUG(gc->config().debug_flag_));
|
||||
|
||||
using gc::generation;
|
||||
|
||||
if (!from_src)
|
||||
return nullptr;
|
||||
|
||||
IObject * retval = from_src->_destination();
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (!gc->check_move(from_src)) {
|
||||
/** incremental collection does not move already-tenured objects **/
|
||||
return from_src;
|
||||
}
|
||||
|
||||
/**
|
||||
* To-space:
|
||||
*
|
||||
* to_lo = start of to-space
|
||||
* w,W = white objects. An object x is white if x
|
||||
* + all immediate children of x are in to-space
|
||||
* (also implies this GC cycle put it there)
|
||||
* g,G = grey objects. An object x is gray if it's in to-space,
|
||||
* but possibly has >0 black children
|
||||
* _ = free to-space memory
|
||||
* N = nursery space
|
||||
* T = tenured space
|
||||
*
|
||||
* wwwwwwwwwwwwwwwwwwwggggggggggggggggggggg_________________...
|
||||
* ^ ^ ^
|
||||
* to_lo grey_lo(N) free_ptr(N)
|
||||
*
|
||||
* After moving children of one object, advancing {nursery_grey_lo, nursery_free_ptr}
|
||||
*
|
||||
* wwwwwwwwwwwwwwwwwwwWWWWgggggggggggggggggGGGGGGGGGGG______...
|
||||
* ^ ^ ^
|
||||
* to_lo grey_lo(N) free_ptr(N)
|
||||
*
|
||||
* Invariant:
|
||||
*
|
||||
* objects in [to_lo, gray_lo) are white.
|
||||
* all gray objects are in [gray_lo, free_ptr)
|
||||
* memory starting at free_ptr is free.
|
||||
*
|
||||
* deep_move terminates when gray_lo catches up to free_ptr
|
||||
*
|
||||
* Above is simplified. Complication is that GC (including incremental) may
|
||||
* promote objects from nursery (N) to tenured (T)
|
||||
*
|
||||
* So more accurate before/after picture
|
||||
*
|
||||
* N wwwwwwwwwwwwwwwwwwwggggggggggggggggggggg_________________...
|
||||
* ^ ^ ^
|
||||
* to_lo(N) grey_lo(N) free_ptr(N)
|
||||
*
|
||||
* T wwwwwwwwwwwwwwgggggggggggg_______________________________...
|
||||
* ^ ^ ^
|
||||
* to_lo(T) grey_lo(T) free_ptr(N)
|
||||
*
|
||||
* After moving children of one object, advancing {nursery_grey_lo, nursery_free_ptr}
|
||||
*
|
||||
* N wwwwwwwwwwwwwwwwwwwWWWWgggggggggggggggggGGGGGGGGGGG_____...
|
||||
* ^ ^ ^
|
||||
* to_lo(N) grey_lo(N) free_ptr(N)
|
||||
*
|
||||
* T wwwwwwwwwwwwwwggggggggggggGGGGG_________________________...
|
||||
* ^ ^ ^
|
||||
* to_lo(T) grey_lo(T) free_ptr(T)
|
||||
*
|
||||
* deep_move terminates when both:
|
||||
* - gray_lo(N) catches up with free_ptr(N)
|
||||
* - gray_lo(T) catches up with free_ptr(T)
|
||||
*
|
||||
**/
|
||||
|
||||
std::array<std::byte *, gen2int(generation::N)> gray_lo_v
|
||||
= { gc->free_ptr(generation::nursery), gc->free_ptr(generation::tenured) };
|
||||
|
||||
IObject * to_src = Object::_shallow_move(from_src, gc);
|
||||
|
||||
std::size_t fixup_work = 0;
|
||||
do {
|
||||
fixup_work = 0;
|
||||
|
||||
auto fixup_generation = [gc, &log, &gray_lo_v](generation gen) {
|
||||
std::size_t work = 0;
|
||||
while(gray_lo_v[gen2int(gen)] < gc->free_ptr(gen)) {
|
||||
Object * x = reinterpret_cast<Object *>(gray_lo_v[gen2int(gen)]);
|
||||
|
||||
// update per-class stats here
|
||||
|
||||
log && log("fwd children", xtag("x", x));
|
||||
|
||||
std::size_t xz = x->_forward_children(gc);
|
||||
|
||||
// must pad xz to multiple of word size,
|
||||
// to match behavior of LinearAlloc::alloc()
|
||||
//
|
||||
xz += gc::IAlloc::alloc_padding(xz);
|
||||
|
||||
gray_lo_v[gen2int(gen)] += xz;
|
||||
++work;
|
||||
}
|
||||
|
||||
return work;
|
||||
};
|
||||
|
||||
fixup_work += fixup_generation(generation::nursery);
|
||||
fixup_work += fixup_generation(generation::tenured);
|
||||
} while (fixup_work > 0);
|
||||
|
||||
return to_src;
|
||||
} /*deep_move*/
|
||||
|
||||
IObject *
|
||||
Object::_shallow_move(IObject * src, gc::IAlloc * gc)
|
||||
{
|
||||
/* filter for source objects that are owned by GC.
|
||||
* Care required though -- during GC from/to spaces have been swapped already
|
||||
*/
|
||||
if (gc->check_owned(src))
|
||||
{
|
||||
IObject * dest = src->_shallow_copy(gc);
|
||||
|
||||
if (dest != src)
|
||||
src->_forward_to(dest);
|
||||
|
||||
return dest;
|
||||
} else {
|
||||
return src;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Object::_forward_to(IObject * dest)
|
||||
{
|
||||
char * mem = reinterpret_cast<char *>(this);
|
||||
|
||||
Forwarding1 * fwd = new (mem) Forwarding1(dest);
|
||||
|
||||
(void)fwd;
|
||||
}
|
||||
|
||||
std::ostream &
|
||||
operator<< (std::ostream & os, gp<Object> x)
|
||||
{
|
||||
if (x.ptr()) {
|
||||
x->display(os);
|
||||
} else {
|
||||
os << "<nullptr>";
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end Object.cpp*/
|
||||
Loading…
Add table
Add a link
Reference in a new issue