/** @file GCObjectStore.hpp * * @author Roland Conybeare, Apr 2026 **/ #pragma once #include "GCObjectStoreConfig.hpp" #include "generation.hpp" #include "object_age.hpp" #include //#include #include namespace xo { namespace mm { /** @brief container to hold gc-aware objects for X1 collector **/ class GCObjectStore { public: using header_type = DArena::header_type; using value_type = DArena::value_type; using size_type = DArena::size_type; public: explicit GCObjectStore(const GCObjectStoreConfig & cfg); const GCObjectStoreConfig & config() const noexcept { return config_; } const DArena * get_space(role r, Generation g) const noexcept { return space_[r][g]; } DArena * get_space(role r, Generation g) noexcept { return space_[r][g]; } DArena * from_space(Generation g) noexcept { return get_space(role::from_space(), g); } DArena * to_space(Generation g) noexcept { return get_space(role::to_space(), g); } DArena * new_space() noexcept { return to_space(Generation{0}); } /** generation to which pointer @p addr belongs, given role @p r; * sentinel if not found in this collector **/ Generation generation_of(role r, const void * addr) const noexcept; /** get allocation size from header **/ std::size_t header2size(header_type hdr) const noexcept; /** get generation counter from alloc header **/ object_age header2age(header_type hdr) const noexcept; /** get tseq from alloc header **/ uint32_t header2tseq(header_type hdr) const noexcept; /** true iff original alloc has been replaced by a forwarding pointer **/ bool is_forwarding_header(header_type hdr) const noexcept; /** Retreive bookkeeping info for allocation at @p mem. **/ AllocInfo alloc_info(value_type mem) const noexcept; /** Call @p visitor for each memory pool owned by this store **/ void visit_pools(const MemorySizeVisitor & visitor) const; /** true iff address @p addr allocated from this collector * in role @p r (according to current GC state) **/ bool contains(role r, const void * addr) const noexcept; /** true iff address @p addr allocated from this collector and currently live * in role @p r (according to current GC state) * * (i.e. in [lo,free) for an arena) **/ bool contains_allocated(role r, const void * addr) const noexcept; /** true iff {@p alloc_hdr, @p object_data} should move for * a collection of all generations strictly younger than @p upto. * * Require: runstate_.is_running() **/ bool check_move_policy(Generation upto, header_type alloc_hdr, void * gco_data) const noexcept; /** For each generation g in [0 ,.., upto) * swap arenas assigned to {to-space, from-space}. * Invoked once at the beginning of each gc cycle. **/ void swap_roles(Generation upto) noexcept; /** Cleanup at the end of a gc cycle. * Reset from-space * (current from-space is former to-space, * relabeled at the beginning of collector cycle) * for generations in [0 ,.., upto) **/ void cleanup_phase(Generation upto, bool sanitize_flag); private: /** auxiliary init function **/ void _init_space(); private: /** configuration for gc-aware object store **/ GCObjectStoreConfig config_; /** arena objects for collector managed memory * 1:1 with roles, but polarity reverses for each collection **/ std::array space_storage_[c_n_role]; /** arena pointers. The roles of space_storage_[0][g] and space_storage_[1][g] * are reversed each time generation g gets collected. **/ std::array space_[c_n_role]; }; } /*namespace mm*/ } /*namespace xo*/ /* end GCObjectStore.hpp */