/** @file GCObjectStore.cpp * * @author Roland Conybeare, Apr 2026 **/ #include "GCObjectStore.hpp" #include #include namespace xo { namespace mm { GCObjectStore::GCObjectStore(const ArenaConfig & arena_cfg, uint32_t ngen, bool debug_flag) : arena_config_{arena_cfg}, n_generation_{ngen}, debug_flag_{debug_flag} { assert(arena_config_.header_.size_bits_ + arena_config_.header_.age_bits_ + arena_config_.header_.tseq_bits_ <= 64); this->_init_space(); } void GCObjectStore::_init_space() { assert(c_n_role == 2); for (uint32_t igen = 0, ngen = n_generation_; igen < ngen; ++igen) { if (igen < c_max_generation) { { char buf[40]; snprintf(buf, sizeof(buf), "x1-space-G%u-a", igen); this->space_storage_[0][igen] = DArena::map(arena_config_.with_name(std::string(buf))); } { char buf[40]; snprintf(buf, sizeof(buf), "x1-space-G%u-b", igen); this->space_storage_[1][igen] = DArena::map(arena_config_.with_name(std::string(buf))); } this->space_[role::to_space()][igen] = &space_storage_[0][igen]; this->space_[role::from_space()][igen] = &space_storage_[1][igen]; } else { assert(false); } } for (uint32_t igen = n_generation_; igen < c_max_generation; ++igen) { this->space_[role::to_space()][igen] = nullptr; this->space_[role::from_space()][igen] = nullptr; } if (n_generation_ == 2) { assert(this->get_space(role::to_space(), Generation{2}) == nullptr); } } Generation GCObjectStore::generation_of(role r, const void * addr) const noexcept { for (Generation gi{0}; gi < n_generation_; ++gi) { const DArena * arena = this->get_space(r, gi); if (arena->contains(addr)) return gi; } return Generation::sentinel(); } auto GCObjectStore::header2size(header_type hdr) const noexcept -> size_type { uint32_t z = arena_config_.header_.size(hdr); return z; } object_age GCObjectStore::header2age(header_type hdr) const noexcept { uint32_t age = arena_config_.header_.age(hdr); assert(age < c_max_object_age); return object_age(age); } uint32_t GCObjectStore::header2tseq(header_type hdr) const noexcept { uint32_t tseq = arena_config_.header_.tseq(hdr); return tseq; } bool GCObjectStore::is_forwarding_header(header_type hdr) const noexcept { /** forwarding pointer encoded as sentinel tseq **/ return arena_config_.header_.is_forwarding_tseq(hdr); } void GCObjectStore::visit_pools(const MemorySizeVisitor & visitor) const { for (uint32_t j = 0; j < n_generation_; ++j) { for (uint32_t i = 0; i < c_n_role; ++i) { space_storage_[i][j].visit_pools(visitor); } } } void GCObjectStore::swap_roles(Generation upto) noexcept { scope log(XO_DEBUG(debug_flag_), xtag("upto", upto)); for (Generation g = Generation{0}; g < upto; ++g) { log && log("swap roles", xtag("g", g)); std::swap(space_[role::to_space()][g], space_[role::from_space()][g]); } } void GCObjectStore::cleanup_phase(Generation upto, bool sanitize_flag) { scope log(XO_DEBUG(debug_flag_), xtag("upto", upto)); // everything live has been copied out of from-space // -> now set to empty // for (Generation g = Generation{0}; g < upto; ++g) { if (sanitize_flag) { space_[role::from_space()][g]->scrub(); } space_[role::from_space()][g]->clear(); } } } /*namespace mm*/ } /*namespace xo*/ /* end GCObjectStore.cpp */