From 30a00be2620dc0ad40a71b1258454db269a6c428 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Mon, 1 Dec 2025 01:20:49 -0500 Subject: [PATCH] xo-alloc + xo-allocutil: refactor to shrink dep surface area --- include/xo/alloc/ArenaAlloc.hpp | 4 +- include/xo/alloc/Forwarding1.hpp | 10 +- include/xo/alloc/GC.hpp | 37 +++---- include/xo/alloc/IAlloc.hpp | 129 ----------------------- include/xo/alloc/Object.hpp | 171 +++++-------------------------- src/alloc/ArenaAlloc.cpp | 2 +- src/alloc/Blob.cpp | 2 +- src/alloc/CMakeLists.txt | 2 +- src/alloc/Forwarding1.cpp | 21 ++-- src/alloc/GC.cpp | 41 ++++---- src/alloc/IAlloc.cpp | 74 ------------- src/alloc/Object.cpp | 20 ++-- 12 files changed, 100 insertions(+), 413 deletions(-) delete mode 100644 include/xo/alloc/IAlloc.hpp delete mode 100644 src/alloc/IAlloc.cpp diff --git a/include/xo/alloc/ArenaAlloc.hpp b/include/xo/alloc/ArenaAlloc.hpp index d9731761..1f48121b 100644 --- a/include/xo/alloc/ArenaAlloc.hpp +++ b/include/xo/alloc/ArenaAlloc.hpp @@ -5,7 +5,7 @@ #pragma once -#include "IAlloc.hpp" +#include "xo/allocutil/IAlloc.hpp" #include "ObjectStatistics.hpp" namespace xo { @@ -175,8 +175,8 @@ namespace xo { virtual void clear() final override; virtual void checkpoint() final override; virtual std::byte * alloc(std::size_t z) final override; + virtual bool check_owned(IObject * src) const final override; - virtual bool check_owned(Object * src) const final override; ArenaAlloc & operator=(const ArenaAlloc &) = delete; ArenaAlloc & operator=(ArenaAlloc &&) = delete; diff --git a/include/xo/alloc/Forwarding1.hpp b/include/xo/alloc/Forwarding1.hpp index 8999849a..90ff0198 100644 --- a/include/xo/alloc/Forwarding1.hpp +++ b/include/xo/alloc/Forwarding1.hpp @@ -19,18 +19,18 @@ namespace xo { **/ class Forwarding1 : public Object { public: - explicit Forwarding1(gp dest); + explicit Forwarding1(gp dest); // inherited from Object.. virtual TaggedPtr self_tp() const final override; virtual void display(std::ostream & os) const final override; virtual bool _is_forwarded() const final override { return true; } - virtual Object * _offset_destination(Object * src) const final override; - virtual Object * _destination() final override; + virtual IObject * _offset_destination(IObject * src) const final override; + virtual IObject * _destination() final override; /** required by Object i/face, but never called on Forwarding1 **/ virtual std::size_t _shallow_size() const final override; /** required by Object i/face, but never called on Forwarding1 **/ - virtual Object * _shallow_copy(gc::IAlloc * mm) const final override; + virtual IObject * _shallow_copy(gc::IAlloc * mm) const final override; /** required by Object i/face, but never called on Forwarding1 **/ virtual std::size_t _forward_children(gc::IAlloc * mm) final override; @@ -47,7 +47,7 @@ namespace xo { * UB revealed when GC traverses a pointer that relies on the 2nd * vtable to index virtual methods. **/ - gp dest_; + gp dest_; }; } /*namespace obj*/ diff --git a/include/xo/alloc/GC.hpp b/include/xo/alloc/GC.hpp index 6146cba9..aeb918c9 100644 --- a/include/xo/alloc/GC.hpp +++ b/include/xo/alloc/GC.hpp @@ -88,29 +88,30 @@ namespace xo { class MutationLogEntry { public: - MutationLogEntry(Object * parent, Object ** lhs) : parent_{parent}, lhs_{lhs} {} + MutationLogEntry(IObject * parent, IObject ** lhs) + : parent_{parent}, lhs_{lhs} {} - Object * parent() const { return parent_; } - Object ** lhs() const { return lhs_; } + IObject * parent() const { return parent_; } + IObject ** lhs() const { return lhs_; } - Object * child() const { return *lhs_; } + IObject * child() const { return *lhs_; } bool is_child_forwarded() const; bool is_parent_forwarded() const; - Object * parent_destination() const; + IObject * parent_destination() const; /** Flag obsolete mutation. * Future proofing, never happens for regular objects **/ bool is_dead() const { return false; } - MutationLogEntry update_parent_moved(Object * parent_to) const; - void fixup_parent_child_moved(Object * child_to) { *lhs_ = child_to; } + MutationLogEntry update_parent_moved(IObject * parent_to) const; + void fixup_parent_child_moved(IObject * child_to) { *lhs_ = child_to; } private: - Object * parent_; - Object ** lhs_; + IObject * parent_ = nullptr; + IObject ** lhs_ = nullptr; }; using MutationLog = std::vector; @@ -235,15 +236,15 @@ namespace xo { /** add gc root at address @p addr . Gc will keep alive anything reachable * from @c *addr **/ - void add_gc_root(Object ** addr); + void add_gc_root(IObject ** addr); /** reverse the effect of previous call to @ref add_gc_root **/ - void remove_gc_root(Object ** addr); + void remove_gc_root(IObject ** addr); /** convenience wrapper **/ template - void add_gc_root_dwim(gp * p) { this->add_gc_root(reinterpret_cast(p->ptr_address())); } + void add_gc_root_dwim(gp * p) { this->add_gc_root(reinterpret_cast(p->ptr_address())); } template - void remove_gc_root_dwim(gp * p) { this->remove_gc_root(reinterpret_cast(p->ptr_address())); } + void remove_gc_root_dwim(gp * p) { this->remove_gc_root(reinterpret_cast(p->ptr_address())); } /** may optionally use this to observe GC copy phase. * Will be invoked once _per surviving object_, so not cheap. @@ -308,17 +309,17 @@ namespace xo { * @param lhs. address of a member variable within the allocation of @p parent. * @param rhs. new target for @p *lhs **/ - virtual void assign_member(Object * parent, Object ** lhs, Object* rhs) final override; + virtual void assign_member(IObject * parent, IObject ** lhs, IObject* 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; + virtual bool check_owned(IObject * 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 bool check_move(IObject * 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; @@ -349,7 +350,7 @@ namespace xo { /** scan to-space for object statistics before GC */ void capture_object_statistics(generation upto, capture_phase phase); /** copy object **/ - void copy_object(Object ** addr, generation upto, ObjectStatistics * object_stats); + void copy_object(IObject ** addr, generation upto, ObjectStatistics * object_stats); /** copy everything reachable from global gc roots **/ void copy_globals(generation g); /** review mutation log; may discover+rescue reachable objects. @@ -426,7 +427,7 @@ namespace xo { * Application can introduce new root object pointers at any time provided GC not running, * but cannot withdraw them. **/ - std::vector gc_root_v_; + std::vector gc_root_v_; /** log cross-generational and cross-checkpoint mutations. * These need to be adjusted on next incremental collection diff --git a/include/xo/alloc/IAlloc.hpp b/include/xo/alloc/IAlloc.hpp deleted file mode 100644 index 3b36dc98..00000000 --- a/include/xo/alloc/IAlloc.hpp +++ /dev/null @@ -1,129 +0,0 @@ -/* file IAlloc.hpp - * - * author: Roland Conybeare, Jul 2025 - */ - -#pragma once - -#include -#include - -namespace xo { - template - using up = std::unique_ptr; - - class Object; - - namespace gc { - /** @class IAllocator - * @brief arena allocation interface with limited garbage collector support - * - * Garbage collector support methods: - * - checkpoint() - * - assign_member() - * - alloc_gc_copy() - * - * See class GC for copying incremental collector. - * See class ArenaAlloc for arena allocator - **/ - class IAlloc { - public: - virtual ~IAlloc() {} - - /** compute padding to add to an allocation of size z to bring it up to - * a multiple of word size (8 bytes on x86_64) - **/ - static std::uint32_t alloc_padding(std::size_t z); - /** z + alloc_padding(z) **/ - static std::size_t with_padding(std::size_t z); - - /** optional name for this allocator; labelling for diagnostics **/ - virtual const std::string & name() const = 0; - /** allocator size in bytes (up to reserved limit) - * Includes unallocated mmeory - **/ - virtual std::size_t size() const = 0; - /** committed size in bytes **/ - virtual std::size_t committed() const = 0; - /** number of unallocated bytes available (up to soft limit) - * from this allocator - **/ - virtual std::size_t available() const = 0; - /** number of bytes allocated from this allocator **/ - virtual std::size_t allocated() const = 0; - /** true iff pointer x comes from this allocator **/ - virtual bool contains(const void * x) const = 0; - /** true iff object at address @p x was allocated by this allocator, - * and before checkpoint - **/ - virtual bool is_before_checkpoint(const void * x) const = 0; - /** number of bytes allocated before @ref checkpoint **/ - virtual std::size_t before_checkpoint() const = 0; - /** number of bytes allocated since @ref checkpoint **/ - virtual std::size_t after_checkpoint() const = 0; - /** @return true iff debug logging enabled **/ - virtual bool debug_flag() const = 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 - * @endcode - * plus additional book keeping if needed (e.g. in @ref GC) - * Default implementation just does the assignment. - **/ - virtual void assign_member(Object * parent, Object ** lhs, Object * rhs); - /** allocate @p z bytes for copy of object at @p src. - * Only used in @ref GC. Default implementation asserts and returns nullptr - **/ - virtual std::byte * alloc_gc_copy(std::size_t z, const void * src); - }; - } /*namespace gc*/ - - class MMPtr { - public: - explicit MMPtr(gc::IAlloc * mm) : mm_{mm} {} - - gc::IAlloc * mm_ = nullptr; - }; -} /*namespace xo*/ - -inline void * operator new (std::size_t z, const xo::MMPtr & mmp) { - return mmp.mm_->alloc(z); -} - -//inline void operator delete (void * p, const MMPtr & mmp) { -// mmp.mm_->free(reinterpret_cast(p)); -//} - -inline void * operator new[] (std::size_t z, const xo::MMPtr & mmp) { - return mmp.mm_->alloc(z); -} - -//inline void operator delete[] (void * p, const MMPtr & mmp) { -// mmp.mm_->free(reinterpret_cast(p)); -//} - - -/* end IAlloc.hpp */ diff --git a/include/xo/alloc/Object.hpp b/include/xo/alloc/Object.hpp index c8772db9..2468c8bc 100644 --- a/include/xo/alloc/Object.hpp +++ b/include/xo/alloc/Object.hpp @@ -7,6 +7,8 @@ #include "xo/reflect/TaggedPtr.hpp" #include "IAlloc.hpp" +#include "xo/allocutil/IObject.hpp" +#include "xo/allocutil/gc_ptr.hpp" #include #include @@ -16,71 +18,6 @@ namespace xo { class ObjectStatistics; }; - template - class gc_ptr; - - template - using gp = gc_ptr; - - /** wrapper for a pointer to garbage-collector-eligible T. - * Application code will usually use the alias template gp - **/ - template - class gc_ptr { - public: - using element_type = T; - - public: - gc_ptr() = default; - gc_ptr(T * p) : ptr_{p} {} - gc_ptr(const gc_ptr & x) : ptr_{x.ptr_} {} - - /** create from gc_ptr to some related type @tparam S **/ - template - gc_ptr(const gc_ptr & x) : ptr_{x.ptr()} {} - - /** runtime downcast. shorthand for dynamic_cast **/ - template - static gc_ptr from(const gc_ptr & x) { return gc_ptr{dynamic_cast(x.ptr())}; } - - /** convenience for static asserts **/ - static constexpr bool is_gc_ptr = true; - /** see also: xo/refcnt/Refcounted.hpp **/ - static constexpr bool is_rc_ptr = false; - - static bool is_eq(gc_ptr x1, gc_ptr x2) { - std::uintptr_t u1 = reinterpret_cast(x1.ptr()); - std::uintptr_t u2 = reinterpret_cast(x2.ptr()); - - // multiple inheritance shenanigans. - // (allow interface pointers separated by one pointer) - - if (u1 >= u2) - return (u1 <= u2 + sizeof(std::uintptr_t)); - else - return (u2 <= u1 + sizeof(std::uintptr_t)); - } - - /** (for consistency's sake) **/ - T * get() const { return ptr_; } - - T * ptr() const { return ptr_; } - T ** ptr_address() { return &ptr_; } - - bool is_null() const { return ptr_ == nullptr; } - void make_null() { ptr_ = nullptr; } - - void assign_ptr(T * x) { ptr_ = x; } - - gc_ptr & operator=(const gc_ptr & x) { ptr_ = x.ptr(); return *this; } - - T * operator->() const { return ptr_; } - T & operator*() const { return *ptr_; } - - private: - T * ptr_ = nullptr; - }; - /** Root class for all xo GC-collectable objects. * * Design note: @@ -92,11 +29,15 @@ namespace xo { * Would be feasible to relax the must-inherit-from-Object constraint * by having GC use its own wrapper, at cost of an extra layer of indirection **/ - class Object { + class Object : public IObject { public: using TaggedPtr = xo::reflect::TaggedPtr; public: + static gp from(gp x) { + return dynamic_cast(x.ptr()); + } + virtual ~Object() = default; /** memory allocator for objects. Likely this will be a GC instance, @@ -111,7 +52,7 @@ namespace xo { * add mutation log entry **/ template - static void assign_member(gp parent, gp * lhs, gp rhs); + static void assign_member(gp parent, gp * lhs, gp rhs); /** use from GC aux functions **/ static gc::GC * _gc() { return reinterpret_cast(mm); } @@ -125,11 +66,11 @@ namespace xo { * @p src. source object to be forwarded * @p gc. garbage collector */ - static Object * _forward(Object * src, gc::IAlloc * gc); + static IObject * _forward(IObject * src, gc::IAlloc * gc); template static void _forward_inplace(T ** src_addr, gc::IAlloc * gc) { - Object * fwd = _forward(*src_addr, gc); + IObject * fwd = _forward(*src_addr, gc); *src_addr = reinterpret_cast(fwd); } @@ -160,12 +101,12 @@ namespace xo { * @param gc garbage collector * @param stats per-object-type GC statistics **/ - static Object * _deep_move(Object * src, gc::GC * gc, gc::ObjectStatistics * stats); + static IObject * _deep_move(IObject * src, gc::GC * gc, gc::ObjectStatistics * stats); /** 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::IAlloc * gc); + static IObject * _shallow_move(IObject * src, gc::IAlloc * gc); // Reflection support @@ -176,89 +117,25 @@ namespace xo { /** print on stream @p os **/ virtual void display(std::ostream & os) const = 0; - // GC support + // Inherited from IObject.. - /** true iff this object represents a forwarding pointer. - * Forwarding pointers are exclusively created by the garbage collector; - * forwarding pointers (and only forwarding pointers) return true here. - **/ - virtual bool _is_forwarded() const { return false; } + //virtual bool _is_forwarded() const override { return false; } + //virtual IObject * _offset_destination(IObject * src) const override { return src; }; + virtual void _forward_to(IObject * dest) override; + //virtual IObject * _destination() override { return nullptr; } - /** offset for uncommon situation where pointer address is offset from object - * base address - **/ - virtual Object * _offset_destination(Object * src) const { return src; }; - - /** replace this object with a forwarding pointer referring to @p dest. - **/ - virtual void _forward_to(Object * dest); - - /** if this object represents a forwarding pointer, return its new location. - * forwarding pointers belong to the garbage collector implementation. - * (if you have to ask -- no, your class is not a forwarding pointer) - * all other objects return nullptr here. - **/ - virtual Object * _destination() { return nullptr; } - - /** return amount of storage (including padding) consumed by this object, - * excluding immediate Object-pointer children - **/ - virtual std::size_t _shallow_size() const = 0; - - /** if subject is allocated by GC: - * - create copy C in to-space - * - destination C will be nursery|tenured depending on location of this. - * else - * - return this to disengage from GC - * - * Require: @ref mm is an instance of @ref gc::GC - **/ - virtual Object * _shallow_copy(gc::IAlloc * gc) const = 0; - - /** update child pointers that refer to forwarding pointers, - * replacing them with the correct destination. - * See @ref Object::deep_move - * - * this gray object, located in to-space. - * fwd1 forwarding objects. - * Located in from-space. Invalid at end of GC cycle. - * p1,p2 source pointers. - * D1,D2 already-forwarded objects. located in to-space. - * - * before: - * this fwd1 - * +----+ +-+ - * | p1 ----->|x|-------> D1 - * | | +-+ - * | | - * | p2 ----------------> D2 - * +----+ - * - * after: - * this - * +----+ - * | p1 ----------------> D1 - * | | - * | | - * | p2 ----------------> D2 - * +----+ - * - * this is now white - * - * @return shallow size of *this. Must exactly match the amount of memory in to-space - * allocated by @ref _shallow_move - * - **/ - virtual std::size_t _forward_children(gc::IAlloc * gc) = 0; + virtual std::size_t _shallow_size() const override = 0; + virtual IObject * _shallow_copy(gc::IAlloc * gc) const override = 0; + virtual std::size_t _forward_children(gc::IAlloc * gc) override = 0; }; template void - Object::assign_member(gp parent, gp * lhs, gp rhs) + Object::assign_member(gp parent, gp * lhs, gp rhs) { - Object::mm->assign_member(parent.ptr(), - reinterpret_cast(lhs->ptr_address()), - rhs.ptr()); + Object::mm->assign_member(reinterpret_cast(parent.ptr()), + reinterpret_cast(lhs->ptr_address()), + reinterpret_cast(rhs.ptr())); } std::ostream & diff --git a/src/alloc/ArenaAlloc.cpp b/src/alloc/ArenaAlloc.cpp index 15078a0e..886b6a70 100644 --- a/src/alloc/ArenaAlloc.cpp +++ b/src/alloc/ArenaAlloc.cpp @@ -357,7 +357,7 @@ namespace xo { } bool - ArenaAlloc::check_owned(Object * src) const + ArenaAlloc::check_owned(IObject * src) const { byte * addr = reinterpret_cast(src); diff --git a/src/alloc/Blob.cpp b/src/alloc/Blob.cpp index 97932844..83e4121b 100644 --- a/src/alloc/Blob.cpp +++ b/src/alloc/Blob.cpp @@ -5,7 +5,7 @@ #include "Blob.hpp" #include "xo/reflect/Reflect.hpp" -#include "xo/alloc/IAlloc.hpp" +#include "xo/allocutil/IAlloc.hpp" namespace xo { using xo::reflect::Reflect; diff --git a/src/alloc/CMakeLists.txt b/src/alloc/CMakeLists.txt index 4a9d1db4..67e9759b 100644 --- a/src/alloc/CMakeLists.txt +++ b/src/alloc/CMakeLists.txt @@ -2,7 +2,6 @@ set(SELF_LIB xo_alloc) set(SELF_SRCS - IAlloc.cpp ArenaAlloc.cpp ListAlloc.cpp GC.cpp @@ -15,6 +14,7 @@ set(SELF_SRCS ) xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) +xo_headeronly_dependency(${SELF_LIB} xo_allocutil) # xo-unit used for time measurement xo_headeronly_dependency(${SELF_LIB} xo_unit) xo_dependency(${SELF_LIB} indentlog) diff --git a/src/alloc/Forwarding1.cpp b/src/alloc/Forwarding1.cpp index f94bf4f1..a42a3f57 100644 --- a/src/alloc/Forwarding1.cpp +++ b/src/alloc/Forwarding1.cpp @@ -13,7 +13,7 @@ namespace xo { using xo::reflect::TaggedPtr; namespace obj { - Forwarding1::Forwarding1(gp dest) + Forwarding1::Forwarding1(gp dest) : dest_{dest} {} @@ -26,18 +26,21 @@ namespace xo { void Forwarding1::display(std::ostream & os) const { - os << "self_tp().td()->short_name()) << ">"; + os << "self_tp().td()->short_name()) + << ">"; } - Object * - Forwarding1::_offset_destination(Object * src) const + IObject * + Forwarding1::_offset_destination(IObject * src) const { - intptr_t offset = src - static_cast(this); + intptr_t offset = src - static_cast(this); return dest_.ptr() + offset; } - Object * + IObject * Forwarding1::_destination() { return dest_.ptr(); } @@ -51,8 +54,10 @@ namespace xo { // LCOV_EXCL_STOP // LCOV_EXCL_START - Object * + IObject * Forwarding1::_shallow_copy(gc::IAlloc *) const { + /* forwarding objects are never copied */ + assert(false); return nullptr; } @@ -61,6 +66,8 @@ namespace xo { // LCOV_EXCL_START std::size_t Forwarding1::_forward_children(gc::IAlloc *) { + /* forwarding objects are never traced */ + assert(false); return 0; } diff --git a/src/alloc/GC.cpp b/src/alloc/GC.cpp index 3e636cad..ca2506d9 100644 --- a/src/alloc/GC.cpp +++ b/src/alloc/GC.cpp @@ -27,7 +27,7 @@ namespace xo { return parent_->_is_forwarded(); } - Object * + IObject * MutationLogEntry::parent_destination() const { //const bool c_debug_flag = true; @@ -45,7 +45,7 @@ namespace xo { } MutationLogEntry - MutationLogEntry::update_parent_moved(Object * parent_to) const + MutationLogEntry::update_parent_moved(IObject * parent_to) const { std::byte * parent_from = reinterpret_cast(parent_); std::byte * lhs_from = reinterpret_cast(lhs_); @@ -55,7 +55,7 @@ namespace xo { std::byte * lhs_to = reinterpret_cast(parent_to) + offset; return MutationLogEntry(parent_to, - reinterpret_cast(lhs_to)); + reinterpret_cast(lhs_to)); } GC::GC(const Config & config) @@ -395,13 +395,13 @@ namespace xo { } void - GC::add_gc_root(Object ** addr) + GC::add_gc_root(IObject ** addr) { gc_root_v_.push_back(addr); } void - GC::remove_gc_root(Object ** addr) + GC::remove_gc_root(IObject ** addr) { /* Multithreaded GC not supported */ @@ -450,7 +450,9 @@ namespace xo { std::byte * GC::alloc_gc_copy(std::size_t z, const void * src) { - scope log(XO_DEBUG(config_.debug_flag_), xtag("z", z), xtag("+pad", IAlloc::alloc_padding(z))); + scope log(XO_DEBUG(config_.debug_flag_), + xtag("z", z), + xtag("+pad", IAlloc::alloc_padding(z))); generation_result src_gr = this->fromspace_generation_of(src); @@ -483,7 +485,8 @@ namespace xo { gc_copy_cbset_.invoke(&GcCopyCallback::notify_gc_copy, z, src, retval, generation::nursery, generation::tenured); - this->gc_statistics_.total_promoted_ += IAlloc::with_padding(z); + this->gc_statistics_.total_promoted_ + += IAlloc::with_padding(z); } else { log && log("nursery"); @@ -509,7 +512,7 @@ namespace xo { } void - GC::assign_member(Object * parent, Object ** lhs, Object * rhs) + GC::assign_member(IObject * parent, IObject ** lhs, IObject * rhs) { ++gc_statistics_.n_mutation_; @@ -566,13 +569,13 @@ namespace xo { } bool - GC::check_owned(Object * src) const + GC::check_owned(IObject * src) const { return this->fromspace_contains(src); } bool - GC::check_move(Object * src) const + GC::check_move(IObject * src) const { return (this->runstate().full_move() || (this->tospace_generation_of(src) != gc::generation_result::tenured)); @@ -682,7 +685,9 @@ namespace xo { } void - GC::copy_object(Object ** pp_object, generation upto, ObjectStatistics * object_stats) + GC::copy_object(IObject ** pp_object, + generation upto, + ObjectStatistics * object_stats) { void * object_address = *pp_object; @@ -707,7 +712,7 @@ namespace xo { scope log(XO_DEBUG(config_.debug_flag_), xtag("roots", gc_root_v_.size())); - for (Object ** pp_root : gc_root_v_) { + for (IObject ** pp_root : gc_root_v_) { this->copy_object(pp_root, upto, &object_statistics_sae_[gen2int(upto)]); } @@ -778,7 +783,7 @@ namespace xo { // obsolete mutation -- no longer belongs to parent, discard } else { // note: child obtained (as it must be) by reading from parent's memory _now_. - Object * child_from = from_entry.child(); + IObject * child_from = from_entry.child(); if (child_from) { if (!child_from->_is_forwarded()) { @@ -813,7 +818,7 @@ namespace xo { // P->C, C moved to C' // Includes cases (a),(c) from above - Object * child_to = child_from->_destination(); + IObject * child_to = child_from->_destination(); from_entry.fixup_parent_child_moved(child_to); @@ -843,7 +848,7 @@ namespace xo { // follows that loc(P') = T // already have P'->C' when parent moved separately - Object * parent_to = from_entry.parent_destination(); + IObject * parent_to = from_entry.parent_destination(); log && log(xtag("parent_to", (void*)parent_to)); @@ -851,7 +856,7 @@ namespace xo { MutationLogEntry to_entry = from_entry.update_parent_moved(parent_to); - Object * child_to = to_entry.child(); // after moving + IObject * child_to = to_entry.child(); // after moving if (tospace_generation_of(child_to) == generation_result::nursery) { if (to_entry.is_dead()) { @@ -954,7 +959,7 @@ namespace xo { log && (i_from % 10000 == 0) && log(xtag("i_from", i_from)); if (from_entry.is_parent_forwarded()) { - Object * parent_to = from_entry.parent_destination(); + IObject * parent_to = from_entry.parent_destination(); log && log(xtag("parent_to", (void*)parent_to)); @@ -964,7 +969,7 @@ namespace xo { // note: child obtained (as it must be) by reading from prarent's memory _now_. // Since parent has moved, child has too - Object * child_to = to_entry.child(); // after moveing + IObject * child_to = to_entry.child(); // after moveing if (tospace_generation_of(parent_to) == generation_result::tenured) { diff --git a/src/alloc/IAlloc.cpp b/src/alloc/IAlloc.cpp deleted file mode 100644 index 9754fb47..00000000 --- a/src/alloc/IAlloc.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* @file IAlloc.cpp - * - * author: Roland Conybeare, Aug 2025 - */ - -#include "IAlloc.hpp" -#include -#include - -namespace xo { - namespace gc { - - std::uint32_t - IAlloc::alloc_padding(std::size_t z) - { - /* word size for alignment */ - constexpr uint32_t c_bpw = sizeof(std::uintptr_t); - - /* round up to multiple of c_bpw, but map 0 -> 0 - * (table assuming c_bpw==8) - * - * z%c_bpw dz - * ------------ - * 0 0 - * 1 7 - * 2 6 - * .. .. - * 7 1 - */ - std::uint32_t dz = (c_bpw - (z % c_bpw)) % c_bpw; - z += dz; - - assert(z % c_bpw == 0ul); - - return dz; - } - - std::size_t - IAlloc::with_padding(std::size_t z) - { - return z + alloc_padding(z); - } - - void - IAlloc::assign_member(Object * /*parent*/, Object ** lhs, Object * rhs) - { - *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*/) - { - assert(false); - return nullptr; - } - // LCOV_EXCL_STOP - - } /*namespace gc*/ -} /*namespace xo*/ - -/* end IAlloc.cpp */ diff --git a/src/alloc/Object.cpp b/src/alloc/Object.cpp index dbb86ae2..82583a0a 100644 --- a/src/alloc/Object.cpp +++ b/src/alloc/Object.cpp @@ -23,8 +23,8 @@ namespace xo { gc::IAlloc * Object::mm = nullptr; - Object * - Object::_forward(Object * src, gc::IAlloc * gc) + IObject * + Object::_forward(IObject * src, gc::IAlloc * gc) { if (!src) return src; @@ -43,15 +43,15 @@ namespace xo { } } - Object * - Object::_deep_move(Object * from_src, gc::GC * gc, gc::ObjectStatistics * /*stats*/) + IObject * + Object::_deep_move(IObject * from_src, gc::GC * gc, gc::ObjectStatistics * /*stats*/) { using gc::generation; if (!from_src) return nullptr; - Object * retval = from_src->_destination(); + IObject * retval = from_src->_destination(); if (retval) return retval; @@ -124,7 +124,7 @@ namespace xo { std::array gray_lo_v = { gc->free_ptr(generation::nursery), gc->free_ptr(generation::tenured) }; - Object * to_src = Object::_shallow_move(from_src, gc); + IObject * to_src = Object::_shallow_move(from_src, gc); std::size_t fixup_work = 0; do { @@ -158,15 +158,15 @@ namespace xo { return to_src; } /*deep_move*/ - Object * - Object::_shallow_move(Object * src, gc::IAlloc * gc) + 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)) { - Object * dest = src->_shallow_copy(gc); + IObject * dest = src->_shallow_copy(gc); if (dest != src) src->_forward_to(dest); @@ -178,7 +178,7 @@ namespace xo { } void - Object::_forward_to(Object * dest) + Object::_forward_to(IObject * dest) { char * mem = reinterpret_cast(this);