diff --git a/CMakeLists.txt b/CMakeLists.txt index 68b484b2..c5cfad97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,6 +116,7 @@ add_subdirectory(xo-expression) add_subdirectory(xo-pyexpression) add_subdirectory(xo-tokenizer) add_subdirectory(xo-reader) +add_subdirectory(xo-symboltable) add_subdirectory(xo-interpreter) add_subdirectory(xo-jit) add_subdirectory(xo-pyjit) diff --git a/xo-alloc/README.md b/xo-alloc/README.md index eeef6ca5..5a42f922 100644 --- a/xo-alloc/README.md +++ b/xo-alloc/README.md @@ -1,3 +1,16 @@ -# xo-alloc -- arena allocator with rudimentary GC support +# xo-alloc -- arena allocator and incremental garbage collector -Xo-alloc is a lightweight arena allocator +# Rules for writing garbage-collected classes. + +Topics +* allocation - allocate Objects (inheriting xo::Object) before owned scratch space. + Can relax this if/when abandon the bad-for-locality use of two pointers + into to-space to keep track of grey objects. Want to use stack anyway + so we can do depth-first search. +* destructors - can omit except for finalization +* assignment - MUST USE Object::assign_member() to assign pointers to gc-owned memory. + Only necessary for old->new pointers, so don't need to worry about this + for initialization. +* finalization - not supported (yet) + +- padding - use IAlloc::with_padding(z) for hand-allocated objects. diff --git a/xo-alloc/include/xo/alloc/Object.hpp b/xo-alloc/include/xo/alloc/Object.hpp index 81f0611c..a29b8de5 100644 --- a/xo-alloc/include/xo/alloc/Object.hpp +++ b/xo-alloc/include/xo/alloc/Object.hpp @@ -191,8 +191,6 @@ namespace xo { **/ virtual std::size_t _shallow_size() const = 0; - // TODO: _shallow_move() also overwrite *this with gc-only forwarding object point to C - /** if subject is allocated by GC: * - create copy C in to-space * - destination C will be nursery|tenured depending on location of this. diff --git a/xo-interpreter/include/xo/interpreter/Env.hpp b/xo-interpreter/include/xo/interpreter/Env.hpp new file mode 100644 index 00000000..947f19e9 --- /dev/null +++ b/xo-interpreter/include/xo/interpreter/Env.hpp @@ -0,0 +1,24 @@ +/** @file Env.hpp + * + * @author Roland Conybeare, Nov 2025 + **/ + +#pragma once + +#include "xo/alloc/Object.hpp" + +namespace xo { + namespace scm { + /** @class Env + * @brief runtime environment, holding variable bindings for schematika interpreter + * + * Garbage-collected + * + * TODO: rename xo-expression xo::scm::Environment -> xo::scm::SymbolTable + **/ + class Env : public Object { + public: + //gp lookup_symbol(xxx); + }; + } /*namespace scm*/ +} /*namespace xo*/ diff --git a/xo-interpreter/include/xo/interpreter/StackFrame.hpp b/xo-interpreter/include/xo/interpreter/StackFrame.hpp index 443a8b3a..0d1bf280 100644 --- a/xo-interpreter/include/xo/interpreter/StackFrame.hpp +++ b/xo-interpreter/include/xo/interpreter/StackFrame.hpp @@ -1,7 +1,7 @@ /** @file StackFrame.hpp **/ #include "xo/alloc/IAlloc.hpp" -#include "xo/alloc/Object.hpp" +#include "Env.hpp" #include #include @@ -45,19 +45,21 @@ namespace xo { * @ref StackFrame class * * memory layout: - * - * +-----------------------+ - * | vtable | + * ^ + * +-----------------------+ | + * | vtable | | + * +-----------------------+ | + * | .parent +------/ * +------------+----------+ * | .slot_v_ | .n_ | * | +----------+ * | | .v_ +------\ * +------------+----------+ <--/ - * | .v_[0] | + * | .v_[0] +---------> Object(1) * +-----------------------+ * . .. . * +-----------------------+ - * | .v_[.n_-1] | + * | .v_[.n_-1] +---------> Object(n) * +-----------------------+ **/ class StackFrame : public Object { @@ -65,16 +67,17 @@ namespace xo { using TaggedPtr = xo::reflect::TaggedPtr; public: - StackFrame(gc::IAlloc * mm, std::size_t n) : slot_v_{mm, n} {} + StackFrame(gc::IAlloc * mm, gp p, std::size_t n) : parent_{p}, slot_v_{mm, n} {} /** create frame using allocator @p mm, - * with exactly @p n_slot object pointers + * with parent @p p and exactly @p n_slot object pointers **/ - static gp make(gc::IAlloc * mm, std::size_t n_slot); + static gp make(gc::IAlloc * mm, gp p, std::size_t n_slot); /** reflect StackFrame object representation **/ static void reflect_self(); + gp parent() const { return parent_; } std::size_t size() const { return slot_v_.size(); } gp operator[](std::size_t i) const { return slot_v_[i]; } @@ -88,6 +91,8 @@ namespace xo { virtual std::size_t _forward_children() final override; private: + /** parent stack frame **/ + gp parent_; /** stack frame contents **/ CVector> slot_v_; }; diff --git a/xo-interpreter/src/interpreter/StackFrame.cpp b/xo-interpreter/src/interpreter/StackFrame.cpp index e0ecd828..f2777370 100644 --- a/xo-interpreter/src/interpreter/StackFrame.cpp +++ b/xo-interpreter/src/interpreter/StackFrame.cpp @@ -24,9 +24,9 @@ namespace xo { } gp - StackFrame::make(gc::IAlloc * mm, std::size_t n) + StackFrame::make(gc::IAlloc * mm, gp p, std::size_t n) { - return new (MMPtr(mm)) StackFrame(mm, n); + return new (MMPtr(mm)) StackFrame(mm, p, n); } TaggedPtr @@ -70,7 +70,7 @@ namespace xo { size_t z = size(); - StackFrame * copy = new (cpof) StackFrame(cpof.mm_, z); + StackFrame * copy = new (cpof) StackFrame(cpof.mm_, parent_, z); void * v_dest = copy->slot_v_.v_; @@ -90,6 +90,7 @@ namespace xo { std::size_t StackFrame::_forward_children() { + Object::_forward_inplace(parent_); for (std::size_t i = 0, n = slot_v_.size(); i < n; ++i) { Object::_forward_inplace((*this)[i]); } @@ -120,6 +121,7 @@ namespace xo { td1->assign_tdextra(Reflect::get_final_invoker(), std::move(tdx1)); + REFLECT_MEMBER(sr, parent); REFLECT_MEMBER(sr, slot_v); } } diff --git a/xo-interpreter/utest/StackFrame.test.cpp b/xo-interpreter/utest/StackFrame.test.cpp index b59cfd6d..1920d407 100644 --- a/xo-interpreter/utest/StackFrame.test.cpp +++ b/xo-interpreter/utest/StackFrame.test.cpp @@ -53,7 +53,7 @@ namespace xo { Object::mm = alloc.get(); std::size_t n = tc.contents_.size(); - gp frame = StackFrame::make(alloc.get(), n); + gp frame = StackFrame::make(alloc.get(), nullptr /*parent*/, n); TaggedPtr tp = frame->self_tp(); @@ -94,7 +94,7 @@ namespace xo { gc->add_gc_root(reinterpret_cast(&x)); REQUIRE(gc->tospace_generation_of(x.ptr()) == generation_result::nursery); - gp frame = StackFrame::make(gc.get(), n); + gp frame = StackFrame::make(gc.get(), nullptr /*parent*/, n); StackFrame ** frame_pp = frame.ptr_address(); gc->add_gc_root(reinterpret_cast(frame_pp)); diff --git a/xo-object/src/object/CMakeLists.txt b/xo-object/src/object/CMakeLists.txt index eee16738..a76cf4c9 100644 --- a/xo-object/src/object/CMakeLists.txt +++ b/xo-object/src/object/CMakeLists.txt @@ -12,4 +12,4 @@ xo_headeronly_dependency(${SELF_LIB} xo_reflectutil) xo_headeronly_dependency(${SELF_LIB} xo_unit) xo_headeronly_dependency(${SELF_LIB} callback) xo_dependency(${SELF_LIB} xo_alloc) -xo_dependency(${SELF_LIB} reflect) +#xo_dependency(${SELF_LIB} reflect) # should be able to get this indirectly via xo_alloc