xo-gc: + execute_gc() scaffold
This commit is contained in:
parent
44a096c6f7
commit
e0cb07c9f5
9 changed files with 112 additions and 6 deletions
|
|
@ -221,6 +221,22 @@ namespace xo {
|
|||
**/
|
||||
bool install_type(const AGCObject & meta) noexcept;
|
||||
|
||||
/** add GC root at @p root_addr, with type @p typeseq **/
|
||||
void add_gc_root(typeseq tseq, Opaque * root_addr) noexcept;
|
||||
|
||||
/** Request immediate collection.
|
||||
* 1. if collection is enabled, immediately collect all generations
|
||||
* up to (but not including) g
|
||||
* 2. may nevertheless escalate to older generations,
|
||||
* depending on collector state.
|
||||
* 3. if collection is currently disabled,
|
||||
* collection will trigger the next time gc is enabled.
|
||||
**/
|
||||
void request_gc(generation upto) noexcept;
|
||||
|
||||
/** Execute gc immediately, for all generations < @p upto **/
|
||||
void execute_gc(generation upto) noexcept;
|
||||
|
||||
// ----- allocation -----
|
||||
|
||||
/** simple allocation. allocate @p z bytes of memory
|
||||
|
|
@ -269,6 +285,12 @@ namespace xo {
|
|||
/** discard all allocated memory **/
|
||||
void clear() noexcept;
|
||||
|
||||
private:
|
||||
/** swap from- and to- roles for all generations < @p upto **/
|
||||
void swap_roles(generation upto) noexcept;
|
||||
/** copy roots + everything reachable from them, to to-space **/
|
||||
void copy_roots(generation upto) noexcept;
|
||||
|
||||
public:
|
||||
/** garbage collector configuration **/
|
||||
CollectorConfig config_;
|
||||
|
|
@ -281,6 +303,11 @@ namespace xo {
|
|||
**/
|
||||
DArena object_types_;
|
||||
|
||||
/** gc disabled whenever gc_blocked_ > 0 **/
|
||||
uint32_t gc_blocked_ = 0;
|
||||
/** if > 0: need gc for all generations < gc_pending_upto_ **/
|
||||
generation gc_pending_upto_;
|
||||
|
||||
/** collector-managed memory here.
|
||||
* - space_[1] is from-space
|
||||
* - space_[0] is to-space
|
||||
|
|
|
|||
|
|
@ -59,6 +59,16 @@ namespace xo {
|
|||
virtual bool install_type(Opaque d, const AGCObject & iface) = 0;
|
||||
virtual void add_gc_root(Opaque d, int32_t tseq, Opaque * root) = 0;
|
||||
|
||||
/** Request immediate collection.
|
||||
* 1. if collection is enabled, immediately collect all generations
|
||||
* up to (but not including) g
|
||||
* 2. may nevertheless escalate to older generations,
|
||||
* depending on collector state.
|
||||
* 3. if collection is currently disabled,
|
||||
* collection will trigger the next time gc is enabled.
|
||||
**/
|
||||
virtual void request_gc(Opaque d, generation upto) = 0;
|
||||
|
||||
/** evacuate @p *lhs, that refers to state with interface @p lhs_iface,
|
||||
* to collector @p d's to-space. Replace *lhs_data with forwarding pointer
|
||||
*
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ namespace xo {
|
|||
// non-const methods
|
||||
[[noreturn]] bool install_type(Opaque, const AGCObject &) noexcept override { _fatal(); }
|
||||
[[noreturn]] void add_gc_root(Opaque, int32_t, Opaque *) override { _fatal(); }
|
||||
[[noreturn]] void request_gc(Opaque, generation) override { _fatal(); }
|
||||
[[noreturn]] void forward_inplace(Opaque, AGCObject *, void **) override { _fatal(); }
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ namespace xo {
|
|||
|
||||
static bool install_type(DX1Collector & d, const AGCObject & iface);
|
||||
static void add_gc_root(DX1Collector & d, int32_t tseq, Opaque * root);
|
||||
static void request_gc(DX1Collector & d, generation upto);
|
||||
static void forward_inplace(DX1Collector & d, AGCObject * lhs_iface, void ** lhs_data);
|
||||
|
||||
static int32_t s_typeseq;
|
||||
|
|
|
|||
|
|
@ -53,7 +53,11 @@ namespace xo {
|
|||
void add_gc_root(Opaque d, int32_t tseq, Opaque * root) override {
|
||||
I::add_gc_root(_dcast(d), tseq, root);
|
||||
}
|
||||
void forward_inplace(Opaque d, AGCObject * lhs_iface, void ** lhs_data) override {
|
||||
void request_gc(Opaque d, generation upto) override {
|
||||
I::request_gc(_dcast(d), upto);
|
||||
}
|
||||
void forward_inplace(Opaque d,
|
||||
AGCObject * lhs_iface, void ** lhs_data) override {
|
||||
I::forward_inplace(_dcast(d), lhs_iface, lhs_data);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace xo {
|
|||
|
||||
bool install_type(const AGCObject & iface) { return O::iface()->install_type(O::data(), iface); }
|
||||
void add_gc_root(int32_t tseq, Opaque * root) { O::iface()->add_gc_root(O::data(), tseq, root); }
|
||||
|
||||
void request_gc(generation g) { O::iface()->request_gc(O::data(), g); }
|
||||
void forward_inplace(AGCObject * lhs_iface, void ** lhs_data) { O::iface()->forward_inplace(O::data(), lhs_iface, lhs_data); }
|
||||
|
||||
static bool _valid;
|
||||
|
|
|
|||
|
|
@ -228,6 +228,65 @@ namespace xo {
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DX1Collector::add_gc_root(typeseq tseq,
|
||||
Opaque * root) noexcept
|
||||
{
|
||||
(void)tseq;
|
||||
(void)root;
|
||||
}
|
||||
|
||||
void
|
||||
DX1Collector::request_gc(generation upto) noexcept
|
||||
{
|
||||
if (gc_blocked_ > 0) {
|
||||
if (gc_pending_upto_ < upto) {
|
||||
this->gc_pending_upto_ = upto;
|
||||
}
|
||||
|
||||
/* intend collecting later */
|
||||
} else {
|
||||
this->execute_gc(upto);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DX1Collector::execute_gc(generation upto) noexcept
|
||||
{
|
||||
scope log(XO_DEBUG(true), xtag("upto", upto));
|
||||
|
||||
//auto t0 = std::chrono::steady_clock::now();
|
||||
|
||||
log && log("step 0a : [STUB] snapshot alloc state");
|
||||
|
||||
log && log("step 0b : [STUB] scan for object statistics");
|
||||
|
||||
log && log("step 1 : swap from/to roles");
|
||||
this->swap_roles(upto);
|
||||
|
||||
log && log("step 2a : copy roots");
|
||||
this->copy_roots(upto);
|
||||
|
||||
log && log("step 2b : [STUB] copy pinned");
|
||||
log && log("step 3a : [STUB] run destructors");
|
||||
log && log("step 3b : [STUB] keep reachable weak pointers");
|
||||
log && log("step 4 : [STUB] cleanup");
|
||||
}
|
||||
|
||||
void
|
||||
DX1Collector::swap_roles(generation upto) noexcept
|
||||
{
|
||||
for (generation g = generation{0}; g < upto; ++g) {
|
||||
std::swap(space_[role::to_space()][g], space_[role::from_space()][g]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DX1Collector::copy_roots(generation upto) noexcept
|
||||
{
|
||||
scope log(XO_DEBUG(true), "STUB", xtag("upto", upto));
|
||||
}
|
||||
|
||||
auto
|
||||
DX1Collector::alloc(typeseq t, size_type z) noexcept -> value_type
|
||||
{
|
||||
|
|
|
|||
|
|
@ -65,11 +65,14 @@ namespace xo {
|
|||
int32_t tseq,
|
||||
Opaque * root)
|
||||
{
|
||||
(void)d;
|
||||
(void)tseq;
|
||||
(void)root;
|
||||
d.add_gc_root(typeseq(tseq), root);
|
||||
}
|
||||
|
||||
assert(false);
|
||||
void
|
||||
ICollector_DX1Collector::request_gc(DX1Collector & d,
|
||||
generation upto)
|
||||
{
|
||||
d.request_gc(upto);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ namespace ut {
|
|||
}
|
||||
|
||||
/* no GC roots, so GC is trivial */
|
||||
c_o.request_gc(generation{1});
|
||||
} catch (std::exception & ex) {
|
||||
std::cerr << "caught exception: " << ex.what() << std::endl;
|
||||
REQUIRE(false);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue