diff --git a/3rd/lua/lapi.c b/3rd/lua/lapi.c index 348b149f..3d854509 100644 --- a/3rd/lua/lapi.c +++ b/3rd/lua/lapi.c @@ -1017,16 +1017,32 @@ static void cloneproto (lua_State *L, Proto *f, const Proto *src) { /* copy constants and nested proto */ int i,n; n = src->sp->sizek; - f->k=luaM_newvector(L,n,TValue); - for (i=0; ik[i]); - for (i=0; ik[i]; - TValue *o=&f->k[i]; - if (ttisstring(s)) { - TString * str = luaS_clonestring(L,tsvalue(s)); - setsvalue2n(L,o,str); - } else { - setobj(L,o,s); + if (src->sp->sharedk) + f->k = src->sp->k; + else { + lu_byte sharedk = 1; + f->k=luaM_newvector(L,n,TValue); + for (i=0; ik[i]); + for (i=0; ik[i]; + TValue *o=&f->k[i]; + if (ttisstring(s)) { + TString * sstr = tsvalue(s); + if (ttisshrstring(s)) { + TString * str = luaS_clonestring(L,sstr); + setsvalue2n(L,o,str); + if (str != sstr) + sharedk = 0; + } else { + setsvalue2n(L,o,sstr); + } + } else { + setobj(L,o,s); + } + } + if (sharedk) { + luaM_freearray(L, f->k, n); + f->k = src->sp->k; } } n = src->sp->sizep; diff --git a/3rd/lua/lauxlib.c b/3rd/lua/lauxlib.c index e54d3376..63387b7b 100644 --- a/3rd/lua/lauxlib.c +++ b/3rd/lua/lauxlib.c @@ -1152,6 +1152,8 @@ static int cache_mode(lua_State *L) { return 0; } +LUA_API void luaS_expandshr(int n); + LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode) { int level = cache_level(L); @@ -1171,6 +1173,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, lua_pushliteral(L, "New state failed"); return LUA_ERRMEM; } + luaS_expandshr(4096); int err = luaL_loadfilex_(eL, filename, mode); if (err != LUA_OK) { size_t sz = 0; diff --git a/3rd/lua/lfunc.c b/3rd/lua/lfunc.c index 1d011aa0..9c0c911f 100644 --- a/3rd/lua/lfunc.c +++ b/3rd/lua/lfunc.c @@ -122,26 +122,33 @@ Proto *luaF_newproto (lua_State *L, SharedProto *sp) { sp->linedefined = 0; sp->lastlinedefined = 0; sp->source = NULL; + sp->k = NULL; + sp->sharedk = 0; } f->sp = sp; return f; } -static void freesharedproto (lua_State *L, SharedProto *f) { - if (f == NULL || G(L) != f->l_G) +static void freesharedproto (lua_State *L, Proto *pf) { + SharedProto *f = pf->sp; + if (f == NULL) return; - luaM_freearray(L, f->code, f->sizecode); - luaM_freearray(L, f->lineinfo, f->sizelineinfo); - luaM_freearray(L, f->locvars, f->sizelocvars); - luaM_freearray(L, f->upvalues, f->sizeupvalues); - luaM_free(L, f); + if (G(L) == f->l_G) { + luaM_freearray(L, f->code, f->sizecode); + luaM_freearray(L, f->lineinfo, f->sizelineinfo); + luaM_freearray(L, f->locvars, f->sizelocvars); + luaM_freearray(L, f->upvalues, f->sizeupvalues); + luaM_freearray(L, f->k, f->sizek); + luaM_free(L, f); + } else if (pf->k != f->k) { + luaM_freearray(L, pf->k, f->sizek); + } } void luaF_freeproto (lua_State *L, Proto *f) { luaM_freearray(L, f->p, f->sp->sizep); - luaM_freearray(L, f->k, f->sp->sizek); - freesharedproto(L, f->sp); + freesharedproto(L, f); luaM_free(L, f); } diff --git a/3rd/lua/lgc.c b/3rd/lua/lgc.c index eeb5401e..a5677130 100644 --- a/3rd/lua/lgc.c +++ b/3rd/lua/lgc.c @@ -497,7 +497,7 @@ static int traverseproto (global_State *g, Proto *f) { f->cache = NULL; /* allow cache to be collected */ if (f->sp == NULL) return sizeof(Proto); - nk = (f->k == NULL) ? 0 : f->sp->sizek; + nk = (f->k == f->sp->k && g != f->sp->l_G) ? 0 : f->sp->sizek; np = (f->p == NULL) ? 0 : f->sp->sizep; for (i = 0; i < nk; i++) /* mark literals */ markvalue(g, &f->k[i]); diff --git a/3rd/lua/lobject.h b/3rd/lua/lobject.h index 8318005c..b537d392 100644 --- a/3rd/lua/lobject.h +++ b/3rd/lua/lobject.h @@ -404,6 +404,7 @@ typedef struct SharedProto { lu_byte numparams; /* number of fixed parameters */ lu_byte is_vararg; lu_byte maxstacksize; /* number of registers needed by this function */ + lu_byte sharedk; /* constants can be shared directly */ int sizeupvalues; /* size of 'upvalues' */ int sizek; /* size of 'k' */ int sizecode; @@ -418,6 +419,7 @@ typedef struct SharedProto { LocVar *locvars; /* information about local variables (debug information) */ Upvaldesc *upvalues; /* upvalue information */ TString *source; /* used for debug information */ + TValue *k; /* Shared constants */ } SharedProto; /* diff --git a/3rd/lua/lparser.c b/3rd/lua/lparser.c index 2a5cbf1e..9e0af8bc 100644 --- a/3rd/lua/lparser.c +++ b/3rd/lua/lparser.c @@ -550,6 +550,14 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { enterblock(fs, bl, 0); } +static lu_byte check_shortstring(const TValue *k, int sizek) { + int i; + for (i=0;iL; @@ -563,6 +571,8 @@ static void close_func (LexState *ls) { luaM_reallocvector(L, sp->lineinfo, sp->sizelineinfo, fs->pc, int); sp->sizelineinfo = fs->pc; luaM_reallocvector(L, f->k, sp->sizek, fs->nk, TValue); + sp->sharedk = check_shortstring(f->k, fs->nk); + sp->k = f->k; sp->sizek = fs->nk; luaM_reallocvector(L, f->p, sp->sizep, fs->np, Proto *); sp->sizep = fs->np; diff --git a/3rd/lua/lstring.c b/3rd/lua/lstring.c index b7a47fae..3bd7da69 100644 --- a/3rd/lua/lstring.c +++ b/3rd/lua/lstring.c @@ -397,7 +397,8 @@ internshrstr (lua_State *L, const char *str, size_t l) { LUA_API void luaS_expandshr(int n) { - ATOM_ADD(&SSM.n, n); + if (SSM.n < n) + ATOM_ADD(&SSM.n, n); } LUAI_FUNC TString * diff --git a/3rd/lua/lundump.c b/3rd/lua/lundump.c index bd7dd32d..86057037 100644 --- a/3rd/lua/lundump.c +++ b/3rd/lua/lundump.c @@ -119,7 +119,9 @@ static void LoadConstants (LoadState *S, Proto *f) { int i; int n = LoadInt(S); f->k = luaM_newvector(S->L, n, TValue); + f->sp->k = f->k; f->sp->sizek = n; + f->sp->sharedk = 1; for (i = 0; i < n; i++) setnilvalue(&f->k[i]); for (i = 0; i < n; i++) { @@ -139,6 +141,8 @@ static void LoadConstants (LoadState *S, Proto *f) { setivalue(o, LoadInteger(S)); break; case LUA_TSHRSTR: + f->sp->sharedk = 0; + //fall-through case LUA_TLNGSTR: setsvalue2n(S->L, o, LoadString(S)); break;