diff --git a/xo-alloc/include/xo/alloc/ArenaAlloc.hpp b/xo-alloc/include/xo/alloc/ArenaAlloc.hpp index 302d9c0a..ed3fd59c 100644 --- a/xo-alloc/include/xo/alloc/ArenaAlloc.hpp +++ b/xo-alloc/include/xo/alloc/ArenaAlloc.hpp @@ -175,6 +175,8 @@ namespace xo { virtual void checkpoint() 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=(ArenaAlloc &&) = delete; diff --git a/xo-alloc/include/xo/alloc/Forwarding1.hpp b/xo-alloc/include/xo/alloc/Forwarding1.hpp index 77e081f9..88ca849a 100644 --- a/xo-alloc/include/xo/alloc/Forwarding1.hpp +++ b/xo-alloc/include/xo/alloc/Forwarding1.hpp @@ -32,7 +32,7 @@ namespace xo { /** required by Object i/face, but never called on Forwarding1 **/ virtual Object * _shallow_copy(gc::IAlloc * mm) const final override; /** 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: /** the object that used to be located at this address (i.e. @c this) diff --git a/xo-alloc/include/xo/alloc/GC.hpp b/xo-alloc/include/xo/alloc/GC.hpp index 8e12990e..423dd2f8 100644 --- a/xo-alloc/include/xo/alloc/GC.hpp +++ b/xo-alloc/include/xo/alloc/GC.hpp @@ -308,6 +308,15 @@ namespace xo { **/ 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_gc_copy(std::size_t z, const void * src) final override; diff --git a/xo-alloc/include/xo/alloc/IAlloc.hpp b/xo-alloc/include/xo/alloc/IAlloc.hpp index 0b6791f0..fceaca94 100644 --- a/xo-alloc/include/xo/alloc/IAlloc.hpp +++ b/xo-alloc/include/xo/alloc/IAlloc.hpp @@ -16,7 +16,12 @@ namespace xo { namespace gc { /** @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 { public: @@ -56,14 +61,28 @@ namespace xo { /** @return true iff debug logging enabled **/ virtual bool debug_flag() const = 0; - /** reset allocator to empty state. **/ - virtual void clear() = 0; /** remember allocator state. All currently-allocated addresses xo * will satisfy is_before_checkpoint(x). Subsequent allocations x * will fail is_before_checkpoint(x), until checkpoint superseded * by @ref clear or another call to @ref checkpoint **/ 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 * @code * *lhs = rhs @@ -72,8 +91,6 @@ namespace xo { * Default implementation just does the assignment. **/ 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. * Only used in @ref GC. Default implementation asserts and returns nullptr **/ diff --git a/xo-alloc/include/xo/alloc/Object.hpp b/xo-alloc/include/xo/alloc/Object.hpp index 849cf9bb..f1d03225 100644 --- a/xo-alloc/include/xo/alloc/Object.hpp +++ b/xo-alloc/include/xo/alloc/Object.hpp @@ -122,15 +122,15 @@ namespace xo { static Object * _forward(Object * src, gc::GC * gc); template - static void _forward_inplace(T ** src_addr) { - Object * fwd = _forward(*src_addr, _gc()); + static void _forward_inplace(T ** src_addr, gc::GC * gc) { + Object * fwd = _forward(*src_addr, gc); *src_addr = reinterpret_cast(fwd); } template - static void _forward_inplace(gp & src) { - _forward_inplace(src.ptr_address()); + static void _forward_inplace(gp & src, gc::GC * gc) { + _forward_inplace(src.ptr_address(), gc); } /** primary workhorse for garbage collection. @@ -156,10 +156,10 @@ namespace xo { **/ 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 **/ - static Object * _shallow_move(Object * src, gc::GC * gc); + static Object * _shallow_move(Object * src, gc::IAlloc * gc); // Reflection support @@ -207,7 +207,7 @@ namespace xo { * * 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, * replacing them with the correct destination. @@ -243,7 +243,7 @@ namespace xo { * allocated by @ref _shallow_move * **/ - virtual std::size_t _forward_children() = 0; + virtual std::size_t _forward_children(gc::GC * gc) = 0; }; template diff --git a/xo-alloc/src/alloc/ArenaAlloc.cpp b/xo-alloc/src/alloc/ArenaAlloc.cpp index c06b9518..15078a0e 100644 --- a/xo-alloc/src/alloc/ArenaAlloc.cpp +++ b/xo-alloc/src/alloc/ArenaAlloc.cpp @@ -356,6 +356,14 @@ namespace xo { return free_ptr_ - checkpoint_; } + bool + ArenaAlloc::check_owned(Object * src) const + { + byte * addr = reinterpret_cast(src); + + return (lo_ <= addr) && (addr < hi_); + } + bool ArenaAlloc::debug_flag() const { diff --git a/xo-alloc/src/alloc/Forwarding1.cpp b/xo-alloc/src/alloc/Forwarding1.cpp index b4a44ff6..2cc183d5 100644 --- a/xo-alloc/src/alloc/Forwarding1.cpp +++ b/xo-alloc/src/alloc/Forwarding1.cpp @@ -60,7 +60,7 @@ namespace xo { // LCOV_EXCL_START std::size_t - Forwarding1::_forward_children() { + Forwarding1::_forward_children(gc::GC *) { assert(false); return 0; } diff --git a/xo-alloc/src/alloc/GC.cpp b/xo-alloc/src/alloc/GC.cpp index c78768fb..bb556620 100644 --- a/xo-alloc/src/alloc/GC.cpp +++ b/xo-alloc/src/alloc/GC.cpp @@ -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 GC::swap_nursery() { diff --git a/xo-alloc/src/alloc/IAlloc.cpp b/xo-alloc/src/alloc/IAlloc.cpp index 8fe4789a..9754fb47 100644 --- a/xo-alloc/src/alloc/IAlloc.cpp +++ b/xo-alloc/src/alloc/IAlloc.cpp @@ -47,6 +47,18 @@ namespace xo { *lhs = rhs; } + bool + IAlloc::check_owned(Object * /*obj*/) const + { + return false; + } + + bool + IAlloc::check_move(Object * /*obj*/) const + { + return false; + } + // LCOV_EXCL_START std::byte * IAlloc::alloc_gc_copy(std::size_t /*z*/, const void * /*src*/) diff --git a/xo-alloc/src/alloc/Object.cpp b/xo-alloc/src/alloc/Object.cpp index 309e0886..560f941b 100644 --- a/xo-alloc/src/alloc/Object.cpp +++ b/xo-alloc/src/alloc/Object.cpp @@ -14,9 +14,9 @@ operator new (std::size_t z, const xo::Cpof & cpof) { using xo::gc::GC; - GC * gc = reinterpret_cast(cpof.mm_); + //GC * gc = reinterpret_cast(cpof.mm_); - return gc->alloc_gc_copy(z, cpof.src_); + return cpof.mm_->alloc_gc_copy(z, cpof.src_); } namespace xo { @@ -32,18 +32,15 @@ namespace xo { if (src->_is_forwarded()) 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 */ return src; } - - Object::_shallow_move(src, gc); - - /* *src is now a forwarding pointer to copy in to-space */ - - return src->_offset_destination(src); } Object * @@ -59,9 +56,7 @@ namespace xo { if (retval) return retval; - bool full_move = gc->runstate().full_move(); - - if (!full_move && gc->tospace_generation_of(from_src) == gc::generation_result::tenured) { + if (!gc->check_move(from_src)) { /** incremental collection does not move already-tenured objects **/ return from_src; } @@ -70,7 +65,8 @@ namespace xo { * 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) * g,G = grey objects. An object x is gray if it's in to-space, * but possibly has >0 black children @@ -141,7 +137,7 @@ namespace xo { // 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, // to match behavior of LinearAlloc::alloc() @@ -163,12 +159,12 @@ namespace xo { } /*deep_move*/ 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. * 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); diff --git a/xo-interpreter/include/xo/interpreter/GlobalEnv.hpp b/xo-interpreter/include/xo/interpreter/GlobalEnv.hpp index bed452da..54a7cbdd 100644 --- a/xo-interpreter/include/xo/interpreter/GlobalEnv.hpp +++ b/xo-interpreter/include/xo/interpreter/GlobalEnv.hpp @@ -35,7 +35,7 @@ namespace xo { virtual void display(std::ostream & os) const final override; virtual std::size_t _shallow_size() const final override; virtual Object * _shallow_copy(gc::IAlloc * mm) const final override; - virtual std::size_t _forward_children() final override; + virtual std::size_t _forward_children(gc::GC * /*gc*/) final override; private: GlobalEnv(const GlobalEnv & x); diff --git a/xo-interpreter/include/xo/interpreter/LocalEnv.hpp b/xo-interpreter/include/xo/interpreter/LocalEnv.hpp index e762d7d7..d79a3355 100644 --- a/xo-interpreter/include/xo/interpreter/LocalEnv.hpp +++ b/xo-interpreter/include/xo/interpreter/LocalEnv.hpp @@ -103,7 +103,7 @@ namespace xo { virtual void display(std::ostream & os) const final override; virtual std::size_t _shallow_size() const final override; virtual Object * _shallow_copy(gc::IAlloc * mm) const final override; - virtual std::size_t _forward_children() final override; + virtual std::size_t _forward_children(gc::GC * /*gc*/) final override; private: /** parent stack frame **/ diff --git a/xo-interpreter/src/interpreter/GlobalEnv.cpp b/xo-interpreter/src/interpreter/GlobalEnv.cpp index 38b9ff1c..a45893bd 100644 --- a/xo-interpreter/src/interpreter/GlobalEnv.cpp +++ b/xo-interpreter/src/interpreter/GlobalEnv.cpp @@ -90,10 +90,10 @@ namespace xo { } std::size_t - GlobalEnv::_forward_children() + GlobalEnv::_forward_children(gc::GC * gc) { for (auto & ix : *slot_map_) { - Object::_forward_inplace(ix.second); + Object::_forward_inplace(ix.second, gc); } return _shallow_size(); } diff --git a/xo-interpreter/src/interpreter/LocalEnv.cpp b/xo-interpreter/src/interpreter/LocalEnv.cpp index 6042d00d..65462157 100644 --- a/xo-interpreter/src/interpreter/LocalEnv.cpp +++ b/xo-interpreter/src/interpreter/LocalEnv.cpp @@ -121,14 +121,14 @@ namespace xo { } std::size_t - LocalEnv::_forward_children() + LocalEnv::_forward_children(gc::GC * gc) { static_assert(decltype(symtab_)::is_gc_ptr == false); - Object::_forward_inplace(parent_); + Object::_forward_inplace(parent_, gc); // Object::_forward_inplace(symtab_); // not a gp yet for (std::size_t i = 0, n = slot_v_.size(); i < n; ++i) { - Object::_forward_inplace((*this)[i]); + Object::_forward_inplace((*this)[i], gc); } return _shallow_size(); diff --git a/xo-object/include/xo/object/Boolean.hpp b/xo-object/include/xo/object/Boolean.hpp index e0b9217c..8379b0f4 100644 --- a/xo-object/include/xo/object/Boolean.hpp +++ b/xo-object/include/xo/object/Boolean.hpp @@ -24,8 +24,8 @@ namespace xo { virtual TaggedPtr self_tp() const final override; virtual void display(std::ostream & os) const final override; virtual std::size_t _shallow_size() const final override; - virtual Object * _shallow_copy(gc::IAlloc * mm) const final override; - virtual std::size_t _forward_children() final override; + virtual Object * _shallow_copy(gc::IAlloc * gc) const final override; + virtual std::size_t _forward_children(gc::GC * gc) final override; private: explicit Boolean(bool x) : value_{x} {} diff --git a/xo-object/include/xo/object/Float.hpp b/xo-object/include/xo/object/Float.hpp index 507aefff..ce6fa3be 100644 --- a/xo-object/include/xo/object/Float.hpp +++ b/xo-object/include/xo/object/Float.hpp @@ -29,8 +29,8 @@ namespace xo { virtual TaggedPtr self_tp() const final override; virtual void display(std::ostream & os) const final override; virtual std::size_t _shallow_size() const final override; - virtual Object * _shallow_copy(gc::IAlloc * mm) const final override; - virtual std::size_t _forward_children() final override; + virtual Object * _shallow_copy(gc::IAlloc * gc) const final override; + virtual std::size_t _forward_children(gc::GC * gc) final override; private: float_type value_ = 0.0; diff --git a/xo-object/include/xo/object/Integer.hpp b/xo-object/include/xo/object/Integer.hpp index d3ebd22d..8f4a0c8f 100644 --- a/xo-object/include/xo/object/Integer.hpp +++ b/xo-object/include/xo/object/Integer.hpp @@ -29,8 +29,8 @@ namespace xo { virtual TaggedPtr self_tp() const final override; virtual void display(std::ostream & os) const final override; virtual std::size_t _shallow_size() const final override; - virtual Object * _shallow_copy(gc::IAlloc * mm) const final override; - virtual std::size_t _forward_children() final override; + virtual Object * _shallow_copy(gc::IAlloc * gc) const final override; + virtual std::size_t _forward_children(gc::GC * gc) final override; private: int_type value_ = 0; diff --git a/xo-object/include/xo/object/List.hpp b/xo-object/include/xo/object/List.hpp index cc601a16..c263484c 100644 --- a/xo-object/include/xo/object/List.hpp +++ b/xo-object/include/xo/object/List.hpp @@ -58,8 +58,8 @@ namespace xo { virtual TaggedPtr self_tp() const final override; virtual void display(std::ostream & os) const final override; virtual std::size_t _shallow_size() const final override; - virtual Object * _shallow_copy(gc::IAlloc * mm) const final override; - virtual std::size_t _forward_children() final override; + virtual Object * _shallow_copy(gc::IAlloc * gc) const final override; + virtual std::size_t _forward_children(gc::GC * gc) final override; private: List(gp head, gp rest); diff --git a/xo-object/include/xo/object/String.hpp b/xo-object/include/xo/object/String.hpp index 90d8c536..c8fa712b 100644 --- a/xo-object/include/xo/object/String.hpp +++ b/xo-object/include/xo/object/String.hpp @@ -36,8 +36,8 @@ namespace xo { virtual TaggedPtr self_tp() const final override; virtual void display(std::ostream & os) const final override; virtual std::size_t _shallow_size() const final override; - virtual Object * _shallow_copy(gc::IAlloc * mm) const final override; - virtual std::size_t _forward_children() final override; + virtual Object * _shallow_copy(gc::IAlloc * gc) const final override; + virtual std::size_t _forward_children(gc::GC * gc) final override; private: String(owner owner, std::size_t z, char * s); diff --git a/xo-object/src/object/Boolean.cpp b/xo-object/src/object/Boolean.cpp index 13cf3f01..4b1c465c 100644 --- a/xo-object/src/object/Boolean.cpp +++ b/xo-object/src/object/Boolean.cpp @@ -75,7 +75,7 @@ namespace xo { // LCOV_EXCL_START std::size_t - Boolean::_forward_children() + Boolean::_forward_children(gc::GC *) { assert(false); return 0; diff --git a/xo-object/src/object/Float.cpp b/xo-object/src/object/Float.cpp index 4939fa49..0a34f451 100644 --- a/xo-object/src/object/Float.cpp +++ b/xo-object/src/object/Float.cpp @@ -48,7 +48,7 @@ namespace xo { } std::size_t - Float::_forward_children() { + Float::_forward_children(gc::GC * /*gc*/) { return Float::_shallow_size(); } } diff --git a/xo-object/src/object/Integer.cpp b/xo-object/src/object/Integer.cpp index f5587b1f..d901569f 100644 --- a/xo-object/src/object/Integer.cpp +++ b/xo-object/src/object/Integer.cpp @@ -49,7 +49,7 @@ namespace xo { } std::size_t - Integer::_forward_children() { + Integer::_forward_children(gc::GC * /*gc*/) { return Integer::_shallow_size(); } diff --git a/xo-object/src/object/List.cpp b/xo-object/src/object/List.cpp index a82c7cc5..1c8c1d56 100644 --- a/xo-object/src/object/List.cpp +++ b/xo-object/src/object/List.cpp @@ -71,12 +71,14 @@ namespace xo { } TaggedPtr - List::self_tp() const { + List::self_tp() const + { return Reflect::make_tp(const_cast(this)); } void - List::display(std::ostream & os) const { + List::display(std::ostream & os) const + { gp l = const_cast(this); os << "("; @@ -92,25 +94,26 @@ namespace xo { } std::size_t - List::_shallow_size() const { + List::_shallow_size() const + { return sizeof(List); } Object * - List::_shallow_copy(gc::IAlloc * mm) const { - scope log(XO_DEBUG(mm->debug_flag())); - + List::_shallow_copy(gc::IAlloc * gc) const + { assert(!(this->is_nil())); - Cpof cpof(mm, this); + Cpof cpof(gc, this); return new (cpof) List(*this); } std::size_t - List::_forward_children() { - Object::_forward_inplace(head_); - Object::_forward_inplace(rest_); + List::_forward_children(gc::GC * gc) + { + Object::_forward_inplace(head_, gc); + Object::_forward_inplace(rest_, gc); return List::_shallow_size(); } } diff --git a/xo-object/src/object/String.cpp b/xo-object/src/object/String.cpp index 400d187c..d56d75e4 100644 --- a/xo-object/src/object/String.cpp +++ b/xo-object/src/object/String.cpp @@ -152,7 +152,7 @@ namespace xo { } std::size_t - String::_forward_children() + String::_forward_children(gc::GC *) { return this->_shallow_size(); }