Skip to content
Permalink
Browse files
Add a simple test
  • Loading branch information
cloudwu committed Apr 17, 2020
1 parent e374793 commit 2242227
Show file tree
Hide file tree
Showing 4 changed files with 256 additions and 0 deletions.
@@ -0,0 +1,21 @@
# for mingw

LUAINC = -I../src
LUALIB = -L../src/ -llua54
CFLAGS = -Wall -g
SHARED = --shared

all : sharetable.dll multivm.dll

sharetable.dll : sharetable.c
gcc $(CFLAGS) $(SHARED) -o $@ $^ $(LUAINC) $(LUALIB)

multivm.dll : multivm.c
gcc $(CFLAGS) $(SHARED) -o $@ $^ $(LUAINC) $(LUALIB)

clean :
rm sharetable.dll multivm.dll

test :
../src/lua.exe test.lua

@@ -0,0 +1,110 @@
#define LUA_LIB

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

struct boxvm {
lua_State *L;
};

static int
lvm_delete(lua_State *L) {
struct boxvm *vm = lua_touserdata(L, 1);
if (vm->L) {
lua_close(vm->L);
vm->L = NULL;
}
return 0;
}

static int
vm_init(lua_State *L) {
luaL_openlibs(L);
return 0;
}

static int
vm_dostring(lua_State *L) {
const char *code = (const char *)lua_touserdata(L, 1);
lua_pop(L, 1);
luaL_loadstring(L, code);
lua_call(L, 0, LUA_MULTRET);
return lua_gettop(L);
}

static int
lvm_dostring(lua_State *L) {
luaL_checktype(L, 1, LUA_TUSERDATA);
struct boxvm *vm = lua_touserdata(L, 1);
lua_State *cL = vm->L;
const char * code = luaL_checkstring(L, 2);
lua_settop(cL, 0);
lua_pushcfunction(cL, vm_dostring);
lua_pushlightuserdata(cL, (void *)code);
if (lua_pcall(cL, 1, LUA_MULTRET, 0) != LUA_OK) {
const char * err = lua_tostring(cL, -1);
lua_pushstring(L, err);
lua_pop(cL, 1);
return lua_error(L);
}
int retn = lua_gettop(cL);
int i;
for (i=1;i<=retn;i++) {
switch(lua_type(cL, i)) {
case LUA_TBOOLEAN:
lua_pushboolean(L, lua_toboolean(cL, i));
break;
case LUA_TNUMBER:
if (lua_isinteger(cL, i)) {
lua_pushinteger(L, lua_tointeger(cL, i));
} else {
lua_pushnumber(L, lua_tonumber(cL, i));
}
break;
case LUA_TLIGHTUSERDATA:
lua_pushlightuserdata(L, lua_touserdata(cL, i));
break;
default:
return luaL_error(L, "Unsupported return type %s", lua_typename(L, lua_type(cL, i)));
}
}
return retn;
}

static int
lnew_vm(lua_State *L) {
struct boxvm *vm = lua_newuserdata(L, sizeof(struct boxvm));
vm->L = NULL;
if (luaL_newmetatable(L, "MULTIVM")) {
luaL_Reg meta[] = {
{ "__gc", lvm_delete },
{ "__index", NULL },
{ "dostring", lvm_dostring },
{ NULL, NULL },
};
luaL_setfuncs(L, meta, 0);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
}
lua_setmetatable(L, -2);
vm->L = luaL_newstate();
lua_pushcfunction(vm->L, vm_init);
if (lua_pcall(vm->L, 0, 0, 0) != LUA_OK) {
lua_close(vm->L);
vm->L = NULL;
return luaL_error(L, "new vm failed");
}
return 1;
}

LUAMOD_API int
luaopen_multivm(lua_State *L) {
luaL_checkversion(L);
luaL_Reg l[] = {
{ "new", lnew_vm },
{ NULL, NULL },
};
luaL_newlib(L, l);
return 1;
}
@@ -0,0 +1,106 @@
#define LUA_LIB

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

#include "lgc.h"

#ifdef makeshared

static void
mark_shared(lua_State *L) {
if (lua_type(L, -1) != LUA_TTABLE) {
luaL_error(L, "Not a table, it's a %s.", lua_typename(L, lua_type(L, -1)));
}
Table * t = (Table *)lua_topointer(L, -1);
if (isshared(t))
return;
makeshared(t);
luaL_checkstack(L, 4, NULL);
if (lua_getmetatable(L, -1)) {
luaL_error(L, "Can't share metatable");
}
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
int i;
for (i=0;i<2;i++) {
int idx = -i-1;
int t = lua_type(L, idx);
switch (t) {
case LUA_TTABLE:
mark_shared(L);
break;
case LUA_TNUMBER:
case LUA_TBOOLEAN:
case LUA_TLIGHTUSERDATA:
break;
case LUA_TFUNCTION:
if (lua_getupvalue(L, idx, 1) != NULL) {
luaL_error(L, "Invalid function with upvalue");
} else if (!lua_iscfunction(L, idx)) {
LClosure *f = (LClosure *)lua_topointer(L, idx);
makeshared(f);
}
break;
case LUA_TSTRING:
lua_sharestring(L, idx);
break;
default:
luaL_error(L, "Invalid type [%s]", lua_typename(L, t));
break;
}
}
lua_pop(L, 1);
}
}

static int
lis_sharedtable(lua_State* L) {
int b = 0;
if(lua_type(L, 1) == LUA_TTABLE) {
Table * t = (Table *)lua_topointer(L, 1);
b = isshared(t);
}
lua_pushboolean(L, b);
return 1;
}

static int
lmark_shared(lua_State *L) {
// turn off gc , because marking shared will prevent gc mark.
lua_gc(L, LUA_GCSTOP, 0);
mark_shared(L);
Table * t = (Table *)lua_topointer(L, -1);
lua_pushlightuserdata(L, t);
return 1;
}

static int
lclone_table(lua_State *L) {
lua_clonetable(L, lua_touserdata(L, 1));

return 1;
}

LUAMOD_API int
luaopen_sharetable(lua_State *L) {
luaL_checkversion(L);
luaL_Reg l[] = {
{ "clone", lclone_table },
{ "mark_shared", lmark_shared },
{ "is_sharedtable", lis_sharedtable },
{ NULL, NULL },
};
luaL_newlib(L, l);
return 1;
}

#else

LUAMOD_API int
luaopen_sharetable(lua_State *L) {
return luaL_error(L, "Not supported");
}

#endif
@@ -0,0 +1,19 @@
local sharetable = require "sharetable"
local multivm = require "multivm"

local vm = multivm.new()

local testp, tablep = vm:dostring [[
local sharetable = require "sharetable"
_G.test = { "Hello", "World" }
local testp = sharetable.mark_shared(_G.test)
local tablep = sharetable.mark_shared(_G.table)
return testp, tablep
]]

local shared_test = sharetable.clone(testp)
local shared_table = sharetable.clone(tablep)

-- Use table.unpack in vm to unpack _G.test in vm.
print(shared_table.unpack(shared_test))

0 comments on commit 2242227

Please sign in to comment.