diff --git a/.gitignore b/.gitignore index 3649d6d..7f5275b 100644 --- a/.gitignore +++ b/.gitignore @@ -75,3 +75,5 @@ fabric.properties # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser + +Testing diff --git a/src/main.cpp b/src/main.cpp index 5c6d528..e59c42c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,7 +5,6 @@ #include "VM.h" int main() { - MemoryContext mc; Handle repl; { Parser parser; diff --git a/src/vm/include/MemoryContext.h b/src/vm/include/MemoryContext.h index 7a9ea06..97afdbf 100644 --- a/src/vm/include/MemoryContext.h +++ b/src/vm/include/MemoryContext.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -14,7 +15,6 @@ #include #include #include -#include #include "Cell.h" #include "Handle.h" @@ -28,6 +28,8 @@ public: MemoryContext(); ~MemoryContext(); + static MemoryContext &get(); + template Handle create_cell(Args... args) { return alloc_cell(std::forward(args)...); @@ -136,6 +138,4 @@ private: std::atomic _gc_thread_stop = false; }; -extern std::atomic CURRENT_MC; - #endif//PSIL_MEMORYCONTEXT_H diff --git a/src/vm/src/Handle.cpp b/src/vm/src/Handle.cpp index c1eb872..36160cd 100644 --- a/src/vm/src/Handle.cpp +++ b/src/vm/src/Handle.cpp @@ -8,17 +8,17 @@ Handle::Handle(Cell *target) : _target(target) { if (target != nullptr) - CURRENT_MC.load()->add_root(target); + MemoryContext::get().add_root(target); } Handle::~Handle() { if (_target != nullptr) - CURRENT_MC.load()->remove_root(_target); + MemoryContext::get().remove_root(_target); } Handle::Handle(Handle const &other) : _target(other._target) { if (_target != nullptr) - CURRENT_MC.load()->add_root(_target); + MemoryContext::get().add_root(_target); } Handle &Handle::operator=(Handle other) { @@ -27,7 +27,7 @@ Handle &Handle::operator=(Handle other) { } Handle Handle::cons(const Handle &car, const Handle &cdr) { - auto ret = CURRENT_MC.load()->create_cell(car.get(), cdr.get()); + auto ret = MemoryContext::get().create_cell(car.get(), cdr.get()); return ret; } @@ -70,22 +70,22 @@ void Handle::splice(const Handle &what) { } Handle Handle::makeNumCell(int64_t val) { - return CURRENT_MC.load()->create_cell(val); + return MemoryContext::get().create_cell(val); } Handle Handle::makeStrCell(std::string val) { - return CURRENT_MC.load()->create_cell(std::move(val)); + return MemoryContext::get().create_cell(std::move(val)); } void Handle::setcar(const Handle &car) { - CURRENT_MC.load()->run_dirty([&](std::function dirty) -> void { + MemoryContext::get().run_dirty([&](std::function dirty) -> void { dirty(dynamic_cast(*_target)._car); dynamic_cast(*_target)._car = car.get(); }); } void Handle::setcdr(const Handle &cdr) { - CURRENT_MC.load()->run_dirty([&](std::function dirty) -> void { + MemoryContext::get().run_dirty([&](std::function dirty) -> void { dirty(dynamic_cast(*_target)._cdr); dynamic_cast(*_target)._cdr = cdr.get(); }); diff --git a/src/vm/src/MemoryContext.cpp b/src/vm/src/MemoryContext.cpp index 139887e..0171f5e 100644 --- a/src/vm/src/MemoryContext.cpp +++ b/src/vm/src/MemoryContext.cpp @@ -10,12 +10,8 @@ #include #include -std::atomic CURRENT_MC = nullptr; MemoryContext::MemoryContext() { - MemoryContext *expected = nullptr; - if (!CURRENT_MC.compare_exchange_strong(expected, this)) throw std::runtime_error("MC already exists!"); - _gc_thread = std::thread(std::bind(&MemoryContext::gc_thread_entry, this)); } @@ -29,11 +25,6 @@ MemoryContext::~MemoryContext() { assert(cell_count() == 0); - MemoryContext *expected = this; - if (!CURRENT_MC.compare_exchange_strong(expected, nullptr)) { - std::cerr << "Global MC pointer was overwritten!" << std::endl; - std::abort(); - } _gc_thread_stop = true; _gc_request_cv.notify_all(); _gc_thread.join(); @@ -253,4 +244,8 @@ void MemoryContext::gc_thread_entry() { _gc_done_cv.notify_all(); } } -} \ No newline at end of file +} +MemoryContext &MemoryContext::get() { + static MemoryContext mc; + return mc; +} diff --git a/test/vm/CompilerTest.cpp b/test/vm/CompilerTest.cpp index f287379..7311e24 100644 --- a/test/vm/CompilerTest.cpp +++ b/test/vm/CompilerTest.cpp @@ -11,7 +11,7 @@ TEST(CompilerTest, BasicHello) { std::stringstream ssin; std::stringstream ssout; { - MemoryContext mc; + VM vm(ssin, ssout); Parser parser; parser.loadStr("(LDC 3 EVAL PRINT STOP)"); @@ -26,7 +26,7 @@ TEST(CompilerTest, BasicLet) { std::stringstream ssin; std::stringstream ssout; { - MemoryContext mc; + VM vm(ssin, ssout); Parser parser; parser.loadStr("(LDC (let ((x 1)) x) EVAL PRINT STOP)"); @@ -41,7 +41,7 @@ TEST(CompilerTest, BasicFn) { std::stringstream ssin; std::stringstream ssout; { - MemoryContext mc; + VM vm(ssin, ssout); Parser parser; parser.loadStr("(LDC (let ((plfn (lambda (a b) (+ a b)))) (plfn 2 3)) EVAL PRINT STOP)"); @@ -56,7 +56,7 @@ TEST(CompilerTest, BasicFnIfT) { std::stringstream ssin; std::stringstream ssout; { - MemoryContext mc; + VM vm(ssin, ssout); Parser parser; parser.loadStr("(LDC (let ((plfn (lambda (a) (if a 1 2)))) (plfn 1)) EVAL PRINT STOP)"); @@ -70,7 +70,7 @@ TEST(CompilerTest, BasicFnIfF) { std::stringstream ssin; std::stringstream ssout; { - MemoryContext mc; + VM vm(ssin, ssout); Parser parser; parser.loadStr("(LDC (let ((plfn (lambda (a) (if a 1 2)))) (plfn 0)) EVAL PRINT STOP)"); @@ -84,7 +84,7 @@ TEST(CompilerTest, RecursiveFn) { std::stringstream ssin; std::stringstream ssout; { - MemoryContext mc; + VM vm(ssin, ssout); Parser parser; parser.loadStr("(LDC (letrec ((fib (lambda (n) (if n (if (+ n -1) (+ (fib (+ n -1)) (fib(+ n -2))) 1) 0) ))) (fib 10)) EVAL PRINT STOP)"); diff --git a/test/vm/GCTest.cpp b/test/vm/GCTest.cpp index 1b3cf1c..fd50551 100644 --- a/test/vm/GCTest.cpp +++ b/test/vm/GCTest.cpp @@ -7,96 +7,96 @@ #include "MemoryContext.h" TEST(GCTest, GCTest) { - MemoryContext mc; + { Handle c = Handle::cons(nullptr, nullptr); - mc.request_gc_and_wait(); + MemoryContext::get().request_gc_and_wait(); c.append(Handle::makeNumCell(1)); c.append(Handle::makeNumCell(2)); - mc.request_gc_and_wait(); + MemoryContext::get().request_gc_and_wait(); EXPECT_EQ(c.car().val(), 1); EXPECT_EQ(c.cdr().car().val(), 2); } - mc.request_gc_and_wait(); - mc.request_gc_and_wait(); - EXPECT_EQ(mc.cell_count(), 0); + MemoryContext::get().request_gc_and_wait(); + MemoryContext::get().request_gc_and_wait(); + EXPECT_EQ(MemoryContext::get().cell_count(), 0); { Handle c = Handle::cons(nullptr, nullptr); - mc.request_gc_and_wait(); + MemoryContext::get().request_gc_and_wait(); c.push(Handle::makeNumCell(1)); c.push(Handle::makeNumCell(2)); - mc.request_gc_and_wait(); + MemoryContext::get().request_gc_and_wait(); EXPECT_EQ(c.car().val(), 2); EXPECT_EQ(c.cdr().car().val(), 1); } - mc.request_gc_and_wait(); - mc.request_gc_and_wait(); - EXPECT_EQ(mc.cell_count(), 0); + MemoryContext::get().request_gc_and_wait(); + MemoryContext::get().request_gc_and_wait(); + EXPECT_EQ(MemoryContext::get().cell_count(), 0); } TEST(GCTest, GCTestAppend) { - MemoryContext mc; + for (int i = 0; i < 25000; i++) { Handle c = Handle::cons(nullptr, nullptr); - mc.request_gc(); + MemoryContext::get().request_gc(); c.append(Handle::makeNumCell(1)); - mc.request_gc(); + MemoryContext::get().request_gc(); EXPECT_EQ(c.car().val(), 1); } - mc.request_gc_and_wait(); - mc.request_gc_and_wait(); - EXPECT_EQ(mc.cell_count(), 0); + MemoryContext::get().request_gc_and_wait(); + MemoryContext::get().request_gc_and_wait(); + EXPECT_EQ(MemoryContext::get().cell_count(), 0); } TEST(GCTest, GCTestPop) { - MemoryContext mc; + { Handle c = Handle::cons(nullptr, nullptr); static constexpr int test_size = 20000; for (int i = 0; i < test_size; i++) { - mc.request_gc(); + MemoryContext::get().request_gc(); c.push(Handle::makeNumCell(i)); } for (int i = test_size - 1; i >= 0; i--) { - mc.request_gc(); + MemoryContext::get().request_gc(); EXPECT_EQ(i, c.pop().val()); } } - mc.request_gc_and_wait(); - mc.request_gc_and_wait(); - EXPECT_EQ(mc.cell_count(), 0); + MemoryContext::get().request_gc_and_wait(); + MemoryContext::get().request_gc_and_wait(); + EXPECT_EQ(MemoryContext::get().cell_count(), 0); } TEST(GCTest, GCTestAppend2) { - MemoryContext mc; + Handle c = Handle::cons(nullptr, nullptr); static constexpr int test_size = 2000; for (int i = 0; i < test_size; i++) { - mc.request_gc(); + MemoryContext::get().request_gc(); c.append(Handle::makeNumCell(i)); } for (int i = 0; i < test_size; i++) { - mc.request_gc(); + MemoryContext::get().request_gc(); EXPECT_EQ(i, c.pop().val()); } - mc.request_gc_and_wait(); - mc.request_gc_and_wait(); - EXPECT_EQ(mc.cell_count(), 0); + MemoryContext::get().request_gc_and_wait(); + MemoryContext::get().request_gc_and_wait(); + EXPECT_EQ(MemoryContext::get().cell_count(), 0); } TEST(GCTest, GCTestAppend3) { - MemoryContext mc; + for (int i = 0; i < 250000; i++) { Handle c = Handle::cons(nullptr, nullptr); - mc.request_gc(); + MemoryContext::get().request_gc(); c.append(Handle::makeNumCell(1)); c.append(Handle::makeNumCell(2)); - mc.request_gc(); + MemoryContext::get().request_gc(); Handle n = c.cdr(); c.setcdr(nullptr); EXPECT_EQ(n.car().val(), 2); EXPECT_EQ(c.car().val(), 1); } - mc.request_gc_and_wait(); - mc.request_gc_and_wait(); - EXPECT_EQ(mc.cell_count(), 0); + MemoryContext::get().request_gc_and_wait(); + MemoryContext::get().request_gc_and_wait(); + EXPECT_EQ(MemoryContext::get().cell_count(), 0); } diff --git a/test/vm/VMTest.cpp b/test/vm/VMTest.cpp index 505415f..be450fd 100644 --- a/test/vm/VMTest.cpp +++ b/test/vm/VMTest.cpp @@ -6,7 +6,7 @@ TEST(VMTest, BasicHello) { std::stringstream ssin; std::stringstream ssout; { - MemoryContext mc; + VM vm(ssin, ssout); Handle newc(Handle::cons(nullptr, nullptr)); newc.append(Handle::makeStrCell("NIL")); diff --git a/test/vm/VMWithParserTest.cpp b/test/vm/VMWithParserTest.cpp index cd60e93..ce3c107 100644 --- a/test/vm/VMWithParserTest.cpp +++ b/test/vm/VMWithParserTest.cpp @@ -7,7 +7,7 @@ TEST(VMWithParserTest, BasicHello) { std::stringstream ssin; std::stringstream ssout; { - MemoryContext mc; + VM vm(ssin, ssout); Parser parser; parser.loadStr("(LDC 104 PUTCHAR STOP)"); @@ -22,7 +22,7 @@ TEST(VMWithParserTest, BasicBranch) { std::stringstream ssin; std::stringstream ssout; { - MemoryContext mc; + VM vm(ssin, ssout); Parser parser; parser.loadStr( @@ -38,7 +38,7 @@ TEST(VMWithParserTest, BasicFunction) { std::stringstream ssin; std::stringstream ssout; { - MemoryContext mc; + VM vm(ssin, ssout); Parser parser; parser.loadStr("(NIL LDC 1 CONS LDC 2 CONS LDF (LD (1 . 1) LD (1.2) ADD RET) AP PUTNUM STOP)"); @@ -52,7 +52,7 @@ TEST(VMWithParserTest, BasicFunction) { TEST(VMWithParserTest, RecFunction) { std::stringstream ssin; std::stringstream ssout; - MemoryContext mc; + { VM vm(ssin, ssout); Parser parser; @@ -61,9 +61,9 @@ TEST(VMWithParserTest, RecFunction) { vm.loadControl(parser.parseExpr()); vm.run(); } - mc.request_gc_and_wait(); - mc.request_gc_and_wait(); - EXPECT_EQ(mc.cell_count(), 0); + MemoryContext::get().request_gc_and_wait(); + MemoryContext::get().request_gc_and_wait(); + EXPECT_EQ(MemoryContext::get().cell_count(), 0); ssout.flush(); EXPECT_EQ(ssout.str(), "6765"); } \ No newline at end of file