use lua_clonefunction for load lua file

This commit is contained in:
Cloud Wu
2015-01-22 15:23:58 +08:00
parent a0adbb1103
commit 459347e24d
4 changed files with 130 additions and 6 deletions

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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