Skip to content
Permalink
Browse files
Add share proto
  • Loading branch information
cloudwu committed Apr 17, 2020
1 parent fa95776 commit e374793
Show file tree
Hide file tree
Showing 8 changed files with 260 additions and 10 deletions.
@@ -0,0 +1,6 @@
This is a modify version of lua 5.4.0-rc1 (http://www.lua.org/work/lua-5.4.0-rc1.tar.gz) .

For detail ,
Shared Proto : http://lua-users.org/lists/lua-l/2014-03/msg00489.html
Shared short string table : http://blog.codingnow.com/2015/08/lua_vm_share_string.html
Signal for debug use : http://blog.codingnow.com/2015/03/skynet_signal.html
@@ -1044,6 +1044,16 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
return status;
}

static void set_env (lua_State *L, LClosure *f) {
if (f->nupvalues >= 1) { /* does it have an upvalue? */
/* get global table from registry */
Table *reg = hvalue(&G(L)->l_registry);
const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
setobj(L, f->upvals[0]->v, gt);
luaC_barrier(L, f->upvals[0], gt);
}
}

LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
const char *chunkname, const char *mode) {
@@ -1055,19 +1065,53 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
status = luaD_protectedparser(L, &z, chunkname, mode);
if (status == LUA_OK) { /* no errors? */
LClosure *f = clLvalue(s2v(L->top - 1)); /* get newly created function */
if (f->nupvalues >= 1) { /* does it have an upvalue? */
/* get global table from registry */
Table *reg = hvalue(&G(L)->l_registry);
const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
setobj(L, f->upvals[0]->v, gt);
luaC_barrier(L, f->upvals[0], gt);
}
set_env(L,f);
}
lua_unlock(L);
return status;
}

LUA_API void lua_clonefunction (lua_State *L, const void * fp) {
LClosure *cl;
LClosure *f = cast(LClosure *, fp);
api_check(L, isshared(f->p), "Not a shared proto");
lua_lock(L);
cl = luaF_newLclosure(L,f->nupvalues);
setclLvalue2s(L,L->top,cl);
api_incr_top(L);
cl->p = f->p;
luaF_initupvals(L, cl);
set_env(L,cl);
lua_unlock(L);
}

LUA_API void lua_sharefunction (lua_State *L, int index) {
if (!lua_isfunction(L,index) || lua_iscfunction(L,index))
luaG_runerror(L, "Only Lua function can share");
LClosure *f = cast(LClosure *, lua_topointer(L, index));
luaF_shareproto(f->p);
}

LUA_API void lua_sharestring (lua_State *L, int index) {
const char *str = lua_tostring(L, index);
if (str == NULL)
luaG_runerror(L, "need a string to share");

TString *ts = (TString *)(str - sizeof(TString));
luaS_share(ts);
}

LUA_API void lua_clonetable(lua_State *L, const void * tp) {
Table *t = cast(Table *, tp);

if (!isshared(t))
luaG_runerror(L, "Not a shared table");

lua_lock(L);
sethvalue2s(L, L->top, t);
api_incr_top(L);
lua_unlock(L);
}

LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) {
int status;
@@ -749,7 +749,7 @@ static int skipcomment (LoadF *lf, int *cp) {
}


LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
LUALIB_API int luaL_loadfilex_ (lua_State *L, const char *filename,
const char *mode) {
LoadF lf;
int status, readstatus;
@@ -1053,3 +1053,176 @@ LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
(LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)v);
}

// use clonefunction

#include "spinlock.h"

struct codecache {
struct spinlock lock;
lua_State *L;
};

static struct codecache CC;

static void
clearcache() {
if (CC.L == NULL)
return;
SPIN_LOCK(&CC)
lua_close(CC.L);
CC.L = luaL_newstate();
SPIN_UNLOCK(&CC)
}

static void
init() {
CC.L = luaL_newstate();
}

LUALIB_API void
luaL_initcodecache(void) {
SPIN_INIT(&CC);
}

static const void *
load(const char *key) {
if (CC.L == NULL)
return NULL;
SPIN_LOCK(&CC)
lua_State *L = CC.L;
lua_pushstring(L, key);
lua_rawget(L, LUA_REGISTRYINDEX);
const void * result = lua_touserdata(L, -1);
lua_pop(L, 1);
SPIN_UNLOCK(&CC)

return result;
}

static const void *
save(const char *key, const void * proto) {
lua_State *L;
const void * result = NULL;

SPIN_LOCK(&CC)
if (CC.L == NULL) {
init();
}
L = CC.L;
lua_pushstring(L, key);
lua_pushvalue(L, -1);
lua_rawget(L, LUA_REGISTRYINDEX);
result = lua_touserdata(L, -1); /* stack: key oldvalue */
if (result == NULL) {
lua_pop(L,1);
lua_pushlightuserdata(L, (void *)proto);
lua_rawset(L, LUA_REGISTRYINDEX);
} else {
lua_pop(L,2);
}

SPIN_UNLOCK(&CC)
return result;
}

#define CACHE_OFF 0
#define CACHE_EXIST 1
#define CACHE_ON 2

static int cache_key = 0;

static int cache_level(lua_State *L) {
int t = lua_rawgetp(L, LUA_REGISTRYINDEX, &cache_key);
int r = lua_tointeger(L, -1);
lua_pop(L,1);
if (t == LUA_TNUMBER) {
return r;
}
return CACHE_ON;
}

static int cache_mode(lua_State *L) {
static const char * lst[] = {
"OFF",
"EXIST",
"ON",
NULL,
};
if (lua_isnoneornil(L,1)) {
int t = lua_rawgetp(L, LUA_REGISTRYINDEX, &cache_key);
int r = lua_tointeger(L, -1);
if (t == LUA_TNUMBER) {
if (r < 0 || r >= CACHE_ON) {
r = CACHE_ON;
}
} else {
r = CACHE_ON;
}
lua_pushstring(L, lst[r]);
return 1;
}
int t = luaL_checkoption(L, 1, "OFF" , lst);
lua_pushinteger(L, t);
lua_rawsetp(L, LUA_REGISTRYINDEX, &cache_key);
return 0;
}

LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
const char *mode) {
int level = cache_level(L);
if (level == CACHE_OFF) {
return luaL_loadfilex_(L, filename, mode);
}
const void * proto = load(filename);
if (proto) {
lua_clonefunction(L, proto);
return LUA_OK;
}
if (level == CACHE_EXIST) {
return luaL_loadfilex_(L, filename, mode);
}
lua_State * eL = luaL_newstate();
if (eL == NULL) {
lua_pushliteral(L, "New state failed");
return LUA_ERRMEM;
}
int err = luaL_loadfilex_(eL, filename, mode);
if (err != LUA_OK) {
size_t sz = 0;
const char * msg = lua_tolstring(eL, -1, &sz);
lua_pushlstring(L, msg, sz);
lua_close(eL);
return err;
}
lua_sharefunction(eL, -1);
proto = lua_topointer(eL, -1);
const void * oldv = save(filename, proto);
if (oldv) {
lua_close(eL);
lua_clonefunction(L, oldv);
} else {
lua_clonefunction(L, proto);
/* Never close it. notice: memory leak */
}

return LUA_OK;
}

static int
cache_clear(lua_State *L) {
(void)(L);
clearcache();
return 0;
}

LUAMOD_API int luaopen_cache(lua_State *L) {
luaL_Reg l[] = {
{ "clear", cache_clear },
{ "mode", cache_mode },
{ NULL, NULL },
};
luaL_newlib(L,l);
lua_getglobal(L, "loadfile");
lua_setfield(L, -2, "loadfile");
return 1;
}
@@ -90,6 +90,8 @@ LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);

LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
const char *mode);
LUALIB_API int (luaL_loadfilex_) (lua_State *L, const char *filename,
const char *mode);

#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL)

@@ -21,6 +21,7 @@
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"



@@ -297,3 +298,20 @@ const char *luaF_getlocalname (const Proto *f, int local_number, int pc) {
return NULL; /* not found */
}

void luaF_shareproto (Proto *f) {
int i;
if (f == NULL)
return;
makeshared(f);
luaS_share(f->source);
for (i = 0; i < f->sizek; i++) {
if (ttype(&f->k[i]) == LUA_TSTRING)
luaS_share(tsvalue(&f->k[i]));
}
for (i = 0; i < f->sizeupvalues; i++)
luaS_share(f->upvalues[i].name);
for (i = 0; i < f->sizelocvars; i++)
luaS_share(f->locvars[i].varname);
for (i = 0; i < f->sizep; i++)
luaF_shareproto(f->p[i]);
}
@@ -64,6 +64,6 @@ LUAI_FUNC void luaF_unlinkupval (UpVal *uv);
LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
int pc);

LUAI_FUNC void luaF_shareproto (Proto *func);

#endif
@@ -243,6 +243,10 @@ LUA_API void (lua_pushboolean) (lua_State *L, int b);
LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
LUA_API int (lua_pushthread) (lua_State *L);

LUA_API void (lua_clonefunction) (lua_State *L, const void * fp);
LUA_API void (lua_sharefunction) (lua_State *L, int index);
LUA_API void (lua_sharestring) (lua_State *L, int index);
LUA_API void (lua_clonetable) (lua_State *L, const void * t);

/*
** get functions (Lua -> stack)
@@ -44,6 +44,9 @@ LUAMOD_API int (luaopen_debug) (lua_State *L);
#define LUA_LOADLIBNAME "package"
LUAMOD_API int (luaopen_package) (lua_State *L);

#define LUA_CACHELIB
LUAMOD_API int (luaopen_cache) (lua_State *L);
LUALIB_API void (luaL_initcodecache) (void);

/* open all previous libraries */
LUALIB_API void (luaL_openlibs) (lua_State *L);

0 comments on commit e374793

Please sign in to comment.