From 459347e24dd66133775b94defcee4b76b89c98c1 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Thu, 22 Jan 2015 15:23:58 +0800 Subject: [PATCH] use lua_clonefunction for load lua file --- 3rd/lua/README | 5 +- 3rd/lua/lapi.c | 8 +-- 3rd/lua/lauxlib.c | 122 +++++++++++++++++++++++++++++++++++++++++++++- 3rd/lua/lua.h | 1 + 4 files changed, 130 insertions(+), 6 deletions(-) diff --git a/3rd/lua/README b/3rd/lua/README index 1daa6438..d658c4fd 100644 --- a/3rd/lua/README +++ b/3rd/lua/README @@ -1,2 +1,5 @@ -Copy from Lua 5.3.0 final http://www.lua.org/ftp/lua-5.3.0.tar.gz +This is a modify version of lua 5.3.0 (http://www.lua.org/ftp/lua-5.3.0.tar.gz) . + +For detail : http://lua-users.org/lists/lua-l/2014-03/msg00489.html + diff --git a/3rd/lua/lapi.c b/3rd/lua/lapi.c index bf5e829f..8d9c3765 100644 --- a/3rd/lua/lapi.c +++ b/3rd/lua/lapi.c @@ -1011,7 +1011,7 @@ static Proto * cloneproto (lua_State *L, const Proto *src) { return f; } -LUA_API void lua_clonefunction (lua_State *L, void * fp) { +LUA_API void lua_clonefunction (lua_State *L, const void * fp) { LClosure *cl; LClosure *f = cast(LClosure *, fp); lua_lock(L); @@ -1027,13 +1027,13 @@ LUA_API void lua_clonefunction (lua_State *L, void * fp) { api_incr_top(L); luaF_initupvals(L, cl); - if (f->nupvalues >= 1) { /* does it have an upvalue? */ + if (cl->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_upvalbarrier(L, f->upvals[0]); + setobj(L, cl->upvals[0]->v, gt); + luaC_upvalbarrier(L, cl->upvals[0]); } lua_unlock(L); } diff --git a/3rd/lua/lauxlib.c b/3rd/lua/lauxlib.c index 1c41d6a8..72ef5d95 100644 --- a/3rd/lua/lauxlib.c +++ b/3rd/lua/lauxlib.c @@ -638,7 +638,7 @@ static int skipcomment (LoadF *lf, int *cp) { } -LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, +static int luaL_loadfilex_ (lua_State *L, const char *filename, const char *mode) { LoadF lf; int status, readstatus; @@ -970,3 +970,123 @@ LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) { ver, *v); } +// use clonefunction + +#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {} +#define UNLOCK(q) __sync_lock_release(&(q)->lock); + +struct codecache { + int lock; + lua_State *L; +}; + +static struct codecache CC = { 0 , NULL }; + +static void +clearcache() { + if (CC.L == NULL) + return; + LOCK(&CC) + lua_close(CC.L); + CC.L = luaL_newstate(); + UNLOCK(&CC) +} + +static void +init() { + CC.lock = 0; + CC.L = luaL_newstate(); +} + +static const void * +load(const char *key) { + if (CC.L == NULL) + return NULL; + 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); + UNLOCK(&CC) + + return result; +} + +static const void * +save(const char *key, const void * proto) { + lua_State *L; + const void * result = NULL; + + LOCK(&CC) + if (CC.L == NULL) { + init(); + L = CC.L; + } else { + 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); + } + } + UNLOCK(&CC) + return result; +} + +LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, + const char *mode) { + const void * proto = load(filename); + if (proto) { + lua_clonefunction(L, proto); + return LUA_OK; + } + 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; + } + 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 }, + { NULL, NULL }, + }; + luaL_newlib(L,l); + lua_getglobal(L, "loadfile"); + lua_setfield(L, -2, "loadfile"); + return 1; +} diff --git a/3rd/lua/lua.h b/3rd/lua/lua.h index 09a4ccaf..579a5e17 100644 --- a/3rd/lua/lua.h +++ b/3rd/lua/lua.h @@ -280,6 +280,7 @@ LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); +LUA_API void (lua_clonefunction) (lua_State *L, const void *eL); /* ** coroutine functions