From c68ff8fdf03d2c5bfb49ed9309c40852ca81845f Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Mon, 1 Mar 2021 17:29:32 -0500 Subject: [PATCH] In process of converting LuaSnap to use eris, not finished --- luprex/core/cpp/luasnap.cpp | 204 +++++++++-------------------------- luprex/core/cpp/luasnap.hpp | 3 +- luprex/core/cpp/luastack.hpp | 1 + luprex/core/cpp/source.cpp | 32 ++++++ luprex/core/cpp/source.hpp | 2 +- 5 files changed, 87 insertions(+), 155 deletions(-) diff --git a/luprex/core/cpp/luasnap.cpp b/luprex/core/cpp/luasnap.cpp index 2b3dfb90..1ceba283 100644 --- a/luprex/core/cpp/luasnap.cpp +++ b/luprex/core/cpp/luasnap.cpp @@ -1,172 +1,72 @@ #include "luasnap.hpp" +#include "luastack.hpp" #include #include - - -struct BlockHeader { - BlockHeader *prev_; - BlockHeader *next_; - int32_t sanity_; // 0x12345678 only when linked. - size_t size_; - bool in_use_; - void *snapshot_; -}; - -size_t blocksize(size_t base) { - return base + sizeof(BlockHeader); -} - -BlockHeader *pointer_to_header(void *ptr) { - return (BlockHeader*)(((char *)ptr) - sizeof(BlockHeader)); -} - -void *header_to_pointer(BlockHeader *blk) { - return (void *)(((char *)blk) + sizeof(BlockHeader)); -} - -class LuaSnapData { -public: - lua_State *state_; - bool have_snapshot_; - BlockHeader sentinel_; - - LuaSnapData(); - ~LuaSnapData(); - lua_State *state() const { return state_; } - bool have_snapshot() const { return have_snapshot_; } - void snapshot(); - void rollback(); - void link(BlockHeader *blk); - void unlink(BlockHeader *blk); - void *allocf(void *ptr, size_t osize, size_t nsize); -}; - -void *lsd_alloc_f(void *lsd, void *ptr, size_t osize, size_t nsize) { - return ((LuaSnapData*)lsd)->allocf(ptr, osize, nsize); -} - -LuaSnapData::LuaSnapData() { - sentinel_.prev_ = &sentinel_; - sentinel_.next_ = &sentinel_; - sentinel_.size_ = 0; - sentinel_.in_use_ = false; - sentinel_.snapshot_ = 0; - have_snapshot_ = false; - state_ = lua_newstate(lsd_alloc_f, (void*)this); -} - -LuaSnapData::~LuaSnapData() { - std::cerr << "LuaSnapData destructor not implemented." << std::endl; - exit(1); -} - -void LuaSnapData::snapshot() { - assert(!have_snapshot_); - for (BlockHeader *blk = sentinel_.next_; blk != &sentinel_; blk = blk->next_) { - assert(blk->in_use_); - blk->snapshot_ = malloc(blk->size_); - memcpy(blk->snapshot_, header_to_pointer(blk), blk->size_); - } - have_snapshot_ = true; -} - -void LuaSnapData::rollback() { - assert(have_snapshot_); - for (BlockHeader *blk = sentinel_.next_; blk != &sentinel_; ) { - BlockHeader *next = blk->next_; - if (blk->snapshot_) { - memcpy(header_to_pointer(blk), blk->snapshot_, blk->size_); - free(blk->snapshot_); - blk->snapshot_ = nullptr; - blk->in_use_ = true; - } else { - assert(blk->in_use_); - unlink(blk); - free(blk); - } - blk = next; - } - have_snapshot_ = false; -} - -void LuaSnapData::link(BlockHeader *blk) { - blk->prev_ = sentinel_.prev_; - blk->next_ = &sentinel_; - blk->prev_->next_ = blk; - blk->next_->prev_ = blk; - blk->sanity_ = 0x12345678; -} - -void LuaSnapData::unlink(BlockHeader *blk) { - blk->prev_->next_ = blk->next_; - blk->next_->prev_ = blk->prev_; - blk->prev_ = nullptr; - blk->next_ = nullptr; - blk->sanity_ = 0; -} - -void *LuaSnapData::allocf(void *ptr, size_t osize, size_t nsize) { - if (nsize == 0) { - if (ptr == 0) return nullptr; - BlockHeader *blk = pointer_to_header(ptr); - assert(blk->sanity_ = 0x12345678); - assert(blk->in_use_); - if (blk->snapshot_ == nullptr) { - unlink(blk); - free(blk); - } else { - blk->in_use_ = false; - } - return nullptr; - } else if (ptr == NULL) { - BlockHeader *blk = (BlockHeader*)malloc(blocksize(nsize)); - link(blk); - blk->size_ = nsize; - blk->in_use_ = true; - blk->snapshot_ = nullptr; - return header_to_pointer(blk); - } else { - BlockHeader *blk = pointer_to_header(ptr); - assert(blk->sanity_ = 0x12345678); - assert(blk->in_use_); - if (blk->snapshot_ == nullptr) { - unlink(blk); - blk = (BlockHeader*)realloc(blk, blocksize(nsize)); - blk->size_ = nsize; - link(blk); - return header_to_pointer(blk); - } else { - BlockHeader *nblk = (BlockHeader*)malloc(blocksize(nsize)); - memcpy(nblk, blk, (blk->size_ < nsize) ? blk->size_ : nsize); - blk->in_use_ = false; - link(nblk); - nblk->size_ = nsize; - nblk->in_use_ = true; - nblk->snapshot_ = nullptr; - return header_to_pointer(nblk); - } - } -} +#include LuaSnap::LuaSnap() { - data_ = new LuaSnapData; - state_ = data_->state(); + state_ = luaL_newstate(); + LuaStack LS(state_); + LS.rawset(LuaRegistry, "persist", LuaNewTable); + LS.rawset(LuaRegistry, "unpersist", LuaNewTable); } LuaSnap::~LuaSnap() { - delete data_; + std::cerr << "LuaSnap destructor not implemented yet" << std::endl; } bool LuaSnap::have_snapshot() const { - return data_->have_snapshot(); + return !snapshot_.empty(); +} + +static void oss_writer(lua_State *L, const void *p, size_t sz, void *ud) { + std::ostringstream *oss = (std::ostringstream *)ud; + oss->write((const char *)p, sz); } void LuaSnap::snapshot() { - data_->snapshot(); + // Snapshot and the lua stack should both be empty. + assert(snapshot_.empty()); + assert(lua_gettop(state_) == 0); + + // lua variables that we'll need. + LuaVar key, value; + LuaRet permstable, regcopy; + LuaStack LS(state_, permstable, regcopy, key, value); + + // Construct a copy of the registry table. + LS.set(regcopy, LuaNewTable); + LS.set(key, LuaNil); + while (LS.next(LuaRegistry, key, value) != 0) { + LS.rawset(regcopy, key, value); + } + + // Remove certain things from the copy. + LS.rawset(regcopy, LUA_RIDX_MAINTHREAD, LuaNil); + LS.rawset(regcopy, "persist", LuaNil); + LS.rawset(regcopy, "unpersist", LuaNil); + LS.rawset(regcopy, "world", LuaNil); + LS.rawset(regcopy, "gui", LuaNil); + LS.result(); + + // Get the permanents table from the registry. + LS.rawget(permstable, LuaRegistry, "persist"); + + // When we call 'LS.result', this should leave the + // permstable and the regcopy on the stack. + LS.result(); + assert(lua_gettop(state_) == 2); + + // Call eris to dump the state to an ostringstream, + // then save the result. + std::ostringstream oss; + eris_dump(state_, oss_writer, (void *)&oss); + snapshot_ = oss.str(); } void LuaSnap::rollback() { - data_->rollback(); + assert(!snapshot_.empty()); } + diff --git a/luprex/core/cpp/luasnap.hpp b/luprex/core/cpp/luasnap.hpp index fef2028f..c8ce019e 100644 --- a/luprex/core/cpp/luasnap.hpp +++ b/luprex/core/cpp/luasnap.hpp @@ -25,11 +25,10 @@ #include "luastack.hpp" -class LuaSnapData; class LuaSnap { private: lua_State *state_; - LuaSnapData *data_; + std::string snapshot_; public: LuaSnap(); diff --git a/luprex/core/cpp/luastack.hpp b/luprex/core/cpp/luastack.hpp index 3c195c7b..e5ab639f 100644 --- a/luprex/core/cpp/luastack.hpp +++ b/luprex/core/cpp/luastack.hpp @@ -369,6 +369,7 @@ public: bool isfunction(LuaSlot s) const { return lua_type(L_, s) == LUA_TFUNCTION; } bool isboolean(LuaSlot s) const { return lua_type(L_, s) == LUA_TBOOLEAN; } bool isnil(LuaSlot s) const { return lua_type(L_, s) == LUA_TNIL; } + bool iscfunction(LuaSlot s) const { return lua_iscfunction(L_, s) != 0; } void checktable(LuaSlot index) const { checktype(index, LUA_TTABLE); } void checkstring(LuaSlot index) const { checktype(index, LUA_TSTRING); } diff --git a/luprex/core/cpp/source.cpp b/luprex/core/cpp/source.cpp index 76fd5730..3436c5b2 100644 --- a/luprex/core/cpp/source.cpp +++ b/luprex/core/cpp/source.cpp @@ -320,3 +320,35 @@ void SourceDB::run_unittests() { LS.result(); } +void SourceDB::init(lua_State *L) { + lua_state_ = L; + LuaVar globtab, persist, unpersist, classname, classtab, funcname, funcp, rawfunc; + LuaStack LS(L, globtab, persist, unpersist, classname, classtab, funcname, funcp, rawfunc); + + // We need to register all C functions with the eris permanents tables. + source_clear_globals(L); + source_install_builtins(L); + source_load_cfunctions(L); + LS.getglobaltable(globtab); + LS.rawget(persist, LuaRegistry, "persist"); + LS.rawget(unpersist, LuaRegistry, "unpersist"); + LS.set(classname, LuaNil); + while (LS.next(globtab, classname, classtab) != 0) { + if (LS.isstring(classname) && LS.istable(classtab)) { + LS.set(funcname, LuaNil); + while (LS.next(classtab, funcname, funcp) != 0) { + if (LS.isstring(funcname) && LS.iscfunction(funcp)) { + std::string full = "cfunc:"; + full += LS.ckstring(classname); + full += "."; + full += LS.ckstring(funcname); + lua_pushcfunction(L, lua_tocfunction(L, funcp.index())); + lua_replace(L, rawfunc.index()); + LS.rawset(persist, rawfunc, full); + LS.rawset(unpersist, full, rawfunc); + } + } + } + } +} + diff --git a/luprex/core/cpp/source.hpp b/luprex/core/cpp/source.hpp index de494dfa..27484fc9 100644 --- a/luprex/core/cpp/source.hpp +++ b/luprex/core/cpp/source.hpp @@ -127,7 +127,7 @@ private: lua_State *lua_state_; public: - void init(lua_State *L) { lua_state_ = L; } + void init(lua_State *L); // Update //