xo-gc: refactor to prune mlog store dep on DX1Collector
This commit is contained in:
parent
9803709df8
commit
1b3ecf9561
8 changed files with 120 additions and 47 deletions
|
|
@ -412,7 +412,7 @@ namespace xo {
|
|||
/** aux init function: initialize @ref roots_ arena **/
|
||||
void _init_gc_roots(const X1CollectorConfig & cfg, std::size_t page_z);
|
||||
/** aux init function: initialize @ref mlog_storage_[][] arenas **/
|
||||
void _init_mlogs(const X1CollectorConfig & cfg, std::size_t page_z);
|
||||
void _init_mlogs(std::size_t page_z);
|
||||
/** aux init function: initialize @ref space_storage_[][] arenas **/
|
||||
void _init_space(const X1CollectorConfig & cfg);
|
||||
|
||||
|
|
|
|||
38
include/xo/gc/MutationLogConfig.hpp
Normal file
38
include/xo/gc/MutationLogConfig.hpp
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/** @file MutationLogConfig.hpp
|
||||
*
|
||||
* @author Roland Conybeare, Apr 2026
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace mm {
|
||||
|
||||
class MutationLogConfig {
|
||||
public:
|
||||
MutationLogConfig(std::uint32_t ngen,
|
||||
std::size_t mlog_z,
|
||||
bool debug_flag);
|
||||
|
||||
public:
|
||||
/** number of generations in use.
|
||||
* Same as @ref X1CollectorConfig::n_generation_
|
||||
**/
|
||||
std::uint32_t n_generation_ = 0;
|
||||
|
||||
/** storage for xgen pointer bookkeeping (aka remembered sets).
|
||||
* Use 3x this value per generation
|
||||
**/
|
||||
std::size_t mutation_log_z_ = 1024;
|
||||
|
||||
/** true to enable debug logging **/
|
||||
bool debug_flag_ = false;
|
||||
};
|
||||
|
||||
} /*namespace mm*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end MutationLogConfig.hpp */
|
||||
|
|
@ -5,7 +5,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "MutationLogConfig.hpp"
|
||||
#include "X1CollectorConfig.hpp"
|
||||
#include "GCObjectStore.hpp"
|
||||
#include "MutationLogStatistics.hpp"
|
||||
#include "MutationLogEntry.hpp"
|
||||
#include <xo/arena/DArenaVector.hpp>
|
||||
|
|
@ -24,12 +26,12 @@ namespace xo {
|
|||
using size_type = DArena::size_type;
|
||||
|
||||
public:
|
||||
MutationLogState(uint32_t ngen, bool debug_flag);
|
||||
explicit MutationLogState(const MutationLogConfig & config);
|
||||
|
||||
/** Initialize mlog state for configuration @p cfg
|
||||
/** Initialize mlog state
|
||||
* with o/s page size @p page_z
|
||||
**/
|
||||
void init_mlogs(const X1CollectorConfig & cfg, std::size_t page_z);
|
||||
void init_mlogs(std::size_t page_z);
|
||||
|
||||
/** total number of active mlog entries (across all generations)
|
||||
**/
|
||||
|
|
@ -42,7 +44,7 @@ namespace xo {
|
|||
* (using gc to identify location of objects).
|
||||
* Update counters in @p *p_verify_stats.
|
||||
**/
|
||||
void verify_ok(DX1Collector * gc,
|
||||
void verify_ok(GCObjectStore * gc,
|
||||
VerifyStats * p_verify_stats) noexcept;
|
||||
|
||||
/** Append a single mutation to log for generation @p dest_g
|
||||
|
|
@ -67,7 +69,8 @@ namespace xo {
|
|||
void ** addr,
|
||||
obj<AGCObject> rhs);
|
||||
|
||||
/** swap {to, from} roles **/
|
||||
/** swap {to, from} roles
|
||||
**/
|
||||
void swap_roles(Generation upto) noexcept;
|
||||
|
||||
/** On behalf of collector @p gc:
|
||||
|
|
@ -135,10 +138,8 @@ namespace xo {
|
|||
|
||||
|
||||
public:
|
||||
/** number of generations in use. Same as @ref X1CollectorConfig::n_generation_ **/
|
||||
uint32_t n_generation_ = 0;
|
||||
/** true to enable debug logging **/
|
||||
bool debug_flag_ = false;
|
||||
/** configuration for mlog store **/
|
||||
MutationLogConfig config_;
|
||||
|
||||
/** Cross-generational mutations tracked in MutationLogs.
|
||||
* We need three logs per generation:
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ set(SELF_SRCS
|
|||
|
||||
X1CollectorConfig.cpp
|
||||
GCObjectStore.cpp
|
||||
|
||||
MutationLogConfig.cpp
|
||||
MutationLogState.cpp
|
||||
MutationLogEntry.cpp
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,11 @@ namespace xo {
|
|||
|
||||
DX1Collector::DX1Collector(const X1CollectorConfig & cfg)
|
||||
: config_{cfg},
|
||||
mlog_state_{cfg.n_generation_, cfg.debug_flag_},
|
||||
mlog_state_{
|
||||
MutationLogConfig{
|
||||
cfg.n_generation_,
|
||||
cfg.mutation_log_z_,
|
||||
cfg.debug_flag_}},
|
||||
gco_store_{cfg.arena_config_, cfg.n_generation_, cfg.debug_flag_}
|
||||
{
|
||||
assert(config_.arena_config_.header_.size_bits_ +
|
||||
|
|
@ -78,10 +82,7 @@ namespace xo {
|
|||
|
||||
this->_init_object_types(cfg, page_z);
|
||||
this->_init_gc_roots(cfg, page_z);
|
||||
this->_init_mlogs(cfg, page_z);
|
||||
#ifdef MOVED
|
||||
this->_init_space(cfg);
|
||||
#endif
|
||||
this->_init_mlogs(page_z);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -109,9 +110,9 @@ namespace xo {
|
|||
}
|
||||
|
||||
void
|
||||
DX1Collector::_init_mlogs(const X1CollectorConfig & cfg, std::size_t page_z)
|
||||
DX1Collector::_init_mlogs(std::size_t page_z)
|
||||
{
|
||||
this->mlog_state_.init_mlogs(cfg, page_z);
|
||||
this->mlog_state_.init_mlogs(page_z);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -145,7 +146,7 @@ namespace xo {
|
|||
DX1Collector::generation_of(role r, const void * addr) const noexcept
|
||||
{
|
||||
for (Generation gi{0}; gi < config_.n_generation_; ++gi) {
|
||||
const DArena * arena = get_space(r, gi);
|
||||
const DArena * arena = this->get_space(r, gi);
|
||||
|
||||
if (arena->contains(addr))
|
||||
return gi;
|
||||
|
|
@ -693,7 +694,7 @@ namespace xo {
|
|||
}
|
||||
|
||||
// 4. scan mutation logs
|
||||
mlog_state_.verify_ok(this,
|
||||
mlog_state_.verify_ok(&gco_store_,
|
||||
&(this->verify_stats_));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ namespace xo {
|
|||
void
|
||||
GCObjectStore::swap_roles(Generation upto) noexcept
|
||||
{
|
||||
scope log(XO_DEBUG(true), xtag("upto", upto));
|
||||
scope log(XO_DEBUG(debug_flag_), xtag("upto", upto));
|
||||
|
||||
for (Generation g = Generation{0}; g < upto; ++g) {
|
||||
log && log("swap roles", xtag("g", g));
|
||||
|
|
@ -88,7 +88,7 @@ namespace xo {
|
|||
GCObjectStore::cleanup_phase(Generation upto,
|
||||
bool sanitize_flag)
|
||||
{
|
||||
scope log(XO_DEBUG(true), xtag("upto", upto));
|
||||
scope log(XO_DEBUG(debug_flag_), xtag("upto", upto));
|
||||
|
||||
// everything live has been copied out of from-space
|
||||
// -> now set to empty
|
||||
|
|
|
|||
22
src/gc/MutationLogConfig.cpp
Normal file
22
src/gc/MutationLogConfig.cpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/** @file MutationLogConfig.cpp
|
||||
*
|
||||
* @author Roland Conybeare, Apr 2026
|
||||
**/
|
||||
|
||||
#include "MutationLogConfig.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace mm {
|
||||
|
||||
MutationLogConfig::MutationLogConfig(std::uint32_t ngen,
|
||||
std::size_t mlog_z,
|
||||
bool debug_flag)
|
||||
: n_generation_{ngen},
|
||||
mutation_log_z_{mlog_z},
|
||||
debug_flag_{debug_flag}
|
||||
{}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* end MutationLogConfig.cpp */
|
||||
|
|
@ -9,36 +9,43 @@
|
|||
namespace xo {
|
||||
namespace mm {
|
||||
|
||||
MutationLogState::MutationLogState(uint32_t ngen, bool debug_flag)
|
||||
: n_generation_{ngen}, debug_flag_{debug_flag}
|
||||
MutationLogState::MutationLogState(const MutationLogConfig & config)
|
||||
: config_{config}
|
||||
{}
|
||||
|
||||
void
|
||||
MutationLogState::init_mlogs(const X1CollectorConfig & cfg,
|
||||
std::size_t page_z)
|
||||
MutationLogState::init_mlogs(std::size_t page_z)
|
||||
{
|
||||
for (uint32_t igen = 0, ngen = cfg.n_generation_; igen + 1 < ngen; ++igen) {
|
||||
assert(c_n_role + 1 == 3);
|
||||
|
||||
for (uint32_t igen = 0, ngen = config_.n_generation_; igen + 1 < ngen; ++igen) {
|
||||
// special case: no use for mutation log for youngest generation,
|
||||
// so don't trouble to allocate one
|
||||
|
||||
if (igen + 1 < c_max_generation) {
|
||||
this->mlog_storage_[0][igen] = _make_mlog(igen, 'a', cfg.mutation_log_z_, page_z);
|
||||
this->mlog_storage_[1][igen] = _make_mlog(igen, 'b', cfg.mutation_log_z_, page_z);
|
||||
this->mlog_storage_[2][igen] = _make_mlog(igen, 'c', cfg.mutation_log_z_, page_z);
|
||||
std::array<char, 3> label_v{'a', 'b', 'c'};
|
||||
|
||||
this->mlog_[0][igen] = &mlog_storage_[0][igen];
|
||||
this->mlog_[1][igen] = &mlog_storage_[1][igen];
|
||||
this->mlog_[2][igen] = &mlog_storage_[2][igen];
|
||||
for (std::uint32_t mlog_role = 0; mlog_role < c_n_role + 1; ++mlog_role) {
|
||||
this->mlog_storage_[mlog_role][igen]
|
||||
= _make_mlog(igen,
|
||||
label_v[mlog_role],
|
||||
config_.mutation_log_z_,
|
||||
page_z);
|
||||
|
||||
this->mlog_[mlog_role][igen]
|
||||
= &(mlog_storage_[mlog_role][igen]);
|
||||
}
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg.n_generation_ > 0) {
|
||||
for (uint32_t igen = cfg.n_generation_ - 1; igen + 1 < c_max_generation; ++igen) {
|
||||
this->mlog_[0][igen] = nullptr;
|
||||
this->mlog_[1][igen] = nullptr;
|
||||
this->mlog_[2][igen] = nullptr;
|
||||
if (config_.n_generation_ > 0) {
|
||||
for (std::uint32_t igen = config_.n_generation_ - 1;
|
||||
igen + 1 < c_max_generation; ++igen) {
|
||||
|
||||
for (std::uint32_t mlog_role = 0; mlog_role < c_n_role + 1; ++mlog_role)
|
||||
this->mlog_[mlog_role][igen] = nullptr;
|
||||
}
|
||||
} else {
|
||||
assert(false);
|
||||
|
|
@ -63,7 +70,7 @@ namespace xo {
|
|||
{
|
||||
size_type z = 0;
|
||||
|
||||
for (Generation gj{0}; gj + 1 < n_generation_; ++gj) {
|
||||
for (Generation gj{0}; gj + 1 < config_.n_generation_; ++gj) {
|
||||
z += mlog_[role::to_space()][gj]->size();
|
||||
}
|
||||
|
||||
|
|
@ -73,7 +80,7 @@ namespace xo {
|
|||
void
|
||||
MutationLogState::visit_pools(const MemorySizeVisitor & visitor) const
|
||||
{
|
||||
for (uint32_t j = 0; j + 1 < n_generation_; ++j) {
|
||||
for (uint32_t j = 0; j + 1 < config_.n_generation_; ++j) {
|
||||
for (uint32_t i = 0; i < c_n_role + 1; ++i) {
|
||||
mlog_storage_[i][j].visit_pools(visitor);
|
||||
}
|
||||
|
|
@ -81,13 +88,13 @@ namespace xo {
|
|||
}
|
||||
|
||||
void
|
||||
MutationLogState::verify_ok(DX1Collector * gc,
|
||||
MutationLogState::verify_ok(GCObjectStore * gco_store,
|
||||
VerifyStats * p_verify_stats) noexcept
|
||||
{
|
||||
// 4. scan mutation logs
|
||||
for (Generation g(0); g + 1 < n_generation_; ++g) {
|
||||
const DArena * space = gc->get_space(role::to_space(), g);
|
||||
const DArena * from = gc->get_space(role::from_space(), g);
|
||||
for (Generation g(0); g + 1 < config_.n_generation_; ++g) {
|
||||
const DArena * space = gco_store->get_space(role::to_space(), g);
|
||||
const DArena * from = gco_store->get_space(role::from_space(), g);
|
||||
|
||||
// mutation log for generation g records *incoming* pointers
|
||||
// from more senior generations; includes objects from *this*
|
||||
|
|
@ -168,7 +175,9 @@ namespace xo {
|
|||
// on 1st iteration, for all generations:
|
||||
// - to_mlog, triage_mlog are empty
|
||||
|
||||
for (Generation child_gen{0}; child_gen + 2 < n_generation_; ++child_gen) {
|
||||
for (Generation child_gen{0};
|
||||
child_gen + 2 < config_.n_generation_;
|
||||
++child_gen) {
|
||||
|
||||
MutationLog * from_mlog = this->mlog_[role::from_space()][child_gen];
|
||||
|
||||
|
|
@ -196,7 +205,7 @@ namespace xo {
|
|||
} while (work > 0);
|
||||
|
||||
// here: reached fixpoints, any remaining triaged mlogs can be discarded
|
||||
for (Generation child_gen{0}; child_gen + 2 < n_generation_; ++child_gen) {
|
||||
for (Generation child_gen{0}; child_gen + 2 < config_.n_generation_; ++child_gen) {
|
||||
MutationLog * triage_mlog = this->mlog_[c_n_role][child_gen];
|
||||
|
||||
triage_mlog->clear();
|
||||
|
|
@ -211,7 +220,7 @@ namespace xo {
|
|||
MutationLog * keep_mlog,
|
||||
MutationLog * triage_mlog)
|
||||
{
|
||||
scope log(XO_DEBUG(debug_flag_),
|
||||
scope log(XO_DEBUG(config_.debug_flag_),
|
||||
xtag("child_gen", child_gen),
|
||||
xtag("mlog.size", from_mlog->size()));
|
||||
|
||||
|
|
@ -415,7 +424,7 @@ namespace xo {
|
|||
= gc->generation_of(role::to_space(), child_to);
|
||||
|
||||
bool need_mlog_entry
|
||||
= ((child_gen_to + 1 < n_generation_)
|
||||
= ((child_gen_to + 1 < config_.n_generation_)
|
||||
&& (gc->config().promotion_threshold(parent_gen_to)
|
||||
> gc->config().promotion_threshold(child_gen_to)));
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue