From 2191eec0f867138d46147d312fef50f032dca550 Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Sun, 15 Feb 2026 14:13:38 -0500 Subject: [PATCH] xo-interpreter2 stack: plumbing for aux_mm and use opportunistically --- .../interpreter2/VirtualSchematikaMachine.hpp | 22 +- include/xo/interpreter2/VsmConfig.hpp | 15 +- src/interpreter2/VirtualSchematikaMachine.cpp | 26 +-- utest/VirtualSchematikaMachine.test.cpp | 211 ++++++++---------- 4 files changed, 133 insertions(+), 141 deletions(-) diff --git a/include/xo/interpreter2/VirtualSchematikaMachine.hpp b/include/xo/interpreter2/VirtualSchematikaMachine.hpp index b809a09d..2cbd08e4 100644 --- a/include/xo/interpreter2/VirtualSchematikaMachine.hpp +++ b/include/xo/interpreter2/VirtualSchematikaMachine.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include namespace xo { namespace scm { @@ -74,7 +74,12 @@ namespace xo { using span_type = xo::mm::span; public: - VirtualSchematikaMachine(const VsmConfig & config); + /** @p config. configuration + * @p aux_mm. Allocator for miscellaneous dataN + * owned by this VSM. + **/ + VirtualSchematikaMachine(const VsmConfig & config, + obj aux_mm); /** allocator for schematika data **/ obj allocator() const noexcept; @@ -213,10 +218,17 @@ namespace xo { /** configuration **/ VsmConfig config_; +#ifdef NOT_YET + /** allocator (likely DArena) for globals. + * For example DArenaHashMap in global symtab, + **/ + obj aux_mm_; +#endif + /** allocator (likely DX1Collector or similar) for * expressions and values **/ - box mm_; + abox mm_; /** Sidecar allocator for error reporting. * Separate to mitigate interference with @ref mm_ @@ -224,12 +236,12 @@ namespace xo { * an out-of-memory error). * Likely DArena or similar **/ - box error_mm_; + abox error_mm_; /** runtime context for this vsm. * For example, provides allocator to primitives **/ - box rcx_; + abox rcx_; // consider separate allocator (which _may_ turn out to be the same) // for VM stack. Only works for code that doesn't rely on fancy diff --git a/include/xo/interpreter2/VsmConfig.hpp b/include/xo/interpreter2/VsmConfig.hpp index f05ac449..bfbe152e 100644 --- a/include/xo/interpreter2/VsmConfig.hpp +++ b/include/xo/interpreter2/VsmConfig.hpp @@ -19,15 +19,28 @@ namespace xo { VsmConfig() = default; + VsmConfig with_debug_flag(bool x) const { + VsmConfig retval = *this; + retval.debug_flag_ = x; + return retval; + } + /** true for interactive parser session; false for batch session **/ bool interactive_flag_ = true; + /** true to enable logging **/ + bool debug_flag_ = false; + /** 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); + X1CollectorConfig x1_config_ = X1CollectorConfig().with_name("gc").with_size(4*1024*1024); + /** Configuration for handful of non-moveable high-level objects + * e.g. DArenaHashMap in global symtab + **/ + ArenaConfig fixed_config_ = ArenaConfig().with_name("fixed").with_size(4*1024); /** Configuration for error allocator * TODO: may want to make ArenaConfig polymorphic **/ diff --git a/src/interpreter2/VirtualSchematikaMachine.cpp b/src/interpreter2/VirtualSchematikaMachine.cpp index f3473681..5c2d2c57 100644 --- a/src/interpreter2/VirtualSchematikaMachine.cpp +++ b/src/interpreter2/VirtualSchematikaMachine.cpp @@ -54,16 +54,16 @@ namespace xo { // NOTE: using heap here for {DX1Collector, DArena, DVsmRcx} instances // (though DX1Collector allocations will be from explictly mmap'd memory) // - VirtualSchematikaMachine::VirtualSchematikaMachine(const VsmConfig & config) + VirtualSchematikaMachine::VirtualSchematikaMachine(const VsmConfig & config, + obj aux_mm) : config_{config}, - mm_(box(new DX1Collector(config.x1_config_))), - rcx_(box(new DVsmRcx(this))), - reader_{config.rdr_config_, mm_.to_op()} + mm_(abox::make(aux_mm, config.x1_config_)), + rcx_(abox::make(aux_mm, this)), + reader_{config.rdr_config_, mm_.to_op(), aux_mm} { { - DArena * arena = new DArena(); + DArena * arena = new DArena(config_.error_config_); assert(arena); - *arena = DArena::map(config_.error_config_); error_mm_.adopt(obj(arena)); } @@ -165,7 +165,7 @@ namespace xo { bool VirtualSchematikaMachine::execute_one() { - scope log(XO_DEBUG(true)); + scope log(XO_DEBUG(config_.debug_flag_)); log && log(xtag("pc", pc_), xtag("cont", cont_)); @@ -333,10 +333,10 @@ namespace xo { // for now: halt VSM execution // TODO: some combination of - // 1. emit stack trace + // 1. emit stack trace // 2. go to debugger // 3. have every vsm instruction check inputs for errors - + this->pc_ = VsmInstr::c_halt; } @@ -396,7 +396,7 @@ namespace xo { // control: // self -> eval(test) -> ifelse_cont -> eval(when_true) // -> eval(when_false) - + auto ifelse_expr = obj::from(expr_); obj ifelse_frame @@ -433,7 +433,7 @@ namespace xo { return; } - auto seqexpr_frame + auto seqexpr_frame = obj (DVsmSeqContFrame::make(mm_.to_op(), this->stack_ /*saved stack*/, @@ -693,10 +693,10 @@ namespace xo { // for now: halt VSM execution // TODO: some combination of - // 1. emit stack trace + // 1. emit stack trace // 2. go to debugger // 3. have every vsm instruction check inputs for errors - + this->pc_ = VsmInstr::c_halt; } } diff --git a/utest/VirtualSchematikaMachine.test.cpp b/utest/VirtualSchematikaMachine.test.cpp index eb62267e..1a50c555 100644 --- a/utest/VirtualSchematikaMachine.test.cpp +++ b/utest/VirtualSchematikaMachine.test.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #ifdef NOT_YET #include @@ -37,61 +38,80 @@ namespace xo { using xo::scm::DRuntimeError; using xo::mm::AGCObject; using xo::mm::MemorySizeInfo; + using xo::mm::AAllocator; + using xo::mm::DArena; + using xo::mm::ArenaConfig; using xo::facet::FacetRegistry; using span_type = xo::scm::VirtualSchematikaMachine::span_type; using Catch::Matchers::WithinAbs; -#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 using std::cout; using std::endl; static InitEvidence s_init = (InitSubsys::require()); namespace ut { + struct ArenaShim { + explicit ArenaShim(const std::string & name, std::size_t size = 16*1024) + : arena_(ArenaConfig().with_name(name).with_size(size)) + { + } + + obj to_op() { return obj(&arena_); } + + DArena arena_; + }; + + struct VsmFixture { + explicit VsmFixture(const std::string & testname, + bool debug_flag, + const VsmConfig & cfg = VsmConfig()) + : aux_mm_{testname}, + vsm_{cfg.with_debug_flag(debug_flag), aux_mm_.to_op()} + {} + + bool log_memory_layout(scope * p_log) { + auto visitor = [p_log](const MemorySizeInfo & info) { + *p_log && (*p_log)(xtag("resource", info.resource_name_), + xtag("used", info.used_), + xtag("alloc", info.allocated_), + xtag("commit", info.committed_), + xtag("resv", info.reserved_)); + }; + + aux_mm_.arena_.visit_pools(visitor); + FacetRegistry::instance().visit_pools(visitor); + vsm_.visit_pools(visitor); + + return true; + } + + ArenaShim aux_mm_; + VirtualSchematikaMachine vsm_; + }; + TEST_CASE("VirtualSchematikaMachine-ctor", "[interpreter2][VSM]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - scope log(XO_DEBUG(true), xtag("test", testname)); + bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } TEST_CASE("VirtualSchematikaMachine-const1", "[interpreter2][VSM]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - scope log(XO_DEBUG(true), xtag("test", testname)); + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); + + auto & vsm = vsm_fixture.vsm_; bool eof_flag = false; @@ -109,26 +129,19 @@ namespace xo { REQUIRE(res.remaining_.size() == 1); REQUIRE(*res.remaining_.lo() == '\n'); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } TEST_CASE("VirtualSchematikaMachine-const2", "[interpreter2][VSM]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - scope log(XO_DEBUG(true), xtag("test", testname)); + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); + + auto & vsm = vsm_fixture.vsm_; bool eof_flag = false; @@ -148,26 +161,18 @@ namespace xo { REQUIRE(res.remaining_.size() == 1); REQUIRE(*res.remaining_.lo() == '\n'); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } TEST_CASE("VirtualSchematikaMachine-arith1", "[interpreter2][VSM]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - scope log(XO_DEBUG(true), xtag("test", testname)); + constexpr bool c_debug_flag = false; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; bool eof_flag = false; @@ -187,16 +192,7 @@ namespace xo { REQUIRE(res.remaining_.size() == 1); REQUIRE(*res.remaining_.lo() == '\n'); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } TEST_CASE("VirtualSchematikaMachine-cmp1", "[interpreter2][VSM]") @@ -206,13 +202,15 @@ namespace xo { constexpr bool c_debug_flag = false; scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; bool eof_flag = false; vsm.begin_interactive_session(); - VsmResultExt res = vsm.read_eval_print(span_type::from_cstr("123 == 123;"), eof_flag); + VsmResultExt res + = vsm.read_eval_print(span_type::from_cstr("123 == 123;"), + eof_flag); REQUIRE(res.is_value()); REQUIRE(res.value()); @@ -227,32 +225,25 @@ namespace xo { REQUIRE(res.remaining_.size() == 1); REQUIRE(*res.remaining_.lo() == '\n'); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } TEST_CASE("VirtualSchematikaMachine-if", "[interpreter2][VSM]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - constexpr bool c_debug_flag = true; + constexpr bool c_debug_flag = false; scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; bool eof_flag = false; vsm.begin_interactive_session(); - VsmResultExt res = vsm.read_eval_print(span_type::from_cstr("if 123 == 123 then \"equal\" else \"notequal\";"), eof_flag); + VsmResultExt res + = vsm.read_eval_print(span_type::from_cstr("if 123 == 123 then \"equal\" else \"notequal\";"), + eof_flag); REQUIRE(res.is_value()); REQUIRE(res.value()); @@ -267,16 +258,7 @@ namespace xo { REQUIRE(res.remaining_.size() == 1); REQUIRE(*res.remaining_.lo() == '\n'); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } TEST_CASE("VirtualSchematikaMachine-lambda1", "[interpreter2][VSM]") @@ -286,13 +268,15 @@ namespace xo { constexpr bool c_debug_flag = false; scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; bool eof_flag = false; vsm.begin_interactive_session(); - VsmResultExt res = vsm.read_eval_print(span_type::from_cstr("lambda (x : i64) -> i64 { x * x; }"), eof_flag); + VsmResultExt res + = vsm.read_eval_print(span_type::from_cstr("lambda (x : i64) -> i64 { x * x; }"), + eof_flag); REQUIRE(res.is_value()); REQUIRE(res.value()); @@ -307,26 +291,18 @@ namespace xo { REQUIRE(res.remaining_.size() == 1); REQUIRE(*res.remaining_.lo() == '\n'); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } TEST_CASE("VirtualSchematikaMachine-apply2", "[interpreter2][VSM]") { const auto & testname = Catch::getResultCapture().getCurrentTestName(); - scope log(XO_DEBUG(false), xtag("test", testname)); + bool c_debug_flag = true; + scope log(XO_DEBUG(c_debug_flag), xtag("test", testname)); - VsmConfig cfg; - VirtualSchematikaMachine vsm(cfg); + VsmFixture vsm_fixture(testname, c_debug_flag); + auto & vsm = vsm_fixture.vsm_; bool eof_flag = false; @@ -341,7 +317,7 @@ namespace xo { log && log(xtag("res.tseq", res.value()->_typeseq())); - // currently get not-implemented error + // currently get not-implemented error auto x = obj::from(*res.value()); REQUIRE(x); @@ -354,16 +330,7 @@ namespace xo { REQUIRE(res.remaining_.size() == 1); REQUIRE(*res.remaining_.lo() == '\n'); - auto visitor = [&log](const MemorySizeInfo & info) { - log && log(xtag("resource", info.resource_name_), - xtag("used", info.used_), - xtag("alloc", info.allocated_), - xtag("commit", info.committed_), - xtag("resv", info.reserved_)); - }; - - FacetRegistry::instance().visit_pools(visitor); - vsm.visit_pools(visitor); + log && vsm_fixture.log_memory_layout(&log); } } /*namespace ut*/