xo-interpreter: refactor for explicit gc::GC* dep
This commit is contained in:
parent
760bb556b2
commit
2f2cb735f3
10 changed files with 89 additions and 32 deletions
|
|
@ -175,6 +175,8 @@ namespace xo {
|
||||||
virtual void checkpoint() final override;
|
virtual void checkpoint() final override;
|
||||||
virtual std::byte * alloc(std::size_t z) final override;
|
virtual std::byte * alloc(std::size_t z) final override;
|
||||||
|
|
||||||
|
virtual bool check_owned(Object * src) const final override;
|
||||||
|
|
||||||
ArenaAlloc & operator=(const ArenaAlloc &) = delete;
|
ArenaAlloc & operator=(const ArenaAlloc &) = delete;
|
||||||
ArenaAlloc & operator=(ArenaAlloc &&) = delete;
|
ArenaAlloc & operator=(ArenaAlloc &&) = delete;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ namespace xo {
|
||||||
/** required by Object i/face, but never called on Forwarding1 **/
|
/** required by Object i/face, but never called on Forwarding1 **/
|
||||||
virtual Object * _shallow_copy(gc::IAlloc * mm) const final override;
|
virtual Object * _shallow_copy(gc::IAlloc * mm) const final override;
|
||||||
/** required by Object i/face, but never called on Forwarding1 **/
|
/** required by Object i/face, but never called on Forwarding1 **/
|
||||||
virtual std::size_t _forward_children() final override;
|
virtual std::size_t _forward_children(gc::GC * mm) final override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** the object that used to be located at this address (i.e. @c this)
|
/** the object that used to be located at this address (i.e. @c this)
|
||||||
|
|
|
||||||
|
|
@ -308,6 +308,15 @@ namespace xo {
|
||||||
**/
|
**/
|
||||||
virtual void assign_member(Object * parent, Object ** lhs, Object* rhs) final override;
|
virtual void assign_member(Object * parent, Object ** lhs, Object* rhs) final override;
|
||||||
|
|
||||||
|
/** during GC check for source objects owned by GC.
|
||||||
|
* See Object::_shallow_move.
|
||||||
|
**/
|
||||||
|
virtual bool check_owned(Object * src) const final override;
|
||||||
|
/** queries during GC to determine if object at address @p src should move:
|
||||||
|
* - full GC -> always
|
||||||
|
* - incr GC -> if not tenured
|
||||||
|
**/
|
||||||
|
virtual bool check_move(Object * src) const final override;
|
||||||
virtual std::byte * alloc(std::size_t z) final override;
|
virtual std::byte * alloc(std::size_t z) final override;
|
||||||
virtual std::byte * alloc_gc_copy(std::size_t z, const void * src) final override;
|
virtual std::byte * alloc_gc_copy(std::size_t z, const void * src) final override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,12 @@ namespace xo {
|
||||||
|
|
||||||
namespace gc {
|
namespace gc {
|
||||||
/** @class IAllocator
|
/** @class IAllocator
|
||||||
* @brief memory allocation interface with limited garbaga collector support
|
* @brief memory allocation interface with limited garbage collector support
|
||||||
|
*
|
||||||
|
* Garbage collector support methods:
|
||||||
|
* - checkpoint()
|
||||||
|
* - assign_member()
|
||||||
|
* - alloc_gc_copy()
|
||||||
**/
|
**/
|
||||||
class IAlloc {
|
class IAlloc {
|
||||||
public:
|
public:
|
||||||
|
|
@ -56,14 +61,28 @@ namespace xo {
|
||||||
/** @return true iff debug logging enabled **/
|
/** @return true iff debug logging enabled **/
|
||||||
virtual bool debug_flag() const = 0;
|
virtual bool debug_flag() const = 0;
|
||||||
|
|
||||||
/** reset allocator to empty state. **/
|
|
||||||
virtual void clear() = 0;
|
|
||||||
/** remember allocator state. All currently-allocated addresses xo
|
/** remember allocator state. All currently-allocated addresses xo
|
||||||
* will satisfy is_before_checkpoint(x). Subsequent allocations x
|
* will satisfy is_before_checkpoint(x). Subsequent allocations x
|
||||||
* will fail is_before_checkpoint(x), until checkpoint superseded
|
* will fail is_before_checkpoint(x), until checkpoint superseded
|
||||||
* by @ref clear or another call to @ref checkpoint
|
* by @ref clear or another call to @ref checkpoint
|
||||||
**/
|
**/
|
||||||
virtual void checkpoint() = 0;
|
virtual void checkpoint() = 0;
|
||||||
|
|
||||||
|
/** allocate @p z bytes of memory. returns pointer to first address **/
|
||||||
|
virtual std::byte * alloc(std::size_t z) = 0;
|
||||||
|
/** reset allocator to empty state. **/
|
||||||
|
virtual void clear() = 0;
|
||||||
|
|
||||||
|
// ----- GC-specific methods -----
|
||||||
|
|
||||||
|
/** true iff this allocator owns object at address @p src.
|
||||||
|
* Use to assist Object::_shallow_move
|
||||||
|
**/
|
||||||
|
virtual bool check_owned(Object * src) const;
|
||||||
|
/** true iff object at address @p src must move as part of
|
||||||
|
* in-progress collection phase
|
||||||
|
**/
|
||||||
|
virtual bool check_move(Object * src) const;
|
||||||
/** perform assignment
|
/** perform assignment
|
||||||
* @code
|
* @code
|
||||||
* *lhs = rhs
|
* *lhs = rhs
|
||||||
|
|
@ -72,8 +91,6 @@ namespace xo {
|
||||||
* Default implementation just does the assignment.
|
* Default implementation just does the assignment.
|
||||||
**/
|
**/
|
||||||
virtual void assign_member(Object * parent, Object ** lhs, Object * rhs);
|
virtual void assign_member(Object * parent, Object ** lhs, Object * rhs);
|
||||||
/** allocate @p z bytes of memory. returns pointer to first address **/
|
|
||||||
virtual std::byte * alloc(std::size_t z) = 0;
|
|
||||||
/** allocate @p z bytes for copy of object at @p src.
|
/** allocate @p z bytes for copy of object at @p src.
|
||||||
* Only used in @ref GC. Default implementation asserts and returns nullptr
|
* Only used in @ref GC. Default implementation asserts and returns nullptr
|
||||||
**/
|
**/
|
||||||
|
|
|
||||||
|
|
@ -122,15 +122,15 @@ namespace xo {
|
||||||
static Object * _forward(Object * src, gc::GC * gc);
|
static Object * _forward(Object * src, gc::GC * gc);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void _forward_inplace(T ** src_addr) {
|
static void _forward_inplace(T ** src_addr, gc::GC * gc) {
|
||||||
Object * fwd = _forward(*src_addr, _gc());
|
Object * fwd = _forward(*src_addr, gc);
|
||||||
|
|
||||||
*src_addr = reinterpret_cast<T *>(fwd);
|
*src_addr = reinterpret_cast<T *>(fwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static void _forward_inplace(gp<T> & src) {
|
static void _forward_inplace(gp<T> & src, gc::GC * gc) {
|
||||||
_forward_inplace<T>(src.ptr_address());
|
_forward_inplace<T>(src.ptr_address(), gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** primary workhorse for garbage collection.
|
/** primary workhorse for garbage collection.
|
||||||
|
|
@ -156,10 +156,10 @@ namespace xo {
|
||||||
**/
|
**/
|
||||||
static Object * _deep_move(Object * src, gc::GC * gc, gc::ObjectStatistics * stats);
|
static Object * _deep_move(Object * src, gc::GC * gc, gc::ObjectStatistics * stats);
|
||||||
|
|
||||||
/** copy @p src to to-space, and replace original with forwarding pointer to new location.
|
/** copy @p src to to-space. Overwrite original with forwarding pointer to new location.
|
||||||
* return the new location
|
* return the new location
|
||||||
**/
|
**/
|
||||||
static Object * _shallow_move(Object * src, gc::GC * gc);
|
static Object * _shallow_move(Object * src, gc::IAlloc * gc);
|
||||||
|
|
||||||
// Reflection support
|
// Reflection support
|
||||||
|
|
||||||
|
|
@ -207,7 +207,7 @@ namespace xo {
|
||||||
*
|
*
|
||||||
* Require: @ref mm is an instance of @ref gc::GC
|
* Require: @ref mm is an instance of @ref gc::GC
|
||||||
**/
|
**/
|
||||||
virtual Object * _shallow_copy(gc::IAlloc * mm) const = 0;
|
virtual Object * _shallow_copy(gc::IAlloc * gc) const = 0;
|
||||||
|
|
||||||
/** update child pointers that refer to forwarding pointers,
|
/** update child pointers that refer to forwarding pointers,
|
||||||
* replacing them with the correct destination.
|
* replacing them with the correct destination.
|
||||||
|
|
@ -243,7 +243,7 @@ namespace xo {
|
||||||
* allocated by @ref _shallow_move
|
* allocated by @ref _shallow_move
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
virtual std::size_t _forward_children() = 0;
|
virtual std::size_t _forward_children(gc::GC * gc) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
||||||
|
|
@ -356,6 +356,14 @@ namespace xo {
|
||||||
return free_ptr_ - checkpoint_;
|
return free_ptr_ - checkpoint_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ArenaAlloc::check_owned(Object * src) const
|
||||||
|
{
|
||||||
|
byte * addr = reinterpret_cast<byte *>(src);
|
||||||
|
|
||||||
|
return (lo_ <= addr) && (addr < hi_);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ArenaAlloc::debug_flag() const
|
ArenaAlloc::debug_flag() const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ namespace xo {
|
||||||
|
|
||||||
// LCOV_EXCL_START
|
// LCOV_EXCL_START
|
||||||
std::size_t
|
std::size_t
|
||||||
Forwarding1::_forward_children() {
|
Forwarding1::_forward_children(gc::GC *) {
|
||||||
assert(false);
|
assert(false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -559,6 +559,19 @@ namespace xo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GC::check_owned(Object * src) const
|
||||||
|
{
|
||||||
|
return this->fromspace_contains(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
GC::check_move(Object * src) const
|
||||||
|
{
|
||||||
|
return (this->runstate().full_move()
|
||||||
|
|| (this->tospace_generation_of(src) != gc::generation_result::tenured));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GC::swap_nursery()
|
GC::swap_nursery()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,18 @@ namespace xo {
|
||||||
*lhs = rhs;
|
*lhs = rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IAlloc::check_owned(Object * /*obj*/) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IAlloc::check_move(Object * /*obj*/) const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// LCOV_EXCL_START
|
// LCOV_EXCL_START
|
||||||
std::byte *
|
std::byte *
|
||||||
IAlloc::alloc_gc_copy(std::size_t /*z*/, const void * /*src*/)
|
IAlloc::alloc_gc_copy(std::size_t /*z*/, const void * /*src*/)
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,9 @@ operator new (std::size_t z, const xo::Cpof & cpof)
|
||||||
{
|
{
|
||||||
using xo::gc::GC;
|
using xo::gc::GC;
|
||||||
|
|
||||||
GC * gc = reinterpret_cast<GC *>(cpof.mm_);
|
//GC * gc = reinterpret_cast<GC *>(cpof.mm_);
|
||||||
|
|
||||||
return gc->alloc_gc_copy(z, cpof.src_);
|
return cpof.mm_->alloc_gc_copy(z, cpof.src_);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
|
|
@ -32,18 +32,15 @@ namespace xo {
|
||||||
if (src->_is_forwarded())
|
if (src->_is_forwarded())
|
||||||
return src->_offset_destination(src);
|
return src->_offset_destination(src);
|
||||||
|
|
||||||
bool full_move = gc->runstate().full_move();
|
if (gc->check_move(src)) {
|
||||||
|
Object::_shallow_move(src, gc);
|
||||||
|
|
||||||
if (!full_move && (gc->tospace_generation_of(src) == gc::generation_result::tenured)) {
|
/* *src is now a forwarding pointer to a copy in to-space */
|
||||||
|
return src->_offset_destination(src);
|
||||||
|
} else {
|
||||||
/* don't move tenured objects during incremental collection */
|
/* don't move tenured objects during incremental collection */
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object::_shallow_move(src, gc);
|
|
||||||
|
|
||||||
/* *src is now a forwarding pointer to copy in to-space */
|
|
||||||
|
|
||||||
return src->_offset_destination(src);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object *
|
Object *
|
||||||
|
|
@ -59,9 +56,7 @@ namespace xo {
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
bool full_move = gc->runstate().full_move();
|
if (!gc->check_move(from_src)) {
|
||||||
|
|
||||||
if (!full_move && gc->tospace_generation_of(from_src) == gc::generation_result::tenured) {
|
|
||||||
/** incremental collection does not move already-tenured objects **/
|
/** incremental collection does not move already-tenured objects **/
|
||||||
return from_src;
|
return from_src;
|
||||||
}
|
}
|
||||||
|
|
@ -70,7 +65,8 @@ namespace xo {
|
||||||
* To-space:
|
* To-space:
|
||||||
*
|
*
|
||||||
* to_lo = start of 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
|
* 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)
|
* (also implies this GC cycle put it there)
|
||||||
* g,G = grey objects. An object x is gray if it's in to-space,
|
* g,G = grey objects. An object x is gray if it's in to-space,
|
||||||
* but possibly has >0 black children
|
* but possibly has >0 black children
|
||||||
|
|
@ -141,7 +137,7 @@ namespace xo {
|
||||||
|
|
||||||
// update per-class stats here
|
// update per-class stats here
|
||||||
|
|
||||||
std::size_t xz = x->_forward_children();
|
std::size_t xz = x->_forward_children(gc);
|
||||||
|
|
||||||
// must pad xz to multiple of word size,
|
// must pad xz to multiple of word size,
|
||||||
// to match behavior of LinearAlloc::alloc()
|
// to match behavior of LinearAlloc::alloc()
|
||||||
|
|
@ -163,12 +159,12 @@ namespace xo {
|
||||||
} /*deep_move*/
|
} /*deep_move*/
|
||||||
|
|
||||||
Object *
|
Object *
|
||||||
Object::_shallow_move(Object * src, gc::GC * gc)
|
Object::_shallow_move(Object * src, gc::IAlloc * gc)
|
||||||
{
|
{
|
||||||
/* filter for source objects that are owned by GC.
|
/* filter for source objects that are owned by GC.
|
||||||
* Care required though -- during GC from/to spaces have been swapped already
|
* Care required though -- during GC from/to spaces have been swapped already
|
||||||
*/
|
*/
|
||||||
if (gc->fromspace_contains(src))
|
if (gc->check_owned(src))
|
||||||
{
|
{
|
||||||
Object * dest = src->_shallow_copy(gc);
|
Object * dest = src->_shallow_copy(gc);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue