xo-interpreter adds + explict mm arg to ctors (retiring Object::mm)
This commit is contained in:
parent
bfee0bdf9b
commit
f3e7330d92
38 changed files with 664 additions and 103 deletions
|
|
@ -116,6 +116,7 @@ add_subdirectory(xo-expression)
|
|||
add_subdirectory(xo-pyexpression)
|
||||
add_subdirectory(xo-tokenizer)
|
||||
add_subdirectory(xo-reader)
|
||||
add_subdirectory(xo-interpreter)
|
||||
add_subdirectory(xo-jit)
|
||||
add_subdirectory(xo-pyjit)
|
||||
#
|
||||
|
|
@ -124,6 +125,6 @@ add_subdirectory(xo-imgui)
|
|||
# ----------------------------------------------------------------
|
||||
# documentation. must follow add_subdirectory() for satellite projects
|
||||
|
||||
xo_umbrella_doxygen_deps(xo_alloc indentlog xo_flatstring xo_ratio xo_unit xo_tokenizer xo_reader xo_jit)
|
||||
xo_umbrella_doxygen_deps(xo_alloc indentlog xo_flatstring xo_ratio xo_unit xo_tokenizer xo_reader xo_interpreter xo_jit)
|
||||
xo_umbrella_doxygen_config()
|
||||
xo_umbrella_sphinx_config(index.rst docs/install.rst docs/glossary.rst)
|
||||
|
|
|
|||
|
|
@ -177,15 +177,31 @@ To setup a unit test coverage build/ccov/all-merged
|
|||
|
||||
Then run unit tests
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ (cd .build && ctest)
|
||||
|
||||
To build coverage report
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ (.build/gen-ccov)
|
||||
|
||||
Html report in ``.build/ccov/html/index.html``
|
||||
|
||||
|
||||
Address Sanitizer Setup
|
||||
-----------------------
|
||||
|
||||
To run address sanitizer
|
||||
|
||||
.. code-block::
|
||||
|
||||
# can reuse phase 1 cmake-macros-install
|
||||
|
||||
# phase 2
|
||||
$ cmake -B .build -S . -DCMAKE_INSTALL_PREFIX=$PREFIX -DCMAKE_BUILD_TYPE=asan
|
||||
|
||||
Sphinx Autobuild Setup
|
||||
----------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ namespace xo {
|
|||
bool allow_incremental_gc_ = true;
|
||||
/** true to report statistics **/
|
||||
bool stats_flag_ = false;
|
||||
/** true to capture per-type object statistics **/
|
||||
bool object_stats_flag_ = false;
|
||||
/** remember basic gc statistics for this many GC's; separately for incremental + full GCs **/
|
||||
std::size_t stats_history_z_ = 256;
|
||||
/** true to enable debug logging **/
|
||||
|
|
|
|||
|
|
@ -258,8 +258,9 @@ namespace xo {
|
|||
**/
|
||||
class Cpof {
|
||||
public:
|
||||
explicit Cpof(const Object * src) : src_{src} {}
|
||||
explicit Cpof(gc::IAlloc * mm, const Object * src) : mm_{mm}, src_{src} {}
|
||||
|
||||
gc::IAlloc * mm_ = nullptr;
|
||||
const void * src_ = nullptr;
|
||||
};
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
|
|
@ -26,6 +26,11 @@ namespace xo {
|
|||
|
||||
void * base = mmap(nullptr, z, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
log && log("acquired memory [lo,hi) using mmap",
|
||||
xtag("lo", base),
|
||||
xtag("z", z),
|
||||
xtag("hi", reinterpret_cast<std::byte *>(base) + z));
|
||||
|
||||
// could use this as fallback..
|
||||
//base = (new std::byte [z]);
|
||||
|
||||
|
|
@ -39,7 +44,7 @@ namespace xo {
|
|||
this->checkpoint_ = lo_;
|
||||
this->free_ptr_ = lo_;
|
||||
this->limit_ = lo_ + z;
|
||||
this->hi_ = limit_;
|
||||
this->hi_ = lo_ + z;
|
||||
this->debug_flag_ = debug_flag;
|
||||
|
||||
if (!lo_) {
|
||||
|
|
@ -52,13 +57,16 @@ namespace xo {
|
|||
|
||||
ArenaAlloc::~ArenaAlloc()
|
||||
{
|
||||
scope log(XO_DEBUG(debug_flag_));
|
||||
|
||||
// hygiene..
|
||||
|
||||
if (lo_) {
|
||||
log && log("unmap [lo,hi)", xtag("lo", lo_), xtag("z", hi_ - lo_), xtag("hi", hi_));
|
||||
|
||||
munmap(lo_, hi_ - lo_);
|
||||
}
|
||||
// could use this as fallback if not using uncommitted technique
|
||||
// could use this as fallback if we dropped the uncommitted technique
|
||||
//delete [] this->lo_;
|
||||
|
||||
this->lo_ = nullptr;
|
||||
|
|
@ -94,26 +102,41 @@ namespace xo {
|
|||
}
|
||||
|
||||
bool
|
||||
ArenaAlloc::expand(size_t offset_z) {
|
||||
ArenaAlloc::expand(size_t offset_z)
|
||||
{
|
||||
scope log(XO_DEBUG(debug_flag_), xtag("offset_z", offset_z), xtag("committed_z", committed_z_));
|
||||
|
||||
if (offset_z <= committed_z_)
|
||||
if (offset_z <= committed_z_) {
|
||||
log && log("trivial success, offset within committed range",
|
||||
xtag("offset_z", offset_z),
|
||||
xtag("committed_z", committed_z_));
|
||||
return true;
|
||||
|
||||
std::size_t align_offset_z = align_lub(offset_z, page_z_);
|
||||
std::byte * commit_start = lo_ + committed_z_;
|
||||
std::size_t new_commit_z = align_offset_z - committed_z_;
|
||||
|
||||
log && log(xtag("align_offset_z", align_offset_z),
|
||||
xtag("new_commit_z", new_commit_z));
|
||||
|
||||
if (mprotect(commit_start, new_commit_z, PROT_READ | PROT_WRITE) != 0) {
|
||||
throw std::runtime_error(tostr("ArenaAlloc::expand: commit failure",
|
||||
xtag("committed_z", committed_z_),
|
||||
xtag("new_commit_z", new_commit_z)));
|
||||
}
|
||||
|
||||
this->committed_z_ = align_offset_z;
|
||||
if (lo_ + offset_z > limit_) {
|
||||
throw std::runtime_error(tostr("ArenaAlloc::expand: requested size exceeds reserved size",
|
||||
xtag("requested", offset_z), xtag("reserved", reserved())));
|
||||
}
|
||||
|
||||
std::size_t aligned_offset_z = align_lub(offset_z, page_z_);
|
||||
std::byte * commit_start = lo_ + committed_z_;
|
||||
std::size_t add_commit_z = aligned_offset_z - committed_z_;
|
||||
|
||||
log && log(xtag("aligned_offset_z", aligned_offset_z),
|
||||
xtag("add_commit_z", add_commit_z));
|
||||
|
||||
log && log("expand committed range",
|
||||
xtag("commit_start", commit_start),
|
||||
xtag("add_commit_z", add_commit_z),
|
||||
xtag("commit_end", commit_start + add_commit_z));
|
||||
|
||||
if (mprotect(commit_start, add_commit_z, PROT_READ | PROT_WRITE) != 0) {
|
||||
throw std::runtime_error(tostr("ArenaAlloc::expand: commit failure",
|
||||
xtag("committed_z", committed_z_),
|
||||
xtag("add_commit_z", add_commit_z)));
|
||||
}
|
||||
|
||||
this->committed_z_ = aligned_offset_z;
|
||||
this->limit_ = this->lo_ + committed_z_;
|
||||
|
||||
return true;
|
||||
|
|
@ -167,6 +190,8 @@ namespace xo {
|
|||
std::byte * p = lo_;
|
||||
|
||||
while (p < free_ptr_) {
|
||||
log && log(xtag("p", (void *)p));
|
||||
|
||||
Object * obj = reinterpret_cast<Object *>(p);
|
||||
TaggedPtr tp = obj->self_tp();
|
||||
std::size_t z = obj->_shallow_size();
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ set(SELF_SRCS
|
|||
|
||||
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
|
||||
# xo-unit used for time measurement
|
||||
xo_dependency(${SELF_LIB} xo_unit)
|
||||
xo_headeronly_dependency(${SELF_LIB} xo_unit)
|
||||
xo_dependency(${SELF_LIB} indentlog)
|
||||
xo_dependency(${SELF_LIB} reflect)
|
||||
xo_dependency(${SELF_LIB} callback)
|
||||
xo_headeronly_dependency(${SELF_LIB} callback)
|
||||
|
||||
#end CMakeLists.txt
|
||||
|
|
|
|||
|
|
@ -66,16 +66,36 @@ namespace xo {
|
|||
std::size_t nursery_size = config.initial_nursery_z_;
|
||||
std::size_t tenured_size = config.initial_tenured_z_;
|
||||
|
||||
nursery_[role2int(role::from_space)]
|
||||
if (config_.incr_gc_threshold_ > nursery_size) {
|
||||
throw std::runtime_error(tostr("GC::ctor: expected nursery gc threshold < nursery size",
|
||||
xtag("nursery-gc-threshold", config_.incr_gc_threshold_),
|
||||
xtag("nursery-size", nursery_size)));
|
||||
}
|
||||
|
||||
if (nursery_size + config_.full_gc_threshold_ > tenured_size) {
|
||||
throw std::runtime_error(tostr("GC::ctor: expected nursery size + tennured gc threshold < tenured size",
|
||||
xtag("nursery-size", nursery_size),
|
||||
xtag("tenured-size", tenured_size),
|
||||
xtag("full-gc-threshold", config_.full_gc_threshold_)
|
||||
));
|
||||
}
|
||||
|
||||
if (config_.incr_gc_threshold_ > nursery_size)
|
||||
this->config_.incr_gc_threshold_ = nursery_size;
|
||||
|
||||
if (config_.full_gc_threshold_ > tenured_size)
|
||||
this->config_.full_gc_threshold_ = tenured_size;
|
||||
|
||||
this->nursery_[role2int(role::from_space)]
|
||||
= ArenaAlloc::make("NA", nursery_size, config.debug_flag_);
|
||||
|
||||
nursery_[role2int(role::to_space) ]
|
||||
this->nursery_[role2int(role::to_space) ]
|
||||
= ArenaAlloc::make("NB", nursery_size, config.debug_flag_);
|
||||
|
||||
tenured_[role2int(role::from_space)]
|
||||
this->tenured_[role2int(role::from_space)]
|
||||
= ArenaAlloc::make("TA", tenured_size, config.debug_flag_);
|
||||
|
||||
tenured_[role2int(role::to_space) ]
|
||||
this->tenured_[role2int(role::to_space) ]
|
||||
= ArenaAlloc::make("TB", tenured_size, config.debug_flag_);
|
||||
|
||||
nursery_[role2int(role::from_space)]->expand(config.incr_gc_threshold_);
|
||||
|
|
@ -83,9 +103,9 @@ namespace xo {
|
|||
tenured_[role2int(role::from_space)]->expand(config.full_gc_threshold_);
|
||||
tenured_[role2int(role::to_space) ]->expand(config.full_gc_threshold_);
|
||||
|
||||
mutation_log_[role2int(role::from_space)] = std::make_unique<MutationLog>();
|
||||
mutation_log_[role2int(role::to_space )] = std::make_unique<MutationLog>();
|
||||
defer_mutation_log_ = std::make_unique<MutationLog>();
|
||||
this->mutation_log_[role2int(role::from_space)] = std::make_unique<MutationLog>();
|
||||
this->mutation_log_[role2int(role::to_space )] = std::make_unique<MutationLog>();
|
||||
this->defer_mutation_log_ = std::make_unique<MutationLog>();
|
||||
|
||||
this->gc_history_ = CircularBuffer<GcStatisticsHistoryItem>(config.stats_history_z_);
|
||||
|
||||
|
|
@ -96,23 +116,25 @@ namespace xo {
|
|||
/* hygiene */
|
||||
this->clear();
|
||||
|
||||
nursery_[role2int(role::from_space)].reset();
|
||||
nursery_[role2int(role::to_space) ].reset();
|
||||
this->nursery_[role2int(role::from_space)].reset();
|
||||
this->nursery_[role2int(role::to_space) ].reset();
|
||||
|
||||
tenured_[role2int(role::from_space)].reset();
|
||||
tenured_[role2int(role::to_space) ].reset();
|
||||
this->tenured_[role2int(role::from_space)].reset();
|
||||
this->tenured_[role2int(role::to_space) ].reset();
|
||||
|
||||
mutation_log_[role2int(role::from_space)].reset();
|
||||
mutation_log_[role2int(role::to_space) ].reset();
|
||||
defer_mutation_log_.reset();
|
||||
this->gc_root_v_.clear();
|
||||
|
||||
this->mutation_log_[role2int(role::from_space)].reset();
|
||||
this->mutation_log_[role2int(role::to_space) ].reset();
|
||||
this->defer_mutation_log_.reset();
|
||||
}
|
||||
|
||||
up<GC>
|
||||
GC::make(const Config & config)
|
||||
{
|
||||
GC * gc = new GC(config);
|
||||
//GC * gc = new GC(config);
|
||||
|
||||
return up<GC>{gc};
|
||||
return std::make_unique<GC>(config);
|
||||
}
|
||||
|
||||
const std::string &
|
||||
|
|
@ -608,6 +630,7 @@ namespace xo {
|
|||
void
|
||||
GC::capture_object_statistics(generation upto, capture_phase phase)
|
||||
{
|
||||
if (config_.object_stats_flag_) {
|
||||
/* scan nursery */
|
||||
this->nursery_[role2int(role::to_space)]->capture_object_statistics
|
||||
(phase,
|
||||
|
|
@ -620,6 +643,7 @@ namespace xo {
|
|||
&object_statistics_sab_[gen2int(generation::tenured)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GC::copy_object(Object ** pp_object, generation upto, ObjectStatistics * object_stats)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ operator new (std::size_t z, const xo::Cpof & cpof)
|
|||
{
|
||||
using xo::gc::GC;
|
||||
|
||||
GC * gc = reinterpret_cast<GC *>(xo::Object::mm);
|
||||
GC * gc = reinterpret_cast<GC *>(cpof.mm_);
|
||||
|
||||
return gc->alloc_gc_copy(z, cpof.src_);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ namespace xo {
|
|||
void display(std::ostream & os) const final override { os << data_; }
|
||||
|
||||
virtual std::size_t _shallow_size() const final override { return sizeof(*this); }
|
||||
virtual Object * _shallow_copy() const final override { return new (Cpof(this)) DummyObject(*this); }
|
||||
virtual Object * _shallow_copy() const final override { return new (Cpof(Object::mm, this)) DummyObject(*this); }
|
||||
virtual std::size_t _forward_children() final override { return _shallow_size(); }
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -306,8 +306,8 @@ public:
|
|||
std::size_t tenured_tospace_scale() const;
|
||||
GcStateDescription snapshot_gc_state() const;
|
||||
|
||||
void generate_random_mutation();
|
||||
void generate_random_mutations();
|
||||
void generate_random_mutation(GC * gc);
|
||||
void generate_random_mutations(GC * gc);
|
||||
|
||||
public:
|
||||
int alloc_per_cycle_ = 1;
|
||||
|
|
@ -415,10 +415,10 @@ AppState::snapshot_gc_state() const {
|
|||
}
|
||||
|
||||
void
|
||||
AppState::generate_random_mutation() {
|
||||
AppState::generate_random_mutation(GC * gc) {
|
||||
if (rng_() % 1000 > (5 * 1000) / 7) {
|
||||
/* p=16% integer */
|
||||
gc_root_v_[next_root_++] = Integer::make(next_int_);
|
||||
gc_root_v_[next_root_++] = Integer::make(gc, next_int_);
|
||||
} else if (rng_() % 1000 > (3 * 1000) / 7) {
|
||||
/* p=16% cons */
|
||||
gp<Object> random_car = gc_root_v_.at(rng_() % gc_root_v_.size());
|
||||
|
|
@ -454,9 +454,9 @@ AppState::generate_random_mutation() {
|
|||
}
|
||||
|
||||
void
|
||||
AppState::generate_random_mutations() {
|
||||
AppState::generate_random_mutations(GC * gc) {
|
||||
for (int i = 0; i < this->alloc_per_cycle_; ++i) {
|
||||
this->generate_random_mutation();
|
||||
this->generate_random_mutation(gc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1921,7 +1921,7 @@ int main(int, char **)
|
|||
case draw_state_type::alloc:
|
||||
{
|
||||
/** generate random alloc **/
|
||||
app_state.generate_random_mutations();
|
||||
app_state.generate_random_mutations(app_state.gc_.get());
|
||||
|
||||
gcstate = app_state.snapshot_gc_state();
|
||||
|
||||
|
|
|
|||
|
|
@ -20,13 +20,12 @@ add_definitions(${PROJECT_CXX_FLAGS})
|
|||
|
||||
# note on ordering: must read .cmake defn of lib before configuring any examples
|
||||
add_subdirectory(src/interpreter)
|
||||
|
||||
xo_export_cmake_config(${PROJECT_NAME} ${PROJECT_VERSION} ${PROJECT_NAME}Targets)
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
#add_subdirectory(example)
|
||||
#add_subdirectory(utest)
|
||||
add_subdirectory(utest)
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
35
xo-interpreter/cmake/xo-bootstrap-macros.cmake
Normal file
35
xo-interpreter/cmake/xo-bootstrap-macros.cmake
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# ----------------------------------------------------------------
|
||||
# for example:
|
||||
# $ PREFIX=/usr/local # for example
|
||||
# $ cmake -DCMAKE_MODULE_PATH=prefix -DCMAKE_INSTALL_PREFIX=$PREFIX -B .build
|
||||
#
|
||||
# will get
|
||||
# CMAKE_MODULE_PATH
|
||||
# from xo-cmake-config --cmake-module-path
|
||||
#
|
||||
# and expect .cmake macros in
|
||||
# CMAKE_MODULE_PATH/xo_macros/xo_cxx.cmake
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
find_program(XO_CMAKE_CONFIG_EXECUTABLE NAMES xo-cmake-config REQUIRED)
|
||||
|
||||
if ("${XO_CMAKE_CONFIG_EXECUTABLE}" STREQUAL "XO_CMAKE_CONFIG_EXECUTABLE-NOT_FOUND")
|
||||
message(FATAL "could not find xo-cmake-config executable")
|
||||
endif()
|
||||
|
||||
message(STATUS "XO_CMAKE_CONFIG_EXECUTABLE=${XO_CMAKE_CONFIG_EXECUTABLE}")
|
||||
|
||||
if (NOT XO_SUBMODULE_BUILD)
|
||||
if (("${CMAKE_MODULE_PATH}" STREQUAL "") OR ("${CMAKE_MODULE_PATH}" STREQUAL prefix))
|
||||
# default to typical install location for xo-project-macros
|
||||
execute_process(COMMAND ${XO_CMAKE_CONFIG_EXECUTABLE} --cmake-module-path OUTPUT_VARIABLE CMAKE_MODULE_PATH)
|
||||
message(STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# needs to have been installed somewhere on CMAKE_MODULE_PATH,
|
||||
# (e.g. from xo-cmake with the same value for CMAKE_INSTALL_PREFIX)
|
||||
#
|
||||
include(xo_macros/xo_cxx)
|
||||
|
||||
xo_cxx_bootstrap_message()
|
||||
7
xo-interpreter/cmake/xo_interpreterConfig.cmake.in
Normal file
7
xo-interpreter/cmake/xo_interpreterConfig.cmake.in
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(xo_alloc)
|
||||
#find_dependency(xo_flatstring)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
check_required_components("@PROJECT_NAME@")
|
||||
9
xo-interpreter/docs/CMakeLists.txt
Normal file
9
xo-interpreter/docs/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# xo-alloc/docs/CMakeLists.txt
|
||||
|
||||
xo_doxygen_collect_deps()
|
||||
xo_docdir_doxygen_config()
|
||||
xo_docdir_sphinx_config(
|
||||
index.rst install.rst)
|
||||
|
||||
# see xo-reader/doc or xo-unit/doc for working examples
|
||||
# example.rst install.rst implementation.rst
|
||||
39
xo-interpreter/docs/conf.py
Normal file
39
xo-interpreter/docs/conf.py
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# For the full list of built-in configuration values, see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||
|
||||
project = 'xo interpreter documentation'
|
||||
copyright = '2025, Roland Conybeare'
|
||||
author = 'Roland Conybeare'
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||
|
||||
#extensions = []
|
||||
extensions = [ "breathe",
|
||||
"sphinx.ext.mathjax", # inline math
|
||||
"sphinx.ext.autodoc", # generate info from docstrings
|
||||
"sphinxcontrib.ditaa", # diagrams-through-ascii-art
|
||||
"sphinxcontrib.plantuml" # text -> uml diagrams
|
||||
]
|
||||
|
||||
# note: breathe requires doxygen xml output -> must have GENERATE_XML = YES in Doxyfile.in
|
||||
# match project name in Doxyfile.in
|
||||
breathe_default_project = "xodoxxml"
|
||||
|
||||
templates_path = ['_templates']
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||
|
||||
#html_theme = 'alabaster'
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_static_path = ['_static']
|
||||
html_favicon = '_static/img/favicon.ico'
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
/** @file StackFrame.hpp **/
|
||||
|
||||
#include "xo/alloc/IAlloc.hpp"
|
||||
#include "xo/alloc/Object.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace scm {
|
||||
|
|
@ -8,15 +10,59 @@ namespace xo {
|
|||
* @brief Represent a single runtime stack frame for a Schematika function
|
||||
*
|
||||
* StackFrame intended to be used for interpreted functions.
|
||||
* Compiled functions will stil likely have stack frames, but need not use the
|
||||
* Compiled functions will still likely have stack frames, but need not use the
|
||||
* @ref StackFrame class
|
||||
*
|
||||
* memory layout:
|
||||
*
|
||||
* +------------+
|
||||
* | vtable |
|
||||
* +------------+
|
||||
* | .n_ |
|
||||
* +------------+
|
||||
* | .v_ +------\
|
||||
* +------------+ <--/
|
||||
* | .v_[0] |
|
||||
* +------------+
|
||||
* . .. .
|
||||
* +------------+
|
||||
* | .v_[.n_-1] |
|
||||
* +------------+
|
||||
**/
|
||||
class StackFrame : public Object {
|
||||
public:
|
||||
StackFrame(std::size_t n_slot)
|
||||
using TaggedPtr = xo::reflect::TaggedPtr;
|
||||
|
||||
public:
|
||||
StackFrame(gc::IAlloc * mm, std::size_t n_slot);
|
||||
|
||||
/** create frame using allocator @p mm,
|
||||
* with exactly @p n_slot object pointers
|
||||
**/
|
||||
static gp<StackFrame> make(gc::IAlloc * mm, std::size_t n_slot);
|
||||
|
||||
/** reflect StackFrame object representation **/
|
||||
static void reflect_self();
|
||||
|
||||
std::size_t n_slot() const { return n_slot_; }
|
||||
gp<Object> lookup(std::size_t i) const { return v_[i]; }
|
||||
gp<Object> & lookup(std::size_t i) { return v_[i]; }
|
||||
|
||||
gp<Object> operator[](std::size_t i) const { return lookup(i); }
|
||||
gp<Object> & operator[](std::size_t i) { return lookup(i); }
|
||||
|
||||
// inherited from Object..
|
||||
virtual TaggedPtr self_tp() const final override;
|
||||
virtual void display(std::ostream & os) const final override;
|
||||
virtual std::size_t _shallow_size() const final override;
|
||||
virtual Object * _shallow_copy() const final override;
|
||||
virtual std::size_t _forward_children() final override;
|
||||
|
||||
private:
|
||||
|
||||
/** number of elements in frame **/
|
||||
std::size_t n_slot_ = 0;
|
||||
/** contiguous array of object pointers: v[0] .. v[n-1] **/
|
||||
gp<Object> * v_ = nullptr;
|
||||
};
|
||||
} /*namespace scm*/
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
21
xo-interpreter/include/xo/interpreter/init_interpreter.hpp
Normal file
21
xo-interpreter/include/xo/interpreter/init_interpreter.hpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/** @file init_interpreter.hpp
|
||||
*
|
||||
* author: Roland Conybeare, Nov 2025
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xo/subsys/Subsystem.hpp"
|
||||
|
||||
namespace xo {
|
||||
/* tag to represent the interpreter/ subsystem in ordered initialization */
|
||||
enum S_interpreter_tag {};
|
||||
|
||||
template<>
|
||||
struct InitSubsys<S_interpreter_tag> {
|
||||
static void init();
|
||||
static InitEvidence require();
|
||||
};
|
||||
}
|
||||
|
||||
/* end init_interpreter.hpp */
|
||||
13
xo-interpreter/src/interpreter/CMakeLists.txt
Normal file
13
xo-interpreter/src/interpreter/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# interpreter/CMakeLists.txt
|
||||
|
||||
set(SELF_LIB xo_interpreter)
|
||||
set(SELF_SRCS
|
||||
init_interpreter.cpp
|
||||
StackFrame.cpp
|
||||
VirtualSchematikaMachine.cpp
|
||||
)
|
||||
|
||||
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
|
||||
xo_dependency(${SELF_LIB} xo_alloc)
|
||||
#xo_dependency(${SELF_LIB} xo_reader)
|
||||
xo_headeronly_dependency(${SELF_LIB} subsys)
|
||||
120
xo-interpreter/src/interpreter/StackFrame.cpp
Normal file
120
xo-interpreter/src/interpreter/StackFrame.cpp
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/** @file StackFrame.cpp **/
|
||||
|
||||
#include "StackFrame.hpp"
|
||||
#include "xo/reflect/Reflect.hpp"
|
||||
#include "xo/reflect/StructReflector.hpp"
|
||||
#include <cstring>
|
||||
|
||||
namespace xo {
|
||||
using xo::reflect::Reflect;
|
||||
using xo::reflect::StructReflector;
|
||||
using xo::reflect::TaggedPtr;
|
||||
using xo::print::quot;
|
||||
|
||||
namespace scm {
|
||||
namespace {
|
||||
std::size_t
|
||||
slot_array_size(std::size_t n) {
|
||||
return n * sizeof(gp<Object>);
|
||||
}
|
||||
}
|
||||
|
||||
StackFrame::StackFrame(gc::IAlloc * mm, std::size_t n_slot)
|
||||
: n_slot_{n_slot}, v_{nullptr}
|
||||
{
|
||||
if (n_slot > 0) {
|
||||
std::byte * mem = mm->alloc(slot_array_size(n_slot));
|
||||
|
||||
this->v_ = new (mem) gp<Object>[n_slot];
|
||||
}
|
||||
}
|
||||
|
||||
gp<StackFrame>
|
||||
StackFrame::make(gc::IAlloc * mm, std::size_t n_slot)
|
||||
{
|
||||
return new (MMPtr(mm)) StackFrame(mm, n_slot);
|
||||
}
|
||||
|
||||
TaggedPtr
|
||||
StackFrame::self_tp() const
|
||||
{
|
||||
return Reflect::make_tp(const_cast<StackFrame *>(this));
|
||||
}
|
||||
|
||||
void
|
||||
StackFrame::display(std::ostream & os) const
|
||||
{
|
||||
os << "<stack-frame"
|
||||
<< xtag("n_slot", n_slot_);
|
||||
|
||||
#ifdef NOT_YET
|
||||
for (std::size_t i = 0, n = n_slot(); i < n; ++i) {
|
||||
char buf[24];
|
||||
snprintf(buf, sizeof(buf), "v[%lu]", i);
|
||||
|
||||
os << xtag(buf, lookup(i));
|
||||
}
|
||||
#endif
|
||||
|
||||
os << ">";
|
||||
}
|
||||
|
||||
std::size_t
|
||||
StackFrame::_shallow_size() const
|
||||
{
|
||||
std::size_t retval = sizeof(StackFrame);
|
||||
|
||||
retval += gc::IAlloc::with_padding(slot_array_size(n_slot_));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
Object *
|
||||
StackFrame::_shallow_copy() const
|
||||
{
|
||||
Cpof cpof(Object::mm, this);
|
||||
|
||||
StackFrame * copy = new (cpof) StackFrame(cpof.mm_, n_slot_);
|
||||
|
||||
void * v_dest = copy->v_;
|
||||
|
||||
if (v_) {
|
||||
::memcpy(v_dest, v_, slot_array_size(n_slot_));
|
||||
}
|
||||
|
||||
#ifdef OBSOLETE
|
||||
for (size_t i = 0, n = n_slot_; i < n; ++i) {
|
||||
copy->v_[i] = v_[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
StackFrame::_forward_children()
|
||||
{
|
||||
for (std::size_t i = 0, n = n_slot_; i < n; ++i) {
|
||||
Object::_forward_inplace(lookup(i));
|
||||
}
|
||||
|
||||
return _shallow_size();
|
||||
}
|
||||
|
||||
void
|
||||
StackFrame::reflect_self()
|
||||
{
|
||||
StructReflector<StackFrame> sr;
|
||||
|
||||
if (sr.is_incomplete()) {
|
||||
REFLECT_MEMBER(sr, n_slot);
|
||||
|
||||
// non-trivial to reflect frame members,
|
||||
// effectively need separate reflection for each cardinality;
|
||||
// or: reflect .v_[] as nested element
|
||||
}
|
||||
}
|
||||
} /*namespace scm*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end StackFrame.cpp */
|
||||
27
xo-interpreter/src/interpreter/init_interpreter.cpp
Normal file
27
xo-interpreter/src/interpreter/init_interpreter.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/** @file init_interpreter.cpp
|
||||
*
|
||||
* author: Roland Conybeare, Nov 2025
|
||||
*/
|
||||
|
||||
#include "init_interpreter.hpp"
|
||||
#include "StackFrame.hpp"
|
||||
#include "xo/subsys/Subsystem.hpp"
|
||||
|
||||
namespace xo {
|
||||
using xo::scm::StackFrame;
|
||||
|
||||
void
|
||||
InitSubsys<S_interpreter_tag>::init()
|
||||
{
|
||||
StackFrame::reflect_self();
|
||||
}
|
||||
|
||||
InitEvidence
|
||||
InitSubsys<S_interpreter_tag>::require()
|
||||
{
|
||||
return Subsystem::provide<S_interpreter_tag>("interpreter", &init);
|
||||
}
|
||||
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end init_interpreter.cpp */
|
||||
12
xo-interpreter/utest/CMakeLists.txt
Normal file
12
xo-interpreter/utest/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# build unittest interpreter/utest
|
||||
|
||||
set(UTEST_EXE utest.interpreter)
|
||||
set(UTEST_SRCS
|
||||
interpreter_utest_main.cpp
|
||||
StackFrame.test.cpp
|
||||
)
|
||||
|
||||
xo_add_utest_executable(${UTEST_EXE} ${UTEST_SRCS})
|
||||
xo_self_dependency(${UTEST_EXE} xo_interpreter)
|
||||
xo_dependency(${UTEST_EXE} xo_object)
|
||||
xo_external_target_dependency(${UTEST_EXE} Catch2 Catch2::Catch2)
|
||||
133
xo-interpreter/utest/StackFrame.test.cpp
Normal file
133
xo-interpreter/utest/StackFrame.test.cpp
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
/** @file StackFrame.test.cpp **/
|
||||
|
||||
#include "xo/interpreter/init_interpreter.hpp"
|
||||
#include "xo/interpreter/StackFrame.hpp"
|
||||
#include "xo/object/Integer.hpp"
|
||||
#include "xo/alloc/GC.hpp"
|
||||
#include <catch2/catch.hpp>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
using xo::scm::StackFrame;
|
||||
using xo::obj::Integer;
|
||||
using xo::gc::GC;
|
||||
using xo::gc::ArenaAlloc;
|
||||
using xo::gc::generation;
|
||||
using xo::gc::generation_result;
|
||||
using xo::reflect::TaggedPtr;
|
||||
|
||||
namespace ut {
|
||||
static InitEvidence s_init = (InitSubsys<S_interpreter_tag>::require());
|
||||
|
||||
namespace {
|
||||
struct Testcase_StackFrame {
|
||||
Testcase_StackFrame(const std::vector<std::int32_t> & contents) : contents_{contents} {}
|
||||
|
||||
/* build xo::obj::Integer for each contents_[i], store in F[i] for new StackFrame F */
|
||||
std::vector<std::int32_t> contents_;
|
||||
};
|
||||
|
||||
std::vector<Testcase_StackFrame>
|
||||
s_testcase_v = {
|
||||
Testcase_StackFrame({}),
|
||||
Testcase_StackFrame({}),
|
||||
Testcase_StackFrame({111}),
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("StackFrame", "[StackFrame][interpreter]")
|
||||
{
|
||||
Subsystem::initialize_all();
|
||||
|
||||
constexpr bool c_debug_flag = false;
|
||||
|
||||
for (std::size_t i_tc = 0, n_tc = s_testcase_v.size(); i_tc < n_tc; ++i_tc) {
|
||||
scope log(XO_DEBUG(c_debug_flag), xtag("test", "StackFrame2"), xtag("i_tc", i_tc));
|
||||
|
||||
const Testcase_StackFrame & tc = s_testcase_v[i_tc];
|
||||
|
||||
up<ArenaAlloc> alloc = ArenaAlloc::make("utest", 16384, c_debug_flag);
|
||||
REQUIRE(alloc.get());
|
||||
Object::mm = alloc.get();
|
||||
|
||||
std::size_t n = tc.contents_.size();
|
||||
gp<StackFrame> frame = StackFrame::make(alloc.get(), n);
|
||||
|
||||
TaggedPtr tp = frame->self_tp();
|
||||
|
||||
REQUIRE(tp.is_struct());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("StackFrame2", "[StackFrame][gc][interpreter]")
|
||||
{
|
||||
Subsystem::initialize_all();
|
||||
|
||||
constexpr bool c_debug_flag = false;
|
||||
|
||||
try {
|
||||
for (std::size_t i_tc = 0, n_tc = s_testcase_v.size(); i_tc < n_tc; ++i_tc) {
|
||||
scope log(XO_DEBUG(c_debug_flag), xtag("test", "StackFrame2"), xtag("i_tc", i_tc));
|
||||
|
||||
const Testcase_StackFrame & tc = s_testcase_v[i_tc];
|
||||
|
||||
up<GC> gc = GC::make(
|
||||
{.initial_nursery_z_ = 16384,
|
||||
.initial_tenured_z_ = 32768,
|
||||
.incr_gc_threshold_ = 4096,
|
||||
.full_gc_threshold_ = 4096,
|
||||
.object_stats_flag_ = true,
|
||||
.debug_flag_ = c_debug_flag,
|
||||
});
|
||||
|
||||
REQUIRE(gc.get());
|
||||
|
||||
/* use gc for all Object allocs */
|
||||
GC * mm = gc.get();
|
||||
Object::mm = mm;
|
||||
|
||||
std::size_t n = tc.contents_.size();
|
||||
|
||||
gp<Integer> x = Integer::make(gc.get(), 42);
|
||||
gc->add_gc_root(reinterpret_cast<Object **>(&x));
|
||||
REQUIRE(gc->tospace_generation_of(x.ptr()) == generation_result::nursery);
|
||||
|
||||
gp<StackFrame> frame = StackFrame::make(gc.get(), n);
|
||||
StackFrame ** frame_pp = frame.ptr_address();
|
||||
gc->add_gc_root(reinterpret_cast<Object **>(frame_pp));
|
||||
|
||||
/* verifying allocated in N1 */
|
||||
REQUIRE(gc->tospace_generation_of(frame.ptr()) == generation_result::nursery);
|
||||
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
frame->lookup(i) = Integer::make(mm, tc.contents_.at(i));
|
||||
|
||||
std::size_t expected_alloc_z = frame->_shallow_size();
|
||||
REQUIRE(expected_alloc_z >= sizeof(StackFrame) + n * sizeof(gp<Object>));
|
||||
|
||||
gc->request_gc(generation::nursery); // <<<<<<<<< GC here <<<<<<<<<
|
||||
|
||||
REQUIRE(gc->native_gc_statistics().gen_v_[gen2int(generation::nursery)].n_gc_ == 1);
|
||||
REQUIRE(gc->native_gc_statistics().gen_v_[gen2int(generation::tenured)].n_gc_ == 0);
|
||||
|
||||
/* verify Integer x preserved across gc */
|
||||
REQUIRE(gc->tospace_generation_of(x.ptr()) == generation_result::nursery);
|
||||
|
||||
/* verify StackFrame preserved across gc */
|
||||
REQUIRE(gc->tospace_generation_of(frame.ptr()) == generation_result::nursery);
|
||||
REQUIRE(frame->n_slot() == n);
|
||||
for (std::size_t i = 0; i < n; ++i) {
|
||||
//REQUIRE(Integer::from(frame->lookup(i)).ptr());
|
||||
//REQUIRE(Integer::from(frame->lookup(i))->value() == tc.contents_.at(i));
|
||||
}
|
||||
}
|
||||
} catch (std::exception & ex) {
|
||||
std::cerr << "exception: " << ex.what() << std::endl;
|
||||
REQUIRE(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* end StackFrame.test.cpp */
|
||||
6
xo-interpreter/utest/interpreter_utest_main.cpp
Normal file
6
xo-interpreter/utest/interpreter_utest_main.cpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/** @file interpreter_utest_main.cpp **/
|
||||
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch2/catch.hpp"
|
||||
|
||||
/* end interpreter_utest_main.cpp */
|
||||
|
|
@ -10,7 +10,7 @@ if (ENABLE_TESTING)
|
|||
xo_add_utest_executable(${SELF_EXE} ${SELF_SRCS})
|
||||
xo_self_dependency(${SELF_EXE} xo_jit)
|
||||
xo_dependency(${SELF_EXE} xo_ratio)
|
||||
xo_dependency(${SELF_EXE} xo_reflectutil)
|
||||
xo_headeronly_dependency(${SELF_EXE} xo_reflectutil)
|
||||
xo_external_target_dependency(${SELF_EXE} Catch2 Catch2::Catch2)
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ namespace xo {
|
|||
namespace obj {
|
||||
class Integer : public Number {
|
||||
public:
|
||||
using IAlloc = xo::gc::IAlloc;
|
||||
using int_type = long long;
|
||||
|
||||
public:
|
||||
|
|
@ -18,7 +19,7 @@ namespace xo {
|
|||
explicit Integer(int_type x);
|
||||
|
||||
/** create instance holding integer value @p x **/
|
||||
static gp<Integer> make(int_type x);
|
||||
static gp<Integer> make(IAlloc * mm, int_type x);
|
||||
/** downcast from @p x iff x is actually an Integer. Otherwise nullptr **/
|
||||
static gp<Integer> from(gp<Object> x);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,4 +8,8 @@ set(SELF_SRCS
|
|||
Integer.cpp)
|
||||
|
||||
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -10,12 +10,13 @@
|
|||
namespace xo {
|
||||
using xo::reflect::Reflect;
|
||||
using xo::reflect::TaggedPtr;
|
||||
using xo::gc::IAlloc;
|
||||
|
||||
namespace obj {
|
||||
Integer::Integer(int_type x) : value_{x} {}
|
||||
|
||||
gp<Integer>
|
||||
Integer::make(int_type x) {
|
||||
Integer::make(IAlloc * mm, int_type x) {
|
||||
return new (MMPtr(mm)) Integer(x);
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +42,7 @@ namespace xo {
|
|||
|
||||
Object *
|
||||
Integer::_shallow_copy() const {
|
||||
Cpof cpof(this);
|
||||
Cpof cpof(Object::mm, this);
|
||||
return new (cpof) Integer(*this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ namespace xo {
|
|||
|
||||
assert(!(this->is_nil()));
|
||||
|
||||
Cpof cpof(this);
|
||||
Cpof cpof(Object::mm, this);
|
||||
|
||||
return new (cpof) List(*this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ namespace xo {
|
|||
{
|
||||
// Reminder: String must come before secondary allocation,
|
||||
|
||||
Cpof cpof(this);
|
||||
Cpof cpof(Object::mm, this);
|
||||
|
||||
// might expect to write:
|
||||
// gp<String> copy = new (gcm) String(Object::mm, owner_, z_chars_, chars_);
|
||||
|
|
|
|||
|
|
@ -55,10 +55,10 @@ namespace xo {
|
|||
/* use gc for all Object allocs */
|
||||
Object::mm = gc.get();
|
||||
|
||||
gp<List> l = List::list(Integer::make(1));
|
||||
gp<List> l = List::list(Integer::make(gc.get(), 1));
|
||||
gc->add_gc_root(reinterpret_cast<Object**>(l.ptr_address()));
|
||||
|
||||
gp<List> l2 = List::list(Integer::make(10));
|
||||
gp<List> l2 = List::list(Integer::make(gc.get(), 10));
|
||||
gc->add_gc_root(reinterpret_cast<Object**>(l2.ptr_address()));
|
||||
|
||||
{
|
||||
|
|
@ -80,7 +80,7 @@ namespace xo {
|
|||
|
||||
// mutation, but not {xgen, xckp} since parent,child both in N0
|
||||
|
||||
l->assign_head(Integer::make(2));
|
||||
l->assign_head(Integer::make(gc.get(), 2));
|
||||
{
|
||||
REQUIRE(gc->native_gc_statistics().n_mutation_ == 1);
|
||||
REQUIRE(gc->native_gc_statistics().n_logged_mutation_ == 0);
|
||||
|
|
@ -106,7 +106,7 @@ namespace xo {
|
|||
|
||||
// mutation, xckp since parent in N1, child in N0
|
||||
|
||||
l->assign_head(Integer::make(3));
|
||||
l->assign_head(Integer::make(gc.get(), 3));
|
||||
{
|
||||
REQUIRE(Integer::from(l->head())->value() == 3);
|
||||
|
||||
|
|
@ -373,11 +373,11 @@ namespace xo {
|
|||
RandomMutationModel(std::size_t m, std::size_t n, std::size_t r, std::size_t rr, std::size_t k)
|
||||
: m_{m}, n_{n}, r_{r}, rr_{rr}, k_{k} {}
|
||||
|
||||
void generate_seed_values();
|
||||
void generate_seed_values(GC * gc);
|
||||
void generate_random_roots(GC * gc, xoshiro256ss * p_rgen);
|
||||
void generate_random_mutations(xoshiro256ss * p_rgen);
|
||||
|
||||
void rejuvenate_seed_values();
|
||||
void rejuvenate_seed_values(GC * gc);
|
||||
void alter_random_roots(xoshiro256ss * p_rgen);
|
||||
|
||||
/* create m random list cells */
|
||||
|
|
@ -400,7 +400,7 @@ namespace xo {
|
|||
std::vector<gp<Object>> root_v_;
|
||||
};
|
||||
|
||||
void RandomMutationModel::generate_seed_values()
|
||||
void RandomMutationModel::generate_seed_values(GC * gc)
|
||||
{
|
||||
w1_.clear();
|
||||
w2_.clear();
|
||||
|
|
@ -415,7 +415,7 @@ namespace xo {
|
|||
{
|
||||
std::copy(w1_.begin(), w1_.end(), std::back_inserter(w2_));
|
||||
for (size_t j = 0; j < n_; ++j) {
|
||||
w2_.push_back(Integer::make((this->start_)++));
|
||||
w2_.push_back(Integer::make(gc, (this->start_)++));
|
||||
}
|
||||
REQUIRE(w2_.size() == m_ + n_);
|
||||
}
|
||||
|
|
@ -468,7 +468,7 @@ namespace xo {
|
|||
}
|
||||
}
|
||||
|
||||
void RandomMutationModel::rejuvenate_seed_values()
|
||||
void RandomMutationModel::rejuvenate_seed_values(GC * gc)
|
||||
{
|
||||
for (std::size_t i = 0; i < w1_.size(); ++i) {
|
||||
INFO(xtag("i", i));
|
||||
|
|
@ -492,7 +492,7 @@ namespace xo {
|
|||
REQUIRE(w2_[j].ptr());
|
||||
} else {
|
||||
/* w2[j] is garbage, replace */
|
||||
w2_[j] = Integer::make((this->start_)++);
|
||||
w2_[j] = Integer::make(gc, (this->start_)++);
|
||||
REQUIRE(w2_[j].ptr());
|
||||
}
|
||||
}
|
||||
|
|
@ -616,7 +616,7 @@ namespace xo {
|
|||
INFO(xtag("cycle", cycle));
|
||||
|
||||
if (cycle == 0) {
|
||||
data_model.generate_seed_values();
|
||||
data_model.generate_seed_values(gc.get());
|
||||
data_model.generate_random_roots(gc.get(), &rgen);
|
||||
} else {
|
||||
/* figure out values in {data_model_.w1_, data_model_.w2_} that
|
||||
|
|
@ -626,7 +626,7 @@ namespace xo {
|
|||
* (For example want to verify behavior of GC w.r.t. cells that are alive only
|
||||
* because of a mutation)
|
||||
*/
|
||||
data_model.rejuvenate_seed_values();
|
||||
data_model.rejuvenate_seed_values(gc.get());
|
||||
data_model.alter_random_roots(&rgen);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ namespace xo {
|
|||
|
||||
Object::mm = gc.get();
|
||||
|
||||
gp<Integer> i1 = Integer::make(123);
|
||||
gp<Integer> i2 = Integer::make(-321);
|
||||
gp<Integer> i1 = Integer::make(gc.get(), 123);
|
||||
gp<Integer> i2 = Integer::make(gc.get(), -321);
|
||||
|
||||
REQUIRE(i1->value() == 123);
|
||||
REQUIRE(i2->value() == -321);
|
||||
|
|
|
|||
|
|
@ -289,9 +289,10 @@ namespace xo {
|
|||
|
||||
up<ArenaAlloc> alloc = ArenaAlloc::make("arena", 1024, c_debug_flag);
|
||||
|
||||
Object::mm = alloc.get();
|
||||
ArenaAlloc * mm = alloc.get();
|
||||
Object::mm = mm;
|
||||
|
||||
gp<List> l = List::list(Integer::make(1), Integer::make(2), Integer::make(3));
|
||||
gp<List> l = List::list(Integer::make(mm, 1), Integer::make(mm, 2), Integer::make(mm, 3));
|
||||
|
||||
REQUIRE(l->size() == 3);
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ if (ENABLE_TESTING)
|
|||
xo_self_headeronly_dependency(${SELF_EXE} xo_ratio)
|
||||
xo_dependency(${SELF_EXE} reflect)
|
||||
# need explicit header-only dependencies, at least in submodule build
|
||||
xo_dependency(${SELF_EXE} xo_reflectutil)
|
||||
xo_headeronly_dependency(${SELF_EXE} xo_reflectutil)
|
||||
xo_dependency(${SELF_EXE} randomgen)
|
||||
xo_dependency(${SELF_EXE} indentlog)
|
||||
xo_external_target_dependency(${SELF_EXE} Catch2 Catch2::Catch2)
|
||||
|
|
|
|||
|
|
@ -24,12 +24,13 @@ Install
|
|||
One-step Install
|
||||
----------------
|
||||
|
||||
Install along with the rest of *XO* from `xo-umbrella2 source`_
|
||||
Install along with the rest of *XO* from `xo-umbrella2 source`_:
|
||||
see install instructions for xo-umrbella2
|
||||
|
||||
.. _xo-umbrella2 source: https://github.com/rconybea/xo-umbrella2
|
||||
|
||||
Minimal Dependencies
|
||||
--------------------
|
||||
Essential Xo Dependencies
|
||||
-------------------------
|
||||
|
||||
``xo-reader`` uses several supporting libraries from the *XO* project:
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace xo {
|
|||
|
||||
template<typename T>
|
||||
static TypeDescrW establish() {
|
||||
TypeDescrW td = TypeDescrBase::require(&typeid(T),
|
||||
static TypeDescrW td = TypeDescrBase::require(&typeid(T),
|
||||
std::string(type_name<T>()),
|
||||
nullptr /*tdextra*/,
|
||||
nullptr /*invoker*/);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ set(SELF_SRCS
|
|||
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
|
||||
xo_dependency(${SELF_LIB} refcnt)
|
||||
xo_dependency(${SELF_LIB} indentlog)
|
||||
xo_dependency(${SELF_LIB} subsys)
|
||||
xo_headeronly_dependency(${SELF_LIB} subsys)
|
||||
#xo_boost_dependency(${SELF_LIB})
|
||||
|
||||
# end CMakeLists.txt
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@ namespace xo {
|
|||
detail::Invoker * invoker,
|
||||
std::unique_ptr<TypeDescrExtra> tdextra)
|
||||
{
|
||||
scope log(XO_DEBUG(false));
|
||||
|
||||
log && log(xtag("canonical_name", canonical_name));
|
||||
|
||||
if (native_tinfo) {
|
||||
/* 1. lookup by tinfo hash_code in s_type_table_map
|
||||
* Not available for manually-constructed type descriptions.
|
||||
|
|
@ -64,18 +68,28 @@ namespace xo {
|
|||
{
|
||||
auto ix = s_native_type_table_map.find(TypeInfoRef(native_tinfo));
|
||||
|
||||
if ((ix != s_native_type_table_map.end()) && ix->second)
|
||||
if ((ix != s_native_type_table_map.end()) && ix->second) {
|
||||
log && log("TypeDescrBase::require"
|
||||
": using s_native_type_table_map[TypeInfoRef(native_tinfo)]");
|
||||
|
||||
return ix->second;
|
||||
}
|
||||
}
|
||||
|
||||
/* 2. lookup by tinfo hash_code in s_coalesced_type_table_map */
|
||||
{
|
||||
auto ix = s_coalesced_type_table_map.find(TypeInfoRef(native_tinfo));
|
||||
|
||||
if ((ix != s_coalesced_type_table_map.end()) && ix->second)
|
||||
if ((ix != s_coalesced_type_table_map.end()) && ix->second) {
|
||||
log && log("TypeDescrBase::require"
|
||||
": using s_coalesced_type_table_map[TypeInfoRef(native_tinfo)]");
|
||||
|
||||
return ix->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log && log("TypeDescrBase::require: try lookup by canonical name");
|
||||
|
||||
/* 3. lookup by canonical_name, before we create a new slot.
|
||||
*
|
||||
|
|
@ -85,6 +99,7 @@ namespace xo {
|
|||
auto ix = s_canonical_type_table_map.find(canonical_name);
|
||||
|
||||
if (ix != s_canonical_type_table_map.end()) {
|
||||
|
||||
/** assume existing slot, with same canonical name,
|
||||
* represents the same type as native_tinfo
|
||||
**/
|
||||
|
|
@ -145,6 +160,8 @@ namespace xo {
|
|||
|
||||
TypeId new_td_id = TypeId::allocate();
|
||||
|
||||
log && log("TypeDescrBase::require", xtag("new_td_id", new_td_id));
|
||||
|
||||
if (s_type_table_v.size() <= new_td_id.id())
|
||||
s_type_table_v.resize(new_td_id.id() + 1);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue