diff --git a/include/xo/gc/X1CollectorConfig.hpp b/include/xo/gc/X1CollectorConfig.hpp index 4b889ef..a8681c1 100644 --- a/include/xo/gc/X1CollectorConfig.hpp +++ b/include/xo/gc/X1CollectorConfig.hpp @@ -24,8 +24,20 @@ namespace xo { **/ X1CollectorConfig with_name(std::string name); + /** copy of this config, + * but with @ref n_generation_ set to @p n_gen + **/ + X1CollectorConfig with_n_gen(uint32_t n_gen); + + /** copy of this config, + * but with @ref n_survive_ set to @p n_survive + **/ + X1CollectorConfig with_n_survive(uint32_t n_survive); + /** copy of this config, * but with @c arena_config_.size_ set to @p gen_z + * + * TODO: rename to with_halfspace_size() **/ X1CollectorConfig with_size(std::size_t gen_z); diff --git a/src/gc/GCObjectStore.cpp b/src/gc/GCObjectStore.cpp index 830fdb4..0dc5ed3 100644 --- a/src/gc/GCObjectStore.cpp +++ b/src/gc/GCObjectStore.cpp @@ -305,7 +305,7 @@ namespace xo { // could use c++ vector in scratch space instead of running on // boxed types. // - DArray * stats_v = DArray::empty(mm, object_types_.size()); + DArray * stats_v = DArray::_empty(mm, object_types_.size()); if (!stats_v) return false; @@ -346,7 +346,8 @@ namespace xo { recd->upsert_cstr(mm, "n-live", DInteger::box(mm, 0)); recd->upsert_cstr(mm, "bytes", DInteger::box(mm, 0)); - stats_v->assign_at(tseq.seqno(), obj(recd)); + stats_v->assign_at(mm.try_to_facet(), + tseq.seqno(), obj(recd)); } } @@ -385,13 +386,15 @@ namespace xo { stats_v->resize(max_tseq + 1); - DArray * final_stats_v = DArray::empty(mm, n_tseq_present); + DArray * final_stats_v = DArray::_empty(mm, n_tseq_present); for (std::size_t i = 0, n = stats_v->size(); i < n; ++i) { auto recd = stats_v->at(i); if (recd) { - bool ok = final_stats_v->push_back(recd); + obj gc = mm.try_to_facet(); + + bool ok = final_stats_v->push_back(gc, recd); assert(ok); } } @@ -433,7 +436,7 @@ namespace xo { } // stats, indexed by age - DArray * stats_v = DArray::empty(mm, soft_max_age + 1); + DArray * stats_v = DArray::_empty(mm, soft_max_age + 1); if (!stats_v) return false; @@ -448,7 +451,9 @@ namespace xo { recd->upsert_cstr(mm, "n-live", DInteger::box(mm, 0)); recd->upsert_cstr(mm, "bytes", DInteger::box(mm, 0)); - stats_v->push_back(obj(recd)); + obj gc = mm.try_to_facet(); + + stats_v->push_back(gc, obj(recd)); } log && log(xtag("soft_max_age", soft_max_age), diff --git a/src/gc/X1CollectorConfig.cpp b/src/gc/X1CollectorConfig.cpp index 812e276..c7781fb 100644 --- a/src/gc/X1CollectorConfig.cpp +++ b/src/gc/X1CollectorConfig.cpp @@ -16,6 +16,22 @@ namespace xo { return copy; } + X1CollectorConfig + X1CollectorConfig::with_n_gen(std::uint32_t n_gen) + { + X1CollectorConfig copy = *this; + copy.n_generation_ = n_gen; + return copy; + } + + X1CollectorConfig + X1CollectorConfig::with_n_survive(std::uint32_t n_survive) + { + X1CollectorConfig copy = *this; + copy.n_survive_threshold_ = n_survive; + return copy; + } + X1CollectorConfig X1CollectorConfig::with_size(std::size_t gen_z) { diff --git a/utest/Collector.test.cpp b/utest/Collector.test.cpp index 225a5ab..94baeb5 100644 --- a/utest/Collector.test.cpp +++ b/utest/Collector.test.cpp @@ -7,12 +7,15 @@ * see xo-object2/utest **/ -#include -#include "Collector.hpp" +//#include #include "random_allocs.hpp" -#include "detail/ICollector_DX1Collector.hpp" -#include "detail/IAllocator_DX1Collector.hpp" -//#include "gc/DX1Collector.hpp" +#include +#include +#include +#include +//#include "detail/ICollector_DX1Collector.hpp" +//#include "detail/IAllocator_DX1Collector.hpp" +#include #include #include #include @@ -21,10 +24,15 @@ #include namespace xo { + using xo::scm::DList; + using xo::scm::DArray; + using xo::scm::DInteger; using xo::mm::AAllocator; using xo::mm::ACollector; + using xo::mm::AGCObject; using xo::mm::X1CollectorConfig; using xo::mm::DX1Collector; + using xo::mm::Role; using xo::mm::ArenaConfig; using xo::mm::AllocHeaderConfig; using xo::mm::Generation; @@ -263,8 +271,163 @@ namespace xo { auto rng = rng::xoshiro256ss(seed); + // these are not gc-aware objects. + // just testing ability to work as a low-level allocator REQUIRE(utest::AllocUtil::random_allocs(25, false, &rng, x1alloc)); } + + namespace { + class Testcase { + public: + Testcase(uint32_t ng, uint32_t ns, size_t gcz, uint32_t otz, bool dbg_flag) + : n_gen_{ng}, + n_survive_{ns}, + gc_halfspace_z_{gcz}, + object_type_z_{otz}, + debug_flag_{dbg_flag} + {} + + public: + /** number of generations in gco store **/ + uint32_t n_gen_ = 0; + /** promote to next gen on surviving this number of gc cycles **/ + uint32_t n_survive_ = 0; + /** size of each generations' half-space, in bytes **/ + size_t gc_halfspace_z_ = 0; + /** storage for object type array, in bytes + * one 8-byte facet pointer per type + **/ + uint32_t object_type_z_; +#ifdef NOT_YET + /** size for error output arena **/ + size_t error_size_ = 0; +#endif + /** true to enable debug output for this test case **/ + bool debug_flag_ = false; + }; + + class X1Fixture { + public: + explicit X1Fixture(uint32_t i_tc, const Testcase & tc); + +#ifdef NOT_IN_USE + DArena error_arena_; +#endif + DX1Collector gc_; + }; + + X1Fixture::X1Fixture(uint32_t i_tc, const Testcase & tc) + : gc_(X1CollectorConfig() + .with_name("collector-x1-gc-" + std::to_string(i_tc)) + .with_n_gen(tc.n_gen_) + .with_n_survive(tc.n_survive_) + .with_size(tc.gc_halfspace_z_) + .with_debug_flag(tc.debug_flag_)) + {} + +# define nil nullptr +# define T true +# define F false + + static std::vector s_testcase_v = { + /** + * debug_flag + * object_type_z | + * gc_halfspace_z | | + * n_survive | | | + * n_gen | | | | + * v v v v v + **/ + Testcase(1, 2, 16 * 1024, 128, F), + }; + +# undef T +# undef F +# undef nil + } /*namespace*/ + + // full collector test. + TEST_CASE("collector-x1-gc", "[alloc2][gc]") + { + scope log(XO_DEBUG(true), + "DX1Collector gc test"); + + //std::uint64_t seed = 7988747704879432247ul; + //random_seed(&seed); + + for (size_t i_tc = 0, n_tc = s_testcase_v.size(); i_tc < n_tc; ++i_tc) { + // auto rgen = xoshiro256ss(seed + i_tc); + + const Testcase & tc = s_testcase_v[i_tc]; + + scope log1(XO_DEBUG(tc.debug_flag_), + "testcase loop", + xtag("i_tc", i_tc)); + + INFO(tostr(xtag("i_tc", i_tc), xtag("n_tc", n_tc))); + + X1Fixture fixture(i_tc, tc); + + auto & x1 = fixture.gc_; + + REQUIRE(x1.verify_ok()); + + auto mm = x1.ref(); + auto gc = mm.to_facet(); + Generation g1{1}; + { + auto roots = DArray::_empty(mm, 1)->ref(); + REQUIRE(mm->contains_allocated(Role::to_space(), roots.data())); + + gc.add_gc_root(&roots); + { + auto x1 = DInteger::box(mm, 42); + auto x1_gco = obj(x1); + auto l1 = DList::cons(mm, x1, DList::_nil()); + +#ifdef NOT_YET + REQUIRE(roots->push_back(l1)); + REQUIRE(mm->contains_allocated(Role::to_space(), x1.data())); + REQUIRE(mm->contains_allocated(Role::to_space(), l1.data())); + + gc->add_gc_root_poly(&(*roots.operator->())[0]); + + gc->request_gc(g1); // 1st GC + + // x1 target got moved, og locn now relabeled from-space + REQUIRE(mm->contains(Role::from_space(), x1.data())); + REQUIRE(!mm->contains_allocated(Role::from_space(), x1.data())); + // l1 target got moved, og locn now relabeled from-space + REQUIRE(mm->contains(Role::from_space(), l1.data())); + REQUIRE(!mm->contains_allocated(Role::from_space(), l1.data())); +#endif + } + REQUIRE(mm->contains_allocated(Role::to_space(), roots.data())); + } + } + +#ifdef NOT_YET + /* typed collector i/face */ + auto x1gc = with_facet::mkobj(&x1state); + /* typed allocator i/face */ + auto x1alloc = with_facet::mkobj(&x1state); + + REQUIRE(x1gc.iface()); + REQUIRE(x1gc.data()); + + REQUIRE(x1alloc.iface()); + REQUIRE(x1alloc.data()); + + rng::Seed seed; + log && log("ratio: seed=", seed); + + auto rng = rng::xoshiro256ss(seed); + + // these are not gc-aware objects. + // just testing ability to work as a low-level allocator + REQUIRE(utest::AllocUtil::random_allocs(25, false, &rng, x1alloc)); +#endif + } } } diff --git a/utest/init_gc_utest.cpp b/utest/init_gc_utest.cpp index f92c1f4..6aa39cc 100644 --- a/utest/init_gc_utest.cpp +++ b/utest/init_gc_utest.cpp @@ -12,7 +12,7 @@ namespace xo { using xo::mm::SetupGcUtest; using xo::facet::FacetRegistry; - using xo::reflect::typeseq; + //using xo::reflect::typeseq; bool SetupGcUtest::register_facets() @@ -33,7 +33,8 @@ namespace xo { } InitEvidence - InitSubsys::require() { + InitSubsys::require() + { InitEvidence retval; /* recursive subsystem deps for xo-gc/utest */