diff --git a/xo-alloc2/include/xo/alloc2/alloc/AAllocator.hpp b/xo-alloc2/include/xo/alloc2/alloc/AAllocator.hpp index 588b439b..4639d47e 100644 --- a/xo-alloc2/include/xo/alloc2/alloc/AAllocator.hpp +++ b/xo-alloc2/include/xo/alloc2/alloc/AAllocator.hpp @@ -62,6 +62,10 @@ namespace xo { /** RTTI: unique id# for actual runtime data representation **/ virtual typeseq _typeseq() const noexcept = 0; + /** destroy instance @p d. Calls c++ destructor for actual runtime type. + * does not recover memory. + **/ + virtual void _drop(Opaque d) const noexcept = 0; /** optional name for allocator @p d . * Allows labeling allocators, for diagnostics/instrumentation. **/ @@ -142,10 +146,12 @@ namespace xo { virtual value_type alloc_copy(Opaque d, value_type src) const = 0; /** reset allocator @p d to empty state. **/ virtual void clear(Opaque d) const = 0; +#ifdef OBSOLETE /** Destruct allocator @p d. * Releases allocator memory to operating system. **/ virtual void destruct_data(Opaque d) const = 0; +#endif ///@} }; /*AAllocator*/ diff --git a/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Any.hpp b/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Any.hpp index b45e7651..aac80bca 100644 --- a/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Any.hpp +++ b/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Any.hpp @@ -32,7 +32,10 @@ namespace xo { const AAllocator * iface() const { return std::launder(this); } // from AAllocator + + // builtin methods typeseq _typeseq() const noexcept override { return s_typeseq; } + void _drop(Opaque) const noexcept override { _fatal(); } // const methods [[noreturn]] std::string_view name(Copaque) const noexcept override { _fatal(); } @@ -55,7 +58,6 @@ namespace xo { [[noreturn]] value_type sub_alloc(Opaque, std::size_t, bool) const override { _fatal(); } [[noreturn]] value_type alloc_copy(Opaque, value_type) const override { _fatal(); } [[noreturn]] void clear(Opaque) const override { _fatal(); } - [[noreturn]] void destruct_data(Opaque) const override { _fatal(); } private: [[noreturn]] static void _fatal(); diff --git a/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Xfer.hpp b/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Xfer.hpp index 790bcdc0..e23d1470 100644 --- a/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Xfer.hpp +++ b/xo-alloc2/include/xo/alloc2/alloc/IAllocator_Xfer.hpp @@ -36,10 +36,14 @@ namespace xo { // from AAllocator - // const methods - + // builtin methods /** return typeseq for @tparam DRepr **/ typeseq _typeseq() const noexcept override { return s_typeseq; } + /** invoke native c++ dtor **/ + void _drop(Opaque d) const noexcept override { _dcast(d).~DRepr(); } + + // const methods + std::string_view name(Copaque d) const noexcept override { return I::name(_dcast(d)); } size_type reserved(Copaque d) const noexcept override { return I::reserved(_dcast(d)); } size_type size(Copaque d) const noexcept override { return I::size(_dcast(d)); } @@ -73,7 +77,6 @@ namespace xo { value_type alloc_copy(Opaque d, value_type src) const override { return I::alloc_copy(_dcast(d), src); } void clear(Opaque d) const override { return I::clear(_dcast(d)); } - void destruct_data(Opaque d) const override { return I::destruct_data(_dcast(d)); } ///@} private: diff --git a/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp b/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp index 2e9e7a80..c07b5e81 100644 --- a/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp +++ b/xo-alloc2/include/xo/alloc2/alloc/RAllocator.hpp @@ -29,6 +29,7 @@ namespace xo { RAllocator(Object::DataPtr data) : Object{std::move(data)} {} typeseq _typeseq() const noexcept { return O::iface()->_typeseq(); } + void _drop() const noexcept { O::iface()->_drop(O::data()); } std::string_view name() const noexcept { return O::iface()->name(O::data()); } size_type reserved() const noexcept { return O::iface()->reserved(O::data()); } size_type size() const noexcept { return O::iface()->size(O::data()); } diff --git a/xo-expression2/utest/X1Collector.test.cpp b/xo-expression2/utest/X1Collector.test.cpp index a664f9a2..b872d877 100644 --- a/xo-expression2/utest/X1Collector.test.cpp +++ b/xo-expression2/utest/X1Collector.test.cpp @@ -39,7 +39,7 @@ namespace ut { using xo::mm::ACollector; using xo::mm::AGCObject; using xo::mm::DX1Collector; - using xo::mm::CollectorConfig; + using xo::mm::X1CollectorConfig; using xo::mm::ArenaConfig; using xo::facet::with_facet; using xo::facet::typeseq; @@ -54,14 +54,13 @@ namespace ut { REQUIRE(s_init.evidence()); // Create collector - CollectorConfig cfg{ - .name_ = "x1_duniquestring_test", - .arena_config_ = ArenaConfig{ - .size_ = 8192, - .store_header_flag_ = true}, - .object_types_z_ = 16384, - .gc_trigger_v_{{1024, 1024}}, - .debug_flag_ = false, + X1CollectorConfig cfg{ .name_ = "x1_duniquestring_test", + .arena_config_ = ArenaConfig{ + .size_ = 8192, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{1024, 1024}}, + .debug_flag_ = false, }; DX1Collector gc(cfg); diff --git a/xo-facet/include/xo/facet/OUniqueBox.hpp b/xo-facet/include/xo/facet/OUniqueBox.hpp deleted file mode 100644 index d22ad70f..00000000 --- a/xo-facet/include/xo/facet/OUniqueBox.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/** @file OUniqueBox.hpp - * - * @author Roland Conybeare, Dec 2025 - **/ - -namespace xo { - namespace facet { - /** - * Uniquely-owned instance with runtime polymorphism. - * - * Reminder that in the facet object model we expect - * objects to be transient. - * - - * - * Unlike OUniqueBox can use for variant data - * without additional overhead. Tradeoff is that avoiding such - * overhead excludes std::unique_ptr. - * - * We're going to instead rely on AInterface providing a destruct_data() method, - * so in practice get the deleter from interface state. - * - * Possibly means we need all abstract interfaces to share a common base - * - * Remarks: - * - when @tparam Data is supplied - **/ - template - struct OUniqueBox { - using AbstractInterface = AInterface; - using ISpecific = ISpecificFor::ImplType; - /* note: Data can be void here */ - using DataType = Data; - using DataBox = Data*; - - explicit OUniqueBox() {} - /* unsatisfactory b/c doesn't enforce that @p d is heap-allocated */ - explicit OUniqueBox(DataBox d) : data_{std::move(d)} {} - - ~OUniqueBox() { - if (data_ != nullptr) { - this->iface()->destruct_data(data_); - delete data_; - this->data_ = nullptr; - } - } - - const AInterface * iface() const - requires std::is_same_v - { - return std::launder(&iface_); - } - - const AInterface * iface() const - requires (!std::is_same_v) - { - return &iface_; - } - - /** note: would prefer this to be constexpr, but not simple asof gcc 14.3 **/ - static bool _valid; - - /** note: load-bearing for routing classes such as RComplex **/ - Data * data() const { return data_; } - - ISpecific iface_; - DataBox data_ = nullptr; - }; - - - } -} /*namespace xo*/ - -/* end OUniqueBox.hpp */ diff --git a/xo-facet/include/xo/facet/box.hpp b/xo-facet/include/xo/facet/box.hpp new file mode 100644 index 00000000..25a6561e --- /dev/null +++ b/xo-facet/include/xo/facet/box.hpp @@ -0,0 +1,83 @@ +/** @file box.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "obj.hpp" + +namespace xo { + namespace facet { + + /** object with owned state + * - with default DRepr argument: + * type-erased container (runtime polymorphism). + * - with sepcific DRepr argument: + * typed container (comptime polymorphism). + **/ + template + struct box : public RoutingType> { + using Super = RoutingType>; + + box() : Super() {} + + /** box takes ownership of data @p *d; + * will destroy when box goes out of scope. + * + * Note this is not useful when DRepr=DVariablePlaceholder + **/ + explicit box(Super::DataPtr d) : Super(d) {} + + /** Adopt instance that has interface @p iface and (type-erased here) + * representation @p data + **/ + box(const AFacet * iface, void * data) + requires std::is_same_v + : Super(iface, data) + {} + + /** (copy ctor not supported -- ownership is unique) **/ + + // -------------------------------- + + /** Move constructor **/ + template + box(box && other) + requires (std::is_same_v + || std::is_same_v) + : obj() + { + /* replacing .iface_ along w/ .data_ */ + this->from_obj(other); + + other.reset_opaque(nullptr); + } + + /** explicit conversion to obj **/ + obj to_op() const noexcept { return obj(this->iface(), this->data()); } + + /** Take ownership from unowned object **/ + template + box & adopt(const obj & other) + requires (std::is_same_v + || std::is_same_v) + { + /* replace .iface_ along w/ .data_ */ + this->from_obj(other); + + return *this; + } + + ~box() { + auto p = this->data(); + this->_drop(); + ::operator delete(p); + } + }; + } /*namespace facet*/ + + using facet::box; +} /*namespace xo*/ + +/* end box.hpp */ diff --git a/xo-facet/include/xo/facet/obj.hpp b/xo-facet/include/xo/facet/obj.hpp index 3983cecf..850ef7bf 100644 --- a/xo-facet/include/xo/facet/obj.hpp +++ b/xo-facet/include/xo/facet/obj.hpp @@ -12,9 +12,9 @@ namespace xo { namespace facet { /** object with borrowed state pointer - * - With default Data argument: + * - With default DRepr argument: * type-erased polymorphic container - * - with specific Data argument: + * - with specific DRepr argument: * typed container. Trivially de-virtualizable * * Example: @@ -88,7 +88,7 @@ namespace xo { * - same strategy for holding state (naked / unique / refcounted ...) **/ template - obj(const obj && other) + obj(obj && other) requires (std::is_same_v || std::is_convertible_v) : Super() @@ -98,7 +98,7 @@ namespace xo { } obj & operator=(const obj & rhs) { - /* ensure we replace .iface_ along w/ .ata_ */ + /* ensure we replace .iface_ along w/ .data_ */ this->from_obj(rhs); return *this; } diff --git a/xo-gc/include/xo/gc/DX1Collector.hpp b/xo-gc/include/xo/gc/DX1Collector.hpp index 40c7f4f2..af41ae0d 100644 --- a/xo-gc/include/xo/gc/DX1Collector.hpp +++ b/xo-gc/include/xo/gc/DX1Collector.hpp @@ -5,6 +5,7 @@ #pragma once +#include "X1CollectorConfig.hpp" #include "GCObject.hpp" #include "generation.hpp" #include "object_age.hpp" @@ -40,104 +41,6 @@ namespace xo { }; #endif - struct CollectorConfig { - using size_type = std::size_t; - -#ifdef OBSOLETE // get from arena_config_.header_ - /* - * alloc header - * TTTTTTTTTTTTGGGGGZZZZZZZZZZZZ - * < tseq >< size > - * - * masking - * - * ..432107654321076543210 bit - * - * > < .gen_bits - * 0..............01111111 gen_mask_unshifted - * 0..011111110..........0 gen_mask_shifted - * > < gen_shift - */ - //constexpr std::uint64_t gen_mult() const; - constexpr std::uint64_t gen_shift() const; - constexpr std::uint64_t gen_mask_unshifted() const; - constexpr std::uint64_t gen_mask_shifted() const; - - //constexpr std::uint64_t tseq_mult() const; - constexpr std::uint64_t tseq_shift() const; - constexpr std::uint64_t tseq_mask_unshifted() const; - constexpr std::uint64_t tseq_mask_shifted() const; -#endif - - - /** copy of this config, - * with @c arena_config_.size_ set to @p gen_z - **/ - CollectorConfig with_size(std::size_t gen_z); - - generation age2gen(object_age age) const noexcept { - return generation(age % n_survive_threshold_); - } - - public: - // ----- Instance Variables ----- - - /** optional name, for diagnostics **/ - std::string name_; - - /** Configuration for collector spaces. - * Will have at least {nursery,tenured} x {from,to} spaces. - * Not using name_ member. - * - * REQUIRE: - * - arena_config_.store_header_flag_ must be true - **/ - ArenaConfig arena_config_; - - /** storage for N object types requires 8*N bytes **/ - std::size_t object_types_z_ = 2*1024*1024; - - /** storage for N object roots requires 8*N bytes **/ - std::size_t object_roots_z_ = 16*1024; - - /** number of bits to represent generation **/ - std::uint64_t gen_bits_ = 8; - - /** number of bits to represent tseq **/ - std::uint64_t tseq_bits_ = 24; - - /** Number of generations. - * Must be at least 2. - **/ - uint32_t n_generation_ = 2; - - /** Number of promotion steps. - * An object that survives this number of collections - * advances to the next generation. - **/ - uint32_t n_survive_threshold_ = 2; - - /** Trigger garbage collection when to-space allocation for - * generation g reaches gc_trigger_v_[g] - **/ - std::array gc_trigger_v_; - - /** true -> enable incremental collection. - * false -> only do full collection. - * - * Incremental collection requires mutation logs. - **/ - bool allow_incremental_gc_ = true; - - /** If non-zero remember statistics for - * the last @p stats_history_z_ collections. - **/ - uint32_t stats_history_z_ = false; - - /** true to enable debug logging **/ - bool debug_flag_ = false; - }; - // ----- GCRunState ----- /** @class GCRunState @@ -173,7 +76,7 @@ namespace xo { static constexpr size_t c_max_typeseq = 4096; /** Create X1 collector instance. **/ - explicit DX1Collector(const CollectorConfig & cfg); + explicit DX1Collector(const X1CollectorConfig & cfg); /** faceted object pointer to this instance */ template @@ -344,7 +247,7 @@ namespace xo { public: /** garbage collector configuration **/ - CollectorConfig config_; + X1CollectorConfig config_; /** current gc state **/ GCRunState runstate_; diff --git a/xo-gc/include/xo/gc/X1CollectorConfig.hpp b/xo-gc/include/xo/gc/X1CollectorConfig.hpp new file mode 100644 index 00000000..54296e2c --- /dev/null +++ b/xo-gc/include/xo/gc/X1CollectorConfig.hpp @@ -0,0 +1,92 @@ +/** @file X1CollectorConfig.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "object_age.hpp" +#include "generation.hpp" +#include +#include +#include + +namespace xo { + namespace mm { + struct X1CollectorConfig { + using size_type = std::size_t; + + /** copy of this config, + * with @c arena_config_.size_ set to @p gen_z + **/ + X1CollectorConfig with_size(std::size_t gen_z); + + generation age2gen(object_age age) const noexcept { + return generation(age % n_survive_threshold_); + } + + public: + // ----- Instance Variables ----- + + /** optional name, for diagnostics **/ + std::string name_; + + /** Configuration for collector spaces. + * Will have at least {nursery,tenured} x {from,to} spaces. + * Not using name_ member. + * + * REQUIRE: + * - arena_config_.store_header_flag_ must be true + **/ + ArenaConfig arena_config_; + + /** storage for N object types requires 8*N bytes **/ + std::size_t object_types_z_ = 2*1024*1024; + + /** storage for N object roots requires 8*N bytes **/ + std::size_t object_roots_z_ = 16*1024; + + /** number of bits to represent generation **/ + std::uint64_t gen_bits_ = 8; + + /** number of bits to represent tseq **/ + std::uint64_t tseq_bits_ = 24; + + /** Number of generations. + * Must be at least 2. + **/ + uint32_t n_generation_ = 2; + + /** Number of promotion steps. + * An object that survives this number of collections + * advances to the next generation. + **/ + uint32_t n_survive_threshold_ = 2; + + /** Trigger garbage collection when to-space allocation for + * generation g reaches gc_trigger_v_[g] + **/ + std::array gc_trigger_v_; + + /** true -> enable incremental collection. + * false -> only do full collection. + * + * Incremental collection requires mutation logs. + **/ + bool allow_incremental_gc_ = true; + + /** If non-zero remember statistics for + * the last @p stats_history_z_ collections. + **/ + uint32_t stats_history_z_ = false; + + /** true to enable debug logging **/ + bool debug_flag_ = false; + }; + + + } /*namespace mm*/ +} /*namespace xo*/ + +/* end X1CollectorConfig.hpp */ + diff --git a/xo-gc/src/gc/DX1Collector.cpp b/xo-gc/src/gc/DX1Collector.cpp index 3a77e15f..16bdedc3 100644 --- a/xo-gc/src/gc/DX1Collector.cpp +++ b/xo-gc/src/gc/DX1Collector.cpp @@ -25,24 +25,24 @@ namespace xo { namespace mm { - CollectorConfig - CollectorConfig::with_size(std::size_t gen_z) + X1CollectorConfig + X1CollectorConfig::with_size(std::size_t gen_z) { - CollectorConfig copy = *this; + X1CollectorConfig copy = *this; copy.arena_config_ = arena_config_.with_size(gen_z); return copy; } #ifdef NOT_USING constexpr std::uint64_t - CollectorConfig::gen_mult() const { + X1CollectorConfig::gen_mult() const { return 1ul << arena_config_.header_size_bits_; } #endif #ifdef NOT_USING constexpr std::uint64_t - CollectorConfig::tseq_mult() const { + X1CollectorConfig::tseq_mult() const { return 1ul << (gen_bits_ + arena_config_.header_size_bits_); } #endif @@ -69,7 +69,7 @@ namespace xo { using size_type = xo::mm::DX1Collector::size_type; - DX1Collector::DX1Collector(const CollectorConfig & cfg) : config_{cfg} + DX1Collector::DX1Collector(const X1CollectorConfig & cfg) : config_{cfg} { assert(config_.arena_config_.header_.size_bits_ + config_.arena_config_.header_.age_bits_ + diff --git a/xo-gc/utest/Collector.test.cpp b/xo-gc/utest/Collector.test.cpp index f322c286..318c9c21 100644 --- a/xo-gc/utest/Collector.test.cpp +++ b/xo-gc/utest/Collector.test.cpp @@ -23,7 +23,7 @@ namespace xo { using xo::mm::AAllocator; using xo::mm::ACollector; - using xo::mm::CollectorConfig; + using xo::mm::X1CollectorConfig; using xo::mm::DX1Collector; using xo::mm::ArenaConfig; using xo::mm::AllocHeaderConfig; @@ -61,12 +61,12 @@ namespace xo { 0 /*tseq_bits*/, 0 /*age_bits*/, 16 /*size_bits*/), }; - CollectorConfig cfg = { .arena_config_ = arena_cfg, - .n_generation_ = 2, - .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}} }; + X1CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 2, + .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; DX1Collector gc = DX1Collector{cfg}; @@ -109,12 +109,12 @@ namespace xo { 0 /*tseq_bits*/, 0 /*age_bits*/, 16 /*size_bits*/), }; - CollectorConfig cfg = { .arena_config_ = arena_cfg, - .n_generation_ = 2, - .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}} }; + X1CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 2, + .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; DX1Collector gc = DX1Collector{cfg}; @@ -135,12 +135,12 @@ namespace xo { 0 /*tseq-bits*/, 0 /*age-bits*/, 16 /*size-bits*/), }; - CollectorConfig cfg = { .arena_config_ = arena_cfg, - .n_generation_ = 2, - .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}} }; + X1CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 2, + .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; DX1Collector gc = DX1Collector{cfg}; @@ -165,12 +165,12 @@ namespace xo { 16 /*size-bits*/), }; /* collector with one generation collapses to a non-generational copying collector */ - CollectorConfig cfg = { .arena_config_ = arena_cfg, - .n_generation_ = 1, - .gc_trigger_v_ = {{64*1024, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}} }; + X1CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 1, + .gc_trigger_v_ = {{64*1024, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; DX1Collector x1state = DX1Collector{cfg}; @@ -209,12 +209,12 @@ namespace xo { }; /* collector with one generation collapses to a non-generational copying collector */ - CollectorConfig cfg = { .arena_config_ = arena_cfg, - .n_generation_ = 1, - .gc_trigger_v_ = {{64*1024, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}} }; + X1CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 1, + .gc_trigger_v_ = {{64*1024, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; /* X1 allocator+collector */ DX1Collector x1state = DX1Collector{cfg}; diff --git a/xo-gc/utest/DX1CollectorIterator.test.cpp b/xo-gc/utest/DX1CollectorIterator.test.cpp index 99347fad..314eb4a8 100644 --- a/xo-gc/utest/DX1CollectorIterator.test.cpp +++ b/xo-gc/utest/DX1CollectorIterator.test.cpp @@ -24,7 +24,7 @@ namespace xo { using xo::mm::DX1CollectorIterator; using xo::mm::DArena; using xo::mm::DArenaIterator; - using xo::mm::CollectorConfig; + using xo::mm::X1CollectorConfig; using xo::mm::ArenaConfig; using xo::mm::AllocHeaderConfig; using xo::mm::cmpresult; @@ -51,12 +51,12 @@ namespace xo { 0 /*tseq_bits*/, 0 /*age_bits*/, 16 /*size_bits*/), }; - CollectorConfig cfg = { .arena_config_ = arena_cfg, - .n_generation_ = 2, - .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}} }; + X1CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 2, + .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; DX1Collector gc = DX1Collector{cfg}; @@ -94,12 +94,12 @@ namespace xo { 0 /*tseq_bits*/, 0 /*age_bits*/, 16 /*size_bits*/), }; - CollectorConfig cfg = { .arena_config_ = arena_cfg, - .n_generation_ = 2, - .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}} }; + X1CollectorConfig cfg = { .arena_config_ = arena_cfg, + .n_generation_ = 2, + .gc_trigger_v_ = {{64*1024, 1024*1024, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}} }; DX1Collector gc = DX1Collector{cfg}; obj a1o{&gc}; diff --git a/xo-interpreter2/CMakeLists.txt b/xo-interpreter2/CMakeLists.txt index ac944a36..466e1a1c 100644 --- a/xo-interpreter2/CMakeLists.txt +++ b/xo-interpreter2/CMakeLists.txt @@ -21,7 +21,7 @@ add_definitions(${PROJECT_CXX_FLAGS}) # output targets add_subdirectory(src/interpreter2) -#add_subdirectory(utest) +add_subdirectory(utest) xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets) diff --git a/xo-interpreter2/include/xo/interpreter2/VirtualSchematikaMachine.hpp b/xo-interpreter2/include/xo/interpreter2/VirtualSchematikaMachine.hpp index 0f58f2c4..6e1595da 100644 --- a/xo-interpreter2/include/xo/interpreter2/VirtualSchematikaMachine.hpp +++ b/xo-interpreter2/include/xo/interpreter2/VirtualSchematikaMachine.hpp @@ -5,9 +5,12 @@ #pragma once +#include "VsmConfig.hpp" #include "VsmInstr.hpp" +#include #include #include +#include namespace xo { namespace scm { @@ -18,10 +21,11 @@ namespace xo { public: // will be DArenaVector> probably using Stack = void *; + using AAllocator = xo::mm::AAllocator; using AGCObject = xo::mm::AGCObject; public: - VirtualSchematikaMachine(); + VirtualSchematikaMachine(const VsmConfig & config); /** borrow calling thread to run indefinitely, * until halt instruction @@ -93,6 +97,14 @@ namespace xo { * value_ */ + /** configuration **/ + VsmConfig config_; + + box mm_; + + /** reader: text -> expression **/ + SchematikaReader reader_; + /** program counter **/ VsmInstr pc_ = VsmInstr::halt(); diff --git a/xo-interpreter2/include/xo/interpreter2/VsmConfig.hpp b/xo-interpreter2/include/xo/interpreter2/VsmConfig.hpp new file mode 100644 index 00000000..5071c020 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/VsmConfig.hpp @@ -0,0 +1,28 @@ +/** @file VsmConfig.hpp +* + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include +#include + +namespace xo { + namespace scm { + /** Configuration for virtual schematika machine + **/ + struct VsmConfig { + using X1CollectorConfig = xo::mm::X1CollectorConfig; + + /** reader configuration **/ + ReaderConfig rdr_config_; + /** Configuration for allocator/collector. + * TODO: may want to make CollectorConfig polymorphic + **/ + X1CollectorConfig x1_config_ = X1CollectorConfig().with_size(4*1024*1024); + }; + } /*namespace scm*/ +} /*namespace xo*/ + +/* end VsmConfig.hpp */ diff --git a/xo-interpreter2/include/xo/interpreter2/init_interpreter2.hpp b/xo-interpreter2/include/xo/interpreter2/init_interpreter2.hpp new file mode 100644 index 00000000..87e93438 --- /dev/null +++ b/xo-interpreter2/include/xo/interpreter2/init_interpreter2.hpp @@ -0,0 +1,21 @@ +/** @file init_interpreter2.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include + +namespace xo { + /* tag to represent the xo-interpreter2/ subsystem within ordered initialization */ + enum S_interpreter2_tag {}; + + template <> + struct InitSubsys { + static void init(); + static InitEvidence require(); + }; +} /*namespace xo*/ + +/* end init_interpreter2.hpp */ diff --git a/xo-interpreter2/src/interpreter2/CMakeLists.txt b/xo-interpreter2/src/interpreter2/CMakeLists.txt index 15d06fdf..7d9cd250 100644 --- a/xo-interpreter2/src/interpreter2/CMakeLists.txt +++ b/xo-interpreter2/src/interpreter2/CMakeLists.txt @@ -2,6 +2,7 @@ set(SELF_LIB xo_interpreter2) set(SELF_SRCS + init_interpreter2.cpp VirtualSchematikaMachine.cpp #IExpression_Any.cpp #interpreter2_register_facets.cpp @@ -9,7 +10,7 @@ set(SELF_SRCS xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) # note: deps here must also appear in cmake/xo_interpreter2Config.cmake.in -xo_dependency(${SELF_LIB} xo_expression2) +xo_dependency(${SELF_LIB} xo_reader2) xo_dependency(${SELF_LIB} xo_gc) #xo_dependency(${SELF_LIB} reflect) #xo_dependency(${SELF_LIB} xo_printable2) diff --git a/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp b/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp index 02ed023a..f7e8259e 100644 --- a/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp +++ b/xo-interpreter2/src/interpreter2/VirtualSchematikaMachine.cpp @@ -6,12 +6,19 @@ #include "VirtualSchematikaMachine.hpp" #include #include +#include +#include #include namespace xo { + using xo::mm::DX1Collector; + namespace scm { - VirtualSchematikaMachine::VirtualSchematikaMachine() + VirtualSchematikaMachine::VirtualSchematikaMachine(const VsmConfig & config) + : config_{config}, + mm_(box(new DX1Collector(config.x1_config_))), + reader_{config.rdr_config_, mm_.to_op()} {} void diff --git a/xo-interpreter2/src/interpreter2/init_interpreter2.cpp b/xo-interpreter2/src/interpreter2/init_interpreter2.cpp new file mode 100644 index 00000000..b0e8a71c --- /dev/null +++ b/xo-interpreter2/src/interpreter2/init_interpreter2.cpp @@ -0,0 +1,50 @@ +/** @file init_interpreter2.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include "init_interpreter2.hpp" + +#ifdef NOT_YET +#include "interpreter2_register_facets.hpp" +#include "interpreter2_register_types.hpp" +#endif + +#include +#ifdef NOT_YET +#include +#endif + +namespace xo { +#ifdef NOT_YET + using xo::scm::interpreter2_register_facets; + using xo::scm::interpreter2_register_types; + using xo::mm::CollectorTypeRegistry; +#endif + + void + InitSubsys::init() + { +#ifdef NOT_YET + interpreter2_register_facets(); + + CollectorTypeRegistry::instance().register_types(&interpreter2_register_types); +#endif + } + + InitEvidence + InitSubsys::require() + { + InitEvidence retval; + + /* direct subsystem deps for xo-interpreter2/ */ + retval ^= InitSubsys::require(); + + /* xo-interpreter2/'s own initialization code */ + retval ^= Subsystem::provide("interpreter2", &init); + + return retval; + } +} /*namespace xo*/ + +/* end init_interpreter2.cpp */ diff --git a/xo-interpreter2/utest/CMakeLists.txt b/xo-interpreter2/utest/CMakeLists.txt new file mode 100644 index 00000000..e45cffaa --- /dev/null +++ b/xo-interpreter2/utest/CMakeLists.txt @@ -0,0 +1,11 @@ +# build unittest xo-interpreter2/utest + +set(UTEST_EXE utest.interpreter2) +set(UTEST_SRCS + interpreter2_utest_main.cpp + VirtualSchematikaMachine.test.cpp +) + +xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS}) +xo_self_dependency(${UTEST_EXE} xo_interpreter2) +xo_external_target_dependency(${UTEST_EXE} Catch2 Catch2::Catch2) diff --git a/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp b/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp new file mode 100644 index 00000000..29301b1f --- /dev/null +++ b/xo-interpreter2/utest/VirtualSchematikaMachine.test.cpp @@ -0,0 +1,63 @@ +/** @file VirtualSchematikaMachine.test.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include + +#ifdef NOT_YET +#include +#include +#include +#include +#include +#endif +#include +#ifdef NOT_YET +#include +#endif + +#include + +namespace xo { +#ifdef NOT_YET + using xo::scm::SchematikaParser; + using xo::scm::ASyntaxStateMachine; + using xo::scm::syntaxstatetype; +// using xo::scm::DDefineSsm; + using xo::scm::DExpectExprSsm; +// using xo::scm::defexprstatetype; + //using xo::scm::ParserResult; + //using xo::scm::parser_result_type; + using xo::scm::Token; + using xo::scm::DString; + using xo::mm::ArenaConfig; + using xo::mm::AAllocator; + using xo::mm::DArena; + using xo::facet::with_facet; +#endif + + static InitEvidence s_init = (InitSubsys::require()); + + namespace ut { + TEST_CASE("VirtualSchematikaMachine-ctor", "[interpreter2][VSM]") + { +#ifdef NOT_YET + ArenaConfig config; + config.name_ = "test-arena"; + config.size_ = 16 * 1024; + + DArena expr_arena = DArena::map(config); + obj expr_alloc = with_facet::mkobj(&expr_arena); + + SchematikaParser parser(config, 4096, expr_alloc, false /*debug_flag*/); + + REQUIRE(parser.debug_flag() == false); + REQUIRE(parser.is_at_toplevel() == true); +#endif + } + + } /*namespace ut*/ +} /*namespace xo*/ + +/* end SchematikaParser.test.cpp */ diff --git a/xo-interpreter2/utest/interpreter2_utest_main.cpp b/xo-interpreter2/utest/interpreter2_utest_main.cpp new file mode 100644 index 00000000..addc079a --- /dev/null +++ b/xo-interpreter2/utest/interpreter2_utest_main.cpp @@ -0,0 +1,27 @@ +/** @file interpreter2_utest_main.cpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#include + +#define CATCH_CONFIG_RUNNER +#include "catch2/catch.hpp" + +int +main(int argc, char* argv[]) +{ + using xo::Subsystem; + + // initialize subsystems + Subsystem::initialize_all(); + + // Run Catch2's test session + int result = Catch::Session().run(argc, argv); + + // cleanup here, if any + + return result; +} + +/* end interpreter2_utest_main.cpp */ diff --git a/xo-object2/utest/Printable.test.cpp b/xo-object2/utest/Printable.test.cpp index 6c09ca90..64736d22 100644 --- a/xo-object2/utest/Printable.test.cpp +++ b/xo-object2/utest/Printable.test.cpp @@ -44,7 +44,7 @@ namespace ut { using xo::mm::ACollector; using xo::mm::AGCObject; using xo::mm::DX1Collector; - using xo::mm::CollectorConfig; + using xo::mm::X1CollectorConfig; using xo::mm::ArenaConfig; using xo::print::APrintable; using xo::facet::FacetRegistry; @@ -99,15 +99,14 @@ namespace ut { try { const testcase_pp & tc = s_testcase_v[i_tc]; - CollectorConfig cfg{ - .name_ = "pp_test", - .arena_config_ = ArenaConfig{ - .size_ = tc.gc_gen_size_, - .store_header_flag_ = true}, - .object_types_z_ = 16384, - .gc_trigger_v_{{tc.gc_trigger_threshold_, - tc.gc_trigger_threshold_}}, - .debug_flag_ = c_debug_flag + X1CollectorConfig cfg{ .name_ = "pp_test", + .arena_config_ = ArenaConfig{ + .size_ = tc.gc_gen_size_, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{tc.gc_trigger_threshold_, + tc.gc_trigger_threshold_}}, + .debug_flag_ = c_debug_flag }; DX1Collector gc(cfg); diff --git a/xo-object2/utest/X1Collector.test.cpp b/xo-object2/utest/X1Collector.test.cpp index 0f20e68a..90122c25 100644 --- a/xo-object2/utest/X1Collector.test.cpp +++ b/xo-object2/utest/X1Collector.test.cpp @@ -48,7 +48,7 @@ namespace ut { using xo::mm::AGCObject; using xo::mm::DX1Collector; using xo::mm::DArena; - using xo::mm::CollectorConfig; + using xo::mm::X1CollectorConfig; using xo::mm::ArenaConfig; using xo::mm::generation; using xo::mm::role; @@ -108,16 +108,15 @@ namespace ut { try { const testcase_x1 & tc = s_testcase_v[i_tc]; - CollectorConfig cfg{ - .name_ = "x1_test", - .arena_config_ = ArenaConfig{ - .size_ = tc.tenured_z_, - .store_header_flag_ = true}, - .object_types_z_ = 16384, - .gc_trigger_v_{{ - tc.incr_gc_threshold_, - tc.full_gc_threshold_}}, - .debug_flag_ = c_debug_flag, + X1CollectorConfig cfg{ .name_ = "x1_test", + .arena_config_ = ArenaConfig{ + .size_ = tc.tenured_z_, + .store_header_flag_ = true}, + .object_types_z_ = 16384, + .gc_trigger_v_{{ + tc.incr_gc_threshold_, + tc.full_gc_threshold_}}, + .debug_flag_ = c_debug_flag, }; DX1Collector gc(cfg); diff --git a/xo-reader2/example/readerreplxx/readerreplxx.cpp b/xo-reader2/example/readerreplxx/readerreplxx.cpp index 122b2730..c95dd101 100644 --- a/xo-reader2/example/readerreplxx/readerreplxx.cpp +++ b/xo-reader2/example/readerreplxx/readerreplxx.cpp @@ -136,7 +136,7 @@ namespace { struct AppConfig { using ReaderConfig = xo::scm::ReaderConfig; - using CollectorConfig = xo::mm::CollectorConfig; + using X1CollectorConfig = xo::mm::X1CollectorConfig; AppConfig() { rdr_config_.reader_debug_flag_ = true; @@ -146,17 +146,17 @@ struct AppConfig { std::size_t max_history_size_ = 1000; std::string repl_history_fname_ = "repl_history.txt";; - CollectorConfig x1_config_ = (CollectorConfig().with_size(4*1024*1024)); ReaderConfig rdr_config_; + X1CollectorConfig x1_config_ = (X1CollectorConfig().with_size(4*1024*1024)); }; struct AppContext { using DX1Collector = xo::mm::DX1Collector; - using CollectorConfig = xo::mm::CollectorConfig; + using X1CollectorConfig = xo::mm::X1CollectorConfig; using Replxx = replxx::Replxx; AppContext(const AppConfig & cfg = AppConfig()) : config_{cfg}, - x1_{CollectorConfig().with_size(4*1024*1024)}, + x1_{X1CollectorConfig().with_size(4*1024*1024)}, rdr_{config_.rdr_config_, x1_.ref()} { rx_.set_max_history_size(config_.max_history_size_);