diff options
author | Alexander Lantsev <aunsane@gmail.com> | 2015-12-02 20:06:38 +0000 |
---|---|---|
committer | Alexander Lantsev <aunsane@gmail.com> | 2015-12-02 20:06:38 +0000 |
commit | 179fab6819d67b04d2d8caa13bc9fe936aff3a3c (patch) | |
tree | e402a57cb8a45e297e8fe2fcda2be0ceff5c9e2c /plugins/MirLua/src/lua | |
parent | 5291f58e733e19f44be355d76c97be4a83ab43d1 (diff) |
MirLua: updated lua to 5.3.2
git-svn-id: http://svn.miranda-ng.org/main/trunk@15807 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/MirLua/src/lua')
39 files changed, 1280 insertions, 815 deletions
diff --git a/plugins/MirLua/src/lua/lapi.c b/plugins/MirLua/src/lua/lapi.c index 52e7adfedc..9a6a3fbd0c 100644 --- a/plugins/MirLua/src/lua/lapi.c +++ b/plugins/MirLua/src/lua/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.249 2015/04/06 12:23:48 roberto Exp $ +** $Id: lapi.c,v 2.257 2015/11/02 18:48:07 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ @@ -121,11 +121,11 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { lua_lock(to); api_checknelems(from, n); api_check(from, G(from) == G(to), "moving among independent states"); - api_check(from, to->ci->top - to->top >= n, "not enough elements to move"); + api_check(from, to->ci->top - to->top >= n, "stack overflow"); from->top -= n; for (i = 0; i < n; i++) { setobj2s(to, to->top, from->top + i); - api_incr_top(to); + to->top++; /* stack already checked by previous 'api_check' */ } lua_unlock(to); } @@ -471,11 +471,16 @@ LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { } +/* +** Pushes on the stack a string with given length. Avoid using 's' when +** 'len' == 0 (as 's' can be NULL in that case), due to later use of +** 'memcmp' and 'memcpy'. +*/ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { TString *ts; lua_lock(L); luaC_checkGC(L); - ts = luaS_newlstr(L, s, len); + ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); setsvalue2s(L, L->top, ts); api_incr_top(L); lua_unlock(L); @@ -579,16 +584,27 @@ LUA_API int lua_pushthread (lua_State *L) { */ +static int auxgetstr (lua_State *L, const TValue *t, const char *k) { + const TValue *aux; + TString *str = luaS_new(L, k); + if (luaV_fastget(L, t, str, aux, luaH_getstr)) { + setobj2s(L, L->top, aux); + api_incr_top(L); + } + else { + setsvalue2s(L, L->top, str); + api_incr_top(L); + luaV_finishget(L, t, L->top - 1, L->top - 1, aux); + } + lua_unlock(L); + return ttnov(L->top - 1); +} + + LUA_API int lua_getglobal (lua_State *L, const char *name) { Table *reg = hvalue(&G(L)->l_registry); - const TValue *gt; /* global table */ lua_lock(L); - gt = luaH_getint(reg, LUA_RIDX_GLOBALS); - setsvalue2s(L, L->top, luaS_new(L, name)); - api_incr_top(L); - luaV_gettable(L, gt, L->top - 1, L->top - 1); - lua_unlock(L); - return ttnov(L->top - 1); + return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); } @@ -603,24 +619,25 @@ LUA_API int lua_gettable (lua_State *L, int idx) { LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { - StkId t; lua_lock(L); - t = index2addr(L, idx); - setsvalue2s(L, L->top, luaS_new(L, k)); - api_incr_top(L); - luaV_gettable(L, t, L->top - 1, L->top - 1); - lua_unlock(L); - return ttnov(L->top - 1); + return auxgetstr(L, index2addr(L, idx), k); } LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { StkId t; + const TValue *aux; lua_lock(L); t = index2addr(L, idx); - setivalue(L->top, n); - api_incr_top(L); - luaV_gettable(L, t, L->top - 1, L->top - 1); + if (luaV_fastget(L, t, n, aux, luaH_getint)) { + setobj2s(L, L->top, aux); + api_incr_top(L); + } + else { + setivalue(L->top, n); + api_incr_top(L); + luaV_finishget(L, t, L->top - 1, L->top - 1, aux); + } lua_unlock(L); return ttnov(L->top - 1); } @@ -719,18 +736,29 @@ LUA_API int lua_getuservalue (lua_State *L, int idx) { ** set functions (stack -> Lua) */ +/* +** t[k] = value at the top of the stack (where 'k' is a string) +*/ +static void auxsetstr (lua_State *L, const TValue *t, const char *k) { + const TValue *aux; + TString *str = luaS_new(L, k); + api_checknelems(L, 1); + if (luaV_fastset(L, t, str, aux, luaH_getstr, L->top - 1)) + L->top--; /* pop value */ + else { + setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ + api_incr_top(L); + luaV_finishset(L, t, L->top - 1, L->top - 2, aux); + L->top -= 2; /* pop value and key */ + } + lua_unlock(L); /* lock done by caller */ +} + LUA_API void lua_setglobal (lua_State *L, const char *name) { Table *reg = hvalue(&G(L)->l_registry); - const TValue *gt; /* global table */ - lua_lock(L); - api_checknelems(L, 1); - gt = luaH_getint(reg, LUA_RIDX_GLOBALS); - setsvalue2s(L, L->top, luaS_new(L, name)); - api_incr_top(L); - luaV_settable(L, gt, L->top - 1, L->top - 2); - L->top -= 2; /* pop value and key */ - lua_unlock(L); + lua_lock(L); /* unlock done in 'auxsetstr' */ + auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); } @@ -746,42 +774,40 @@ LUA_API void lua_settable (lua_State *L, int idx) { LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { - StkId t; - lua_lock(L); - api_checknelems(L, 1); - t = index2addr(L, idx); - setsvalue2s(L, L->top, luaS_new(L, k)); - api_incr_top(L); - luaV_settable(L, t, L->top - 1, L->top - 2); - L->top -= 2; /* pop value and key */ - lua_unlock(L); + lua_lock(L); /* unlock done in 'auxsetstr' */ + auxsetstr(L, index2addr(L, idx), k); } LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { StkId t; + const TValue *aux; lua_lock(L); api_checknelems(L, 1); t = index2addr(L, idx); - setivalue(L->top, n); - api_incr_top(L); - luaV_settable(L, t, L->top - 1, L->top - 2); - L->top -= 2; /* pop value and key */ + if (luaV_fastset(L, t, n, aux, luaH_getint, L->top - 1)) + L->top--; /* pop value */ + else { + setivalue(L->top, n); + api_incr_top(L); + luaV_finishset(L, t, L->top - 1, L->top - 2, aux); + L->top -= 2; /* pop value and key */ + } lua_unlock(L); } LUA_API void lua_rawset (lua_State *L, int idx) { StkId o; - Table *t; + TValue *slot; lua_lock(L); api_checknelems(L, 2); o = index2addr(L, idx); api_check(L, ttistable(o), "table expected"); - t = hvalue(o); - setobj2t(L, luaH_set(L, t, L->top-2), L->top-1); - invalidateTMcache(t); - luaC_barrierback(L, t, L->top-1); + slot = luaH_set(L, hvalue(o), L->top - 2); + setobj2t(L, slot, L->top - 1); + invalidateTMcache(hvalue(o)); + luaC_barrierback(L, hvalue(o), L->top-1); L->top -= 2; lua_unlock(L); } @@ -789,14 +815,12 @@ LUA_API void lua_rawset (lua_State *L, int idx) { LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { StkId o; - Table *t; lua_lock(L); api_checknelems(L, 1); o = index2addr(L, idx); api_check(L, ttistable(o), "table expected"); - t = hvalue(o); - luaH_setint(L, t, n, L->top - 1); - luaC_barrierback(L, t, L->top-1); + luaH_setint(L, hvalue(o), n, L->top - 1); + luaC_barrierback(L, hvalue(o), L->top-1); L->top--; lua_unlock(L); } @@ -804,16 +828,15 @@ LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { StkId o; - Table *t; - TValue k; + TValue k, *slot; lua_lock(L); api_checknelems(L, 1); o = index2addr(L, idx); api_check(L, ttistable(o), "table expected"); - t = hvalue(o); setpvalue(&k, cast(void *, p)); - setobj2t(L, luaH_set(L, t, &k), L->top - 1); - luaC_barrierback(L, t, L->top - 1); + slot = luaH_set(L, hvalue(o), &k); + setobj2t(L, slot, L->top - 1); + luaC_barrierback(L, hvalue(o), L->top - 1); L->top--; lua_unlock(L); } @@ -895,10 +918,10 @@ LUA_API void lua_callk (lua_State *L, int nargs, int nresults, if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ L->ci->u.c.k = k; /* save continuation */ L->ci->u.c.ctx = ctx; /* save context */ - luaD_call(L, func, nresults, 1); /* do the call */ + luaD_call(L, func, nresults); /* do the call */ } else /* no continuation or no yieldable */ - luaD_call(L, func, nresults, 0); /* just do the call */ + luaD_callnoyield(L, func, nresults); /* just do the call */ adjustresults(L, nresults); lua_unlock(L); } @@ -916,7 +939,7 @@ struct CallS { /* data to 'f_call' */ static void f_call (lua_State *L, void *ud) { struct CallS *c = cast(struct CallS *, ud); - luaD_call(L, c->func, c->nresults, 0); + luaD_callnoyield(L, c->func, c->nresults); } @@ -954,7 +977,7 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, L->errfunc = func; setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ - luaD_call(L, c.func, nresults, 1); /* do the call */ + luaD_call(L, c.func, nresults); /* do the call */ ci->callstatus &= ~CIST_YPCALL; L->errfunc = ci->u.c.old_errfunc; status = LUA_OK; /* if it is here, there were no errors */ @@ -1043,7 +1066,7 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { } case LUA_GCSTEP: { l_mem debt = 1; /* =1 to signal that it did an actual step */ - int oldrunning = g->gcrunning; + lu_byte oldrunning = g->gcrunning; g->gcrunning = 1; /* allow GC to run */ if (data == 0) { luaE_setdebt(g, -GCSTEPSIZE); /* to do a "small" step */ @@ -1091,6 +1114,8 @@ LUA_API int lua_error (lua_State *L) { lua_lock(L); api_checknelems(L, 1); luaG_errormsg(L); + /* code unreachable; will unlock when control actually leaves the kernel */ + return 0; /* to avoid warnings */ } diff --git a/plugins/MirLua/src/lua/lauxlib.c b/plugins/MirLua/src/lua/lauxlib.c index b8bace7f96..5d362c35a2 100644 --- a/plugins/MirLua/src/lua/lauxlib.c +++ b/plugins/MirLua/src/lua/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.280 2015/02/03 17:38:24 roberto Exp $ +** $Id: lauxlib.c,v 1.284 2015/11/19 19:16:22 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -33,8 +33,8 @@ */ -#define LEVELS1 12 /* size of the first part of the stack */ -#define LEVELS2 10 /* size of the second part of the stack */ +#define LEVELS1 10 /* size of the first part of the stack */ +#define LEVELS2 11 /* size of the second part of the stack */ @@ -107,7 +107,7 @@ static void pushfuncname (lua_State *L, lua_Debug *ar) { } -static int countlevels (lua_State *L) { +static int lastlevel (lua_State *L) { lua_Debug ar; int li = 1, le = 1; /* find an upper bound */ @@ -126,14 +126,16 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level) { lua_Debug ar; int top = lua_gettop(L); - int numlevels = countlevels(L1); - int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; - if (msg) lua_pushfstring(L, "%s\n", msg); + int last = lastlevel(L1); + int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; + if (msg) + lua_pushfstring(L, "%s\n", msg); + luaL_checkstack(L, 10, NULL); lua_pushliteral(L, "stack traceback:"); while (lua_getstack(L1, level++, &ar)) { - if (level == mark) { /* too many levels? */ + if (n1-- == 0) { /* too many levels? */ lua_pushliteral(L, "\n\t..."); /* add a '...' */ - level = numlevels - LEVELS2; /* and skip to last ones */ + level = last - LEVELS2 + 1; /* and skip to last ones */ } else { lua_getinfo(L1, "Slnt", &ar); @@ -289,7 +291,7 @@ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */ return 0; /* leave previous value on top, but return 0 */ lua_pop(L, 1); - lua_newtable(L); /* create metatable */ + lua_createtable(L, 0, 2); /* create metatable */ lua_pushstring(L, tname); lua_setfield(L, -2, "__name"); /* metatable.__name = tname */ lua_pushvalue(L, -1); @@ -435,6 +437,47 @@ LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg, ** ======================================================= */ +/* userdata to box arbitrary data */ +typedef struct UBox { + void *box; + size_t bsize; +} UBox; + + +static void *resizebox (lua_State *L, int idx, size_t newsize) { + void *ud; + lua_Alloc allocf = lua_getallocf(L, &ud); + UBox *box = (UBox *)lua_touserdata(L, idx); + void *temp = allocf(ud, box->box, box->bsize, newsize); + if (temp == NULL && newsize > 0) { /* allocation error? */ + resizebox(L, idx, 0); /* free buffer */ + luaL_error(L, "not enough memory for buffer allocation"); + } + box->box = temp; + box->bsize = newsize; + return temp; +} + + +static int boxgc (lua_State *L) { + resizebox(L, 1, 0); + return 0; +} + + +static void *newbox (lua_State *L, size_t newsize) { + UBox *box = (UBox *)lua_newuserdata(L, sizeof(UBox)); + box->box = NULL; + box->bsize = 0; + if (luaL_newmetatable(L, "LUABOX")) { /* creating metatable? */ + lua_pushcfunction(L, boxgc); + lua_setfield(L, -2, "__gc"); /* metatable.__gc = boxgc */ + } + lua_setmetatable(L, -2); + return resizebox(L, -1, newsize); +} + + /* ** check whether buffer is using a userdata on the stack as a temporary ** buffer @@ -455,11 +498,12 @@ LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { if (newsize < B->n || newsize - B->n < sz) luaL_error(L, "buffer too large"); /* create larger buffer */ - newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char)); - /* move content to new buffer */ - memcpy(newbuff, B->b, B->n * sizeof(char)); if (buffonstack(B)) - lua_remove(L, -2); /* remove old buffer */ + newbuff = (char *)resizebox(L, -1, newsize); + else { /* no buffer yet */ + newbuff = (char *)newbox(L, newsize); + memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */ + } B->b = newbuff; B->size = newsize; } @@ -468,9 +512,11 @@ LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { - char *b = luaL_prepbuffsize(B, l); - memcpy(b, s, l * sizeof(char)); - luaL_addsize(B, l); + if (l > 0) { /* avoid 'memcpy' when 's' can be NULL */ + char *b = luaL_prepbuffsize(B, l); + memcpy(b, s, l * sizeof(char)); + luaL_addsize(B, l); + } } @@ -482,8 +528,10 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { LUALIB_API void luaL_pushresult (luaL_Buffer *B) { lua_State *L = B->L; lua_pushlstring(L, B->b, B->n); - if (buffonstack(B)) - lua_remove(L, -2); /* remove old buffer */ + if (buffonstack(B)) { + resizebox(L, -2, 0); /* delete old buffer */ + lua_remove(L, -2); /* remove its header from the stack */ + } } @@ -605,7 +653,7 @@ static int errfile (lua_State *L, const char *what, int fnameindex) { static int skipBOM (LoadF *lf) { - const char *p = "\xEF\xBB\xBF"; /* Utf8 BOM mark */ + const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ int c; lf->n = 0; do { diff --git a/plugins/MirLua/src/lua/lauxlib.h b/plugins/MirLua/src/lua/lauxlib.h index 0bac2467ec..ddb7c22838 100644 --- a/plugins/MirLua/src/lua/lauxlib.h +++ b/plugins/MirLua/src/lua/lauxlib.h @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.h,v 1.128 2014/10/29 16:11:17 roberto Exp $ +** $Id: lauxlib.h,v 1.129 2015/11/23 11:29:43 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -65,7 +65,7 @@ LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); LUALIB_API int (luaL_execresult) (lua_State *L, int stat); -/* pre-defined references */ +/* predefined references */ #define LUA_NOREF (-2) #define LUA_REFNIL (-1) diff --git a/plugins/MirLua/src/lua/lbaselib.c b/plugins/MirLua/src/lua/lbaselib.c index 9a15124502..861823d8c2 100644 --- a/plugins/MirLua/src/lua/lbaselib.c +++ b/plugins/MirLua/src/lua/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.310 2015/03/28 19:14:47 roberto Exp $ +** $Id: lbaselib.c,v 1.312 2015/10/29 15:21:04 roberto Exp $ ** Basic library ** See Copyright Notice in lua.h */ @@ -86,8 +86,8 @@ static int luaB_tonumber (lua_State *L) { const char *s; lua_Integer n = 0; /* to avoid warnings */ lua_Integer base = luaL_checkinteger(L, 2); - luaL_checktype(L, 1, LUA_TSTRING); /* before 'luaL_checklstring'! */ - s = luaL_checklstring(L, 1, &l); + luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */ + s = lua_tolstring(L, 1, &l); luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); if (b_str2int(s, (int)base, &n) == s + l) { lua_pushinteger(L, n); @@ -198,12 +198,10 @@ static int luaB_collectgarbage (lua_State *L) { } -/* -** This function has all type names as upvalues, to maximize performance. -*/ static int luaB_type (lua_State *L) { - luaL_checkany(L, 1); - lua_pushvalue(L, lua_upvalueindex(lua_type(L, 1) + 1)); + int t = lua_type(L, 1); + luaL_argcheck(L, t != LUA_TNONE, 1, "value expected"); + lua_pushstring(L, lua_typename(L, t)); return 1; } @@ -243,18 +241,7 @@ static int luaB_pairs (lua_State *L) { /* -** Traversal function for 'ipairs' for raw tables -*/ -static int ipairsaux_raw (lua_State *L) { - lua_Integer i = luaL_checkinteger(L, 2) + 1; - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushinteger(L, i); - return (lua_rawgeti(L, 1, i) == LUA_TNIL) ? 1 : 2; -} - - -/* -** Traversal function for 'ipairs' for tables with metamethods +** Traversal function for 'ipairs' */ static int ipairsaux (lua_State *L) { lua_Integer i = luaL_checkinteger(L, 2) + 1; @@ -269,13 +256,11 @@ static int ipairsaux (lua_State *L) { ** that can affect the traversal. */ static int luaB_ipairs (lua_State *L) { - lua_CFunction iter = (luaL_getmetafield(L, 1, "__index") != LUA_TNIL) - ? ipairsaux : ipairsaux_raw; #if defined(LUA_COMPAT_IPAIRS) - return pairsmeta(L, "__ipairs", 1, iter); + return pairsmeta(L, "__ipairs", 1, ipairsaux); #else luaL_checkany(L, 1); - lua_pushcfunction(L, iter); /* iteration function */ + lua_pushcfunction(L, ipairsaux); /* iteration function */ lua_pushvalue(L, 1); /* state */ lua_pushinteger(L, 0); /* initial value */ return 3; @@ -490,9 +475,9 @@ static const luaL_Reg base_funcs[] = { {"setmetatable", luaB_setmetatable}, {"tonumber", luaB_tonumber}, {"tostring", luaB_tostring}, + {"type", luaB_type}, {"xpcall", luaB_xpcall}, /* placeholders */ - {"type", NULL}, {"_G", NULL}, {"_VERSION", NULL}, {NULL, NULL} @@ -500,7 +485,6 @@ static const luaL_Reg base_funcs[] = { LUAMOD_API int luaopen_base (lua_State *L) { - int i; /* open lib into global table */ lua_pushglobaltable(L); luaL_setfuncs(L, base_funcs, 0); @@ -510,11 +494,6 @@ LUAMOD_API int luaopen_base (lua_State *L) { /* set global _VERSION */ lua_pushliteral(L, LUA_VERSION); lua_setfield(L, -2, "_VERSION"); - /* set function 'type' with proper upvalues */ - for (i = 0; i < LUA_NUMTAGS; i++) /* push all type names as upvalues */ - lua_pushstring(L, lua_typename(L, i)); - lua_pushcclosure(L, luaB_type, LUA_NUMTAGS); - lua_setfield(L, -2, "type"); return 1; } diff --git a/plugins/MirLua/src/lua/lbitlib.c b/plugins/MirLua/src/lua/lbitlib.c index 15d5f0cdfc..1cb1d5b932 100644 --- a/plugins/MirLua/src/lua/lbitlib.c +++ b/plugins/MirLua/src/lua/lbitlib.c @@ -1,5 +1,5 @@ /* -** $Id: lbitlib.c,v 1.28 2014/11/02 19:19:04 roberto Exp $ +** $Id: lbitlib.c,v 1.30 2015/11/11 19:08:09 roberto Exp $ ** Standard library for bitwise operations ** See Copyright Notice in lua.h */ @@ -19,6 +19,10 @@ #if defined(LUA_COMPAT_BITLIB) /* { */ +#define pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) +#define checkunsigned(L,i) ((lua_Unsigned)luaL_checkinteger(L,i)) + + /* number of bits to consider in a number */ #if !defined(LUA_NBITS) #define LUA_NBITS 32 @@ -46,14 +50,14 @@ static lua_Unsigned andaux (lua_State *L) { int i, n = lua_gettop(L); lua_Unsigned r = ~(lua_Unsigned)0; for (i = 1; i <= n; i++) - r &= luaL_checkunsigned(L, i); + r &= checkunsigned(L, i); return trim(r); } static int b_and (lua_State *L) { lua_Unsigned r = andaux(L); - lua_pushunsigned(L, r); + pushunsigned(L, r); return 1; } @@ -69,8 +73,8 @@ static int b_or (lua_State *L) { int i, n = lua_gettop(L); lua_Unsigned r = 0; for (i = 1; i <= n; i++) - r |= luaL_checkunsigned(L, i); - lua_pushunsigned(L, trim(r)); + r |= checkunsigned(L, i); + pushunsigned(L, trim(r)); return 1; } @@ -79,15 +83,15 @@ static int b_xor (lua_State *L) { int i, n = lua_gettop(L); lua_Unsigned r = 0; for (i = 1; i <= n; i++) - r ^= luaL_checkunsigned(L, i); - lua_pushunsigned(L, trim(r)); + r ^= checkunsigned(L, i); + pushunsigned(L, trim(r)); return 1; } static int b_not (lua_State *L) { - lua_Unsigned r = ~luaL_checkunsigned(L, 1); - lua_pushunsigned(L, trim(r)); + lua_Unsigned r = ~checkunsigned(L, 1); + pushunsigned(L, trim(r)); return 1; } @@ -104,23 +108,23 @@ static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) { else r <<= i; r = trim(r); } - lua_pushunsigned(L, r); + pushunsigned(L, r); return 1; } static int b_lshift (lua_State *L) { - return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkinteger(L, 2)); + return b_shift(L, checkunsigned(L, 1), luaL_checkinteger(L, 2)); } static int b_rshift (lua_State *L) { - return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkinteger(L, 2)); + return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2)); } static int b_arshift (lua_State *L) { - lua_Unsigned r = luaL_checkunsigned(L, 1); + lua_Unsigned r = checkunsigned(L, 1); lua_Integer i = luaL_checkinteger(L, 2); if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1)))) return b_shift(L, r, -i); @@ -128,19 +132,19 @@ static int b_arshift (lua_State *L) { if (i >= LUA_NBITS) r = ALLONES; else r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i)); /* add signal bit */ - lua_pushunsigned(L, r); + pushunsigned(L, r); return 1; } } static int b_rot (lua_State *L, lua_Integer d) { - lua_Unsigned r = luaL_checkunsigned(L, 1); + lua_Unsigned r = checkunsigned(L, 1); int i = d & (LUA_NBITS - 1); /* i = d % NBITS */ r = trim(r); if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */ r = (r << i) | (r >> (LUA_NBITS - i)); - lua_pushunsigned(L, trim(r)); + pushunsigned(L, trim(r)); return 1; } @@ -175,23 +179,22 @@ static int fieldargs (lua_State *L, int farg, int *width) { static int b_extract (lua_State *L) { int w; - lua_Unsigned r = trim(luaL_checkunsigned(L, 1)); + lua_Unsigned r = trim(checkunsigned(L, 1)); int f = fieldargs(L, 2, &w); r = (r >> f) & mask(w); - lua_pushunsigned(L, r); + pushunsigned(L, r); return 1; } static int b_replace (lua_State *L) { int w; - lua_Unsigned r = trim(luaL_checkunsigned(L, 1)); - lua_Unsigned v = luaL_checkunsigned(L, 2); + lua_Unsigned r = trim(checkunsigned(L, 1)); + lua_Unsigned v = trim(checkunsigned(L, 2)); int f = fieldargs(L, 3, &w); - int m = mask(w); - v &= m; /* erase bits outside given width */ - r = (r & ~(m << f)) | (v << f); - lua_pushunsigned(L, r); + lua_Unsigned m = mask(w); + r = (r & ~(m << f)) | ((v & m) << f); + pushunsigned(L, r); return 1; } diff --git a/plugins/MirLua/src/lua/lcode.c b/plugins/MirLua/src/lua/lcode.c index d6f0fcd847..7c6918fda4 100644 --- a/plugins/MirLua/src/lua/lcode.c +++ b/plugins/MirLua/src/lua/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.101 2015/04/29 18:24:11 roberto Exp $ +** $Id: lcode.c,v 2.103 2015/11/19 19:16:22 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -37,7 +37,7 @@ static int tonumeral(expdesc *e, TValue *v) { - if (e->t != NO_JUMP || e->f != NO_JUMP) + if (hasjumps(e)) return 0; /* not a numeral */ switch (e->k) { case VKINT: @@ -816,7 +816,7 @@ static void codeexpval (FuncState *fs, OpCode op, freeexp(fs, e1); } e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); /* generate opcode */ - e1->k = VRELOCABLE; /* all those operations are relocable */ + e1->k = VRELOCABLE; /* all those operations are relocatable */ luaK_fixline(fs, line); } } diff --git a/plugins/MirLua/src/lua/ldblib.c b/plugins/MirLua/src/lua/ldblib.c index 915145845e..786f6cd95d 100644 --- a/plugins/MirLua/src/lua/ldblib.c +++ b/plugins/MirLua/src/lua/ldblib.c @@ -1,5 +1,5 @@ /* -** $Id: ldblib.c,v 1.149 2015/02/19 17:06:21 roberto Exp $ +** $Id: ldblib.c,v 1.151 2015/11/23 11:29:43 roberto Exp $ ** Interface from Lua to its debug API ** See Copyright Notice in lua.h */ @@ -28,8 +28,8 @@ static const int HOOKKEY = 0; /* -** If L1 != L, L1 can be in any state, and therefore there is no -** garanties about its stack space; any push in L1 must be +** If L1 != L, L1 can be in any state, and therefore there are no +** guarantees about its stack space; any push in L1 must be ** checked. */ static void checkstack (lua_State *L, lua_State *L1, int n) { diff --git a/plugins/MirLua/src/lua/ldebug.c b/plugins/MirLua/src/lua/ldebug.c index f76582c5b5..9bd86d0294 100644 --- a/plugins/MirLua/src/lua/ldebug.c +++ b/plugins/MirLua/src/lua/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.115 2015/05/22 17:45:56 roberto Exp $ +** $Id: ldebug.c,v 2.117 2015/11/02 18:48:07 roberto Exp $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -618,7 +618,7 @@ l_noret luaG_errormsg (lua_State *L) { setobjs2s(L, L->top, L->top - 1); /* move argument */ setobjs2s(L, L->top - 1, errfunc); /* push function */ L->top++; /* assume EXTRA_STACK */ - luaD_call(L, L->top - 2, 1, 0); /* call it */ + luaD_callnoyield(L, L->top - 2, 1); /* call it */ } luaD_throw(L, LUA_ERRRUN); } @@ -640,9 +640,11 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { void luaG_traceexec (lua_State *L) { CallInfo *ci = L->ci; lu_byte mask = L->hookmask; - int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0); + int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); if (counthook) resethookcount(L); /* reset count */ + else if (!(mask & LUA_MASKLINE)) + return; /* no line hook and count != 0; nothing to be done */ if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ return; /* do not call hook again (VM yielded, so it did not move) */ diff --git a/plugins/MirLua/src/lua/ldo.c b/plugins/MirLua/src/lua/ldo.c index 5c93a259fe..95efd56068 100644 --- a/plugins/MirLua/src/lua/ldo.c +++ b/plugins/MirLua/src/lua/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.138 2015/05/22 17:48:19 roberto Exp $ +** $Id: ldo.c,v 2.150 2015/11/19 19:16:22 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -150,6 +150,11 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { /* }====================================================== */ +/* +** {================================================================== +** Stack reallocation +** =================================================================== +*/ static void correctstack (lua_State *L, TValue *oldstack) { CallInfo *ci; UpVal *up; @@ -221,13 +226,21 @@ void luaD_shrinkstack (lua_State *L) { luaE_freeCI(L); /* free all CIs (list grew because of an error) */ else luaE_shrinkCI(L); /* shrink list */ - if (inuse > LUAI_MAXSTACK || /* still handling stack overflow? */ - goodsize >= L->stacksize) /* would grow instead of shrink? */ - condmovestack(L); /* don't change stack (change only for debugging) */ - else + if (inuse <= LUAI_MAXSTACK && /* not handling stack overflow? */ + goodsize < L->stacksize) /* trying to shrink? */ luaD_reallocstack(L, goodsize); /* shrink it */ + else + condmovestack(L,,); /* don't change stack (change only for debugging) */ +} + + +void luaD_inctop (lua_State *L) { + luaD_checkstack(L, 1); + L->top++; } +/* }================================================================== */ + void luaD_hook (lua_State *L, int event, int line) { lua_Hook hook = L->hook; @@ -273,15 +286,15 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { int i; int nfixargs = p->numparams; StkId base, fixed; - lua_assert(actual >= nfixargs); /* move fixed parameters to final position */ - luaD_checkstack(L, p->maxstacksize); /* check again for new 'base' */ fixed = L->top - actual; /* first fixed argument */ base = L->top; /* final position of first argument */ - for (i=0; i<nfixargs; i++) { + for (i = 0; i < nfixargs && i < actual; i++) { setobjs2s(L, L->top++, fixed + i); - setnilvalue(fixed + i); + setnilvalue(fixed + i); /* erase original copy (for GC) */ } + for (; i < nfixargs; i++) + setnilvalue(L->top++); /* complete missing arguments */ return base; } @@ -308,26 +321,36 @@ static void tryfuncTM (lua_State *L, StkId func) { #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) +/* macro to check stack size, preserving 'p' */ +#define checkstackp(L,n,p) \ + luaD_checkstackaux(L, n, \ + ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ + luaC_checkGC(L), /* stack grow uses memory */ \ + p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ + + /* -** returns true if function has been executed (C function) +** Prepares a function call: checks the stack, creates a new CallInfo +** entry, fills in the relevant information, calls hook if needed. +** If function is a C function, does the call, too. (Otherwise, leave +** the execution ('luaV_execute') to the caller, to allow stackless +** calls.) Returns true iff function has been executed (C function). */ int luaD_precall (lua_State *L, StkId func, int nresults) { lua_CFunction f; CallInfo *ci; - int n; /* number of arguments (Lua) or returns (C) */ - ptrdiff_t funcr = savestack(L, func); switch (ttype(func)) { + case LUA_TCCL: /* C closure */ + f = clCvalue(func)->f; + goto Cfunc; case LUA_TLCF: /* light C function */ f = fvalue(func); - goto Cfunc; - case LUA_TCCL: { /* C closure */ - f = clCvalue(func)->f; - Cfunc: - luaC_checkGC(L); /* stack grow uses memory */ - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + Cfunc: { + int n; /* number of returns */ + checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ ci = next_ci(L); /* now 'enter' new function */ ci->nresults = nresults; - ci->func = restorestack(L, funcr); + ci->func = func; ci->top = L->top + LUA_MINSTACK; lua_assert(ci->top <= L->stack_last); ci->callstatus = 0; @@ -337,41 +360,36 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { n = (*f)(L); /* do the actual call */ lua_lock(L); api_checknelems(L, n); - luaD_poscall(L, L->top - n, n); + luaD_poscall(L, ci, L->top - n, n); return 1; } case LUA_TLCL: { /* Lua function: prepare its call */ StkId base; Proto *p = clLvalue(func)->p; - n = cast_int(L->top - func) - 1; /* number of real arguments */ - luaC_checkGC(L); /* stack grow uses memory */ - luaD_checkstack(L, p->maxstacksize); - for (; n < p->numparams; n++) - setnilvalue(L->top++); /* complete missing arguments */ - if (!p->is_vararg) { - func = restorestack(L, funcr); + int n = cast_int(L->top - func) - 1; /* number of real arguments */ + int fsize = p->maxstacksize; /* frame size */ + checkstackp(L, fsize, func); + if (p->is_vararg != 1) { /* do not use vararg? */ + for (; n < p->numparams; n++) + setnilvalue(L->top++); /* complete missing arguments */ base = func + 1; } - else { + else base = adjust_varargs(L, p, n); - func = restorestack(L, funcr); /* previous call can change stack */ - } ci = next_ci(L); /* now 'enter' new function */ ci->nresults = nresults; ci->func = func; ci->u.l.base = base; - ci->top = base + p->maxstacksize; + L->top = ci->top = base + fsize; lua_assert(ci->top <= L->stack_last); ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus = CIST_LUA; - L->top = ci->top; if (L->hookmask & LUA_MASKCALL) callhook(L, ci); return 0; } default: { /* not a function */ - luaD_checkstack(L, 1); /* ensure space for metamethod */ - func = restorestack(L, funcr); /* previous call may change stack */ + checkstackp(L, 1, func); /* ensure space for metamethod */ tryfuncTM(L, func); /* try to get '__call' metamethod */ return luaD_precall(L, func, nresults); /* now it must be a function */ } @@ -379,10 +397,57 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { } -int luaD_poscall (lua_State *L, StkId firstResult, int nres) { +/* +** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'. +** Handle most typical cases (zero results for commands, one result for +** expressions, multiple results for tail calls/single parameters) +** separated. +*/ +static int moveresults (lua_State *L, const TValue *firstResult, StkId res, + int nres, int wanted) { + switch (wanted) { /* handle typical cases separately */ + case 0: break; /* nothing to move */ + case 1: { /* one result needed */ + if (nres == 0) /* no results? */ + firstResult = luaO_nilobject; /* adjust with nil */ + setobjs2s(L, res, firstResult); /* move it to proper place */ + break; + } + case LUA_MULTRET: { + int i; + for (i = 0; i < nres; i++) /* move all results to correct place */ + setobjs2s(L, res + i, firstResult + i); + L->top = res + nres; + return 0; /* wanted == LUA_MULTRET */ + } + default: { + int i; + if (wanted <= nres) { /* enough results? */ + for (i = 0; i < wanted; i++) /* move wanted results to correct place */ + setobjs2s(L, res + i, firstResult + i); + } + else { /* not enough results; use all of them plus nils */ + for (i = 0; i < nres; i++) /* move all results to correct place */ + setobjs2s(L, res + i, firstResult + i); + for (; i < wanted; i++) /* complete wanted number of results */ + setnilvalue(res + i); + } + break; + } + } + L->top = res + wanted; /* top points after the last result */ + return 1; +} + + +/* +** Finishes a function call: calls hook if necessary, removes CallInfo, +** moves current number of results to proper place; returns 0 iff call +** wanted multiple (variable number of) results. +*/ +int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { StkId res; - int wanted, i; - CallInfo *ci = L->ci; + int wanted = ci->nresults; if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { if (L->hookmask & LUA_MASKRET) { ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ @@ -392,15 +457,24 @@ int luaD_poscall (lua_State *L, StkId firstResult, int nres) { L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ } res = ci->func; /* res == final position of 1st result */ - wanted = ci->nresults; L->ci = ci->previous; /* back to caller */ - /* move results to correct place */ - for (i = wanted; i != 0 && nres-- > 0; i--) - setobjs2s(L, res++, firstResult++); - while (i-- > 0) - setnilvalue(res++); - L->top = res; - return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ + /* move results to proper place */ + return moveresults(L, firstResult, res, nres, wanted); +} + + +/* +** Check appropriate error for stack overflow ("regular" overflow or +** overflow while handling stack overflow). If 'nCalls' is larger than +** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but +** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to +** allow overflow handling to work) +*/ +static void stackerror (lua_State *L) { + if (L->nCcalls == LUAI_MAXCCALLS) + luaG_runerror(L, "C stack overflow"); + else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ } @@ -410,22 +484,26 @@ int luaD_poscall (lua_State *L, StkId firstResult, int nres) { ** When returns, all the results are on the stack, starting at the original ** function position. */ -void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) { - if (++L->nCcalls >= LUAI_MAXCCALLS) { - if (L->nCcalls == LUAI_MAXCCALLS) - luaG_runerror(L, "C stack overflow"); - else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) - luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ - } - if (!allowyield) L->nny++; +void luaD_call (lua_State *L, StkId func, int nResults) { + if (++L->nCcalls >= LUAI_MAXCCALLS) + stackerror(L); if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ luaV_execute(L); /* call it */ - if (!allowyield) L->nny--; L->nCcalls--; } /* +** Similar to 'luaD_call', but does not allow yields during the call +*/ +void luaD_callnoyield (lua_State *L, StkId func, int nResults) { + L->nny++; + luaD_call(L, func, nResults); + L->nny--; +} + + +/* ** Completes the execution of an interrupted C function, calling its ** continuation function. */ @@ -449,7 +527,7 @@ static void finishCcall (lua_State *L, int status) { lua_lock(L); api_checknelems(L, n); /* finish 'luaD_precall' */ - luaD_poscall(L, L->top - n, n); + luaD_poscall(L, ci, L->top - n, n); } @@ -560,7 +638,7 @@ static void resume (lua_State *L, void *ud) { api_checknelems(L, n); firstArg = L->top - n; /* yield results come from continuation */ } - luaD_poscall(L, firstArg, n); /* finish 'luaD_precall' */ + luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_precall' */ } unroll(L, NULL); /* run continuation */ } @@ -570,7 +648,7 @@ static void resume (lua_State *L, void *ud) { LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { int status; - int oldnny = L->nny; /* save "number of non-yieldable" calls */ + unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */ lua_lock(L); luai_userstateresume(L, nargs); L->nCcalls = (from) ? from->nCcalls + 1 : 1; @@ -684,7 +762,7 @@ static void f_parser (lua_State *L, void *ud) { int c = zgetc(p->z); /* read first character */ if (c == LUA_SIGNATURE[0]) { checkmode(L, p->mode, "binary"); - cl = luaU_undump(L, p->z, &p->buff, p->name); + cl = luaU_undump(L, p->z, p->name); } else { checkmode(L, p->mode, "text"); diff --git a/plugins/MirLua/src/lua/ldo.h b/plugins/MirLua/src/lua/ldo.h index edade657c7..80582dc2e3 100644 --- a/plugins/MirLua/src/lua/ldo.h +++ b/plugins/MirLua/src/lua/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 2.22 2015/05/22 17:48:19 roberto Exp $ +** $Id: ldo.h,v 2.28 2015/11/23 11:29:43 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -13,11 +13,21 @@ #include "lzio.h" -#define luaD_checkstack(L,n) if (L->stack_last - L->top <= (n)) \ - luaD_growstack(L, n); else condmovestack(L); +/* +** Macro to check stack size and grow stack if needed. Parameters +** 'pre'/'pos' allow the macro to preserve a pointer into the +** stack across reallocations, doing the work only when needed. +** 'condmovestack' is used in heavy tests to force a stack reallocation +** at every check. +*/ +#define luaD_checkstackaux(L,n,pre,pos) \ + if (L->stack_last - L->top <= (n)) \ + { pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); } + +/* In general, 'pre'/'pos' are empty (nothing to save) */ +#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,,) -#define incr_top(L) {L->top++; luaD_checkstack(L,0);} #define savestack(L,p) ((char *)(p) - (char *)L->stack) #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) @@ -30,14 +40,16 @@ LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, const char *mode); LUAI_FUNC void luaD_hook (lua_State *L, int event, int line); LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); -LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults, - int allowyield); +LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); +LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t oldtop, ptrdiff_t ef); -LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult, int nres); +LUAI_FUNC int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, + int nres); LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); LUAI_FUNC void luaD_growstack (lua_State *L, int n); LUAI_FUNC void luaD_shrinkstack (lua_State *L); +LUAI_FUNC void luaD_inctop (lua_State *L); LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); diff --git a/plugins/MirLua/src/lua/ldump.c b/plugins/MirLua/src/lua/ldump.c index 4c04812a78..016e300822 100644 --- a/plugins/MirLua/src/lua/ldump.c +++ b/plugins/MirLua/src/lua/ldump.c @@ -1,5 +1,5 @@ /* -** $Id: ldump.c,v 2.36 2015/03/30 15:43:51 roberto Exp $ +** $Id: ldump.c,v 2.37 2015/10/08 15:53:49 roberto Exp $ ** save precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -38,7 +38,7 @@ typedef struct { static void DumpBlock (const void *b, size_t size, DumpState *D) { - if (D->status == 0) { + if (D->status == 0 && size > 0) { lua_unlock(D->L); D->status = (*D->writer)(D->L, b, size, D->data); lua_lock(D->L); diff --git a/plugins/MirLua/src/lua/lgc.c b/plugins/MirLua/src/lua/lgc.c index 973c269f73..49d8ecb7c3 100644 --- a/plugins/MirLua/src/lua/lgc.c +++ b/plugins/MirLua/src/lua/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.205 2015/03/25 13:42:19 roberto Exp $ +** $Id: lgc.c,v 2.210 2015/11/03 18:10:44 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -114,8 +114,13 @@ static void reallymarkobject (global_State *g, GCObject *o); /* -** if key is not marked, mark its entry as dead (therefore removing it -** from the table) +** If key is not marked, mark its entry as dead. This allows key to be +** collected, but keeps its entry in the table. A dead node is needed +** when Lua looks up for a key (it may be part of a chain) and when +** traversing a weak table (key might be removed from the table during +** traversal). Other places never manipulate dead keys, because its +** associated nil value is enough to signal that the entry is logically +** empty. */ static void removeentry (Node *n) { lua_assert(ttisnil(gval(n))); @@ -542,7 +547,8 @@ static lu_mem traversethread (global_State *g, lua_State *th) { } else if (g->gckind != KGC_EMERGENCY) luaD_shrinkstack(th); /* do not change stack in emergency cycle */ - return (sizeof(lua_State) + sizeof(TValue) * th->stacksize); + return (sizeof(lua_State) + sizeof(TValue) * th->stacksize + + sizeof(CallInfo) * th->nci); } @@ -769,12 +775,11 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) { */ /* -** If possible, free concatenation buffer and shrink string table +** If possible, shrink string table */ static void checkSizes (lua_State *L, global_State *g) { if (g->gckind != KGC_EMERGENCY) { l_mem olddebt = g->GCdebt; - luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ luaS_resize(L, g->strt.size / 2); /* shrink it a little */ g->GCestimate += g->GCdebt - olddebt; /* update estimate */ @@ -797,7 +802,7 @@ static GCObject *udata2finalize (global_State *g) { static void dothecall (lua_State *L, void *ud) { UNUSED(ud); - luaD_call(L, L->top - 2, 0, 0); + luaD_callnoyield(L, L->top - 2, 0); } @@ -1114,9 +1119,12 @@ void luaC_runtilstate (lua_State *L, int statesmask) { static l_mem getdebt (global_State *g) { l_mem debt = g->GCdebt; int stepmul = g->gcstepmul; - debt = (debt / STEPMULADJ) + 1; - debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; - return debt; + if (debt <= 0) return 0; /* minimal debt */ + else { + debt = (debt / STEPMULADJ) + 1; + debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; + return debt; + } } /* diff --git a/plugins/MirLua/src/lua/lgc.h b/plugins/MirLua/src/lua/lgc.h index 0eedf84204..1775ca4595 100644 --- a/plugins/MirLua/src/lua/lgc.h +++ b/plugins/MirLua/src/lua/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.86 2014/10/25 11:50:46 roberto Exp $ +** $Id: lgc.h,v 2.90 2015/10/21 18:15:15 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -101,26 +101,35 @@ #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) -#define luaC_condGC(L,c) \ - {if (G(L)->GCdebt > 0) {c;}; condchangemem(L);} -#define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);) +/* +** Does one step of collection when debt becomes positive. 'pre'/'pos' +** allows some adjustments to be done only when needed. macro +** 'condchangemem' is used only for heavy tests (forcing a full +** GC cycle on every opportunity) +*/ +#define luaC_condGC(L,pre,pos) \ + { if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \ + condchangemem(L,pre,pos); } + +/* more often than not, 'pre'/'pos' are empty */ +#define luaC_checkGC(L) luaC_condGC(L,,) -#define luaC_barrier(L,p,v) { \ - if (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) \ - luaC_barrier_(L,obj2gco(p),gcvalue(v)); } +#define luaC_barrier(L,p,v) ( \ + (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ + luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0)) -#define luaC_barrierback(L,p,v) { \ - if (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) \ - luaC_barrierback_(L,p); } +#define luaC_barrierback(L,p,v) ( \ + (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ + luaC_barrierback_(L,p) : cast_void(0)) -#define luaC_objbarrier(L,p,o) { \ - if (isblack(p) && iswhite(o)) \ - luaC_barrier_(L,obj2gco(p),obj2gco(o)); } +#define luaC_objbarrier(L,p,o) ( \ + (isblack(p) && iswhite(o)) ? \ + luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0)) -#define luaC_upvalbarrier(L,uv) \ - { if (iscollectable((uv)->v) && !upisopen(uv)) \ - luaC_upvalbarrier_(L,uv); } +#define luaC_upvalbarrier(L,uv) ( \ + (iscollectable((uv)->v) && !upisopen(uv)) ? \ + luaC_upvalbarrier_(L,uv) : cast_void(0)) LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); LUAI_FUNC void luaC_freeallobjects (lua_State *L); diff --git a/plugins/MirLua/src/lua/liolib.c b/plugins/MirLua/src/lua/liolib.c index 193cac6777..a91ba39181 100644 --- a/plugins/MirLua/src/lua/liolib.c +++ b/plugins/MirLua/src/lua/liolib.c @@ -1,5 +1,5 @@ /* -** $Id: liolib.c,v 2.144 2015/04/03 18:41:57 roberto Exp $ +** $Id: liolib.c,v 2.148 2015/11/23 11:36:11 roberto Exp $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ @@ -23,18 +23,24 @@ #include "lualib.h" -#if !defined(l_checkmode) + /* -** Check whether 'mode' matches '[rwa]%+?b?'. ** Change this macro to accept other modes for 'fopen' besides ** the standard ones. */ +#if !defined(l_checkmode) + +/* accepted extensions to 'mode' in 'fopen' */ +#if !defined(L_MODEEXT) +#define L_MODEEXT "b" +#endif + +/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */ #define l_checkmode(mode) \ (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \ - (*mode != '+' || ++mode) && /* skip if char is '+' */ \ - (*mode != 'b' || ++mode) && /* skip if char is 'b' */ \ - (*mode == '\0')) + (*mode != '+' || (++mode, 1)) && /* skip if char is '+' */ \ + (strspn(mode, L_MODEEXT) == strlen(mode))) #endif @@ -176,7 +182,7 @@ static FILE *tofile (lua_State *L) { /* ** When creating file handles, always creates a 'closed' file handle ** before opening the actual file; so, if there is a memory error, the -** file is not left opened. +** handle is in a consistent state. */ static LStream *newprefile (lua_State *L) { LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); @@ -318,8 +324,15 @@ static int io_output (lua_State *L) { static int io_readline (lua_State *L); +/* +** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit +** in the limit for upvalues of a closure) +*/ +#define MAXARGLINE 250 + static void aux_lines (lua_State *L, int toclose) { int n = lua_gettop(L) - 1; /* number of arguments to read */ + luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments"); lua_pushinteger(L, n); /* number of arguments to read */ lua_pushboolean(L, toclose); /* close/not close file when finished */ lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */ @@ -462,7 +475,7 @@ static int read_line (lua_State *L, FILE *f, int chop) { int c = '\0'; luaL_buffinit(L, &b); while (c != EOF && c != '\n') { /* repeat until end of line */ - char *buff = luaL_prepbuffer(&b); /* pre-allocate buffer */ + char *buff = luaL_prepbuffer(&b); /* preallocate buffer */ int i = 0; l_lockfile(f); /* no memory errors can happen inside the lock */ while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n') @@ -483,7 +496,7 @@ static void read_all (lua_State *L, FILE *f) { luaL_Buffer b; luaL_buffinit(L, &b); do { /* read file in chunks of LUAL_BUFFERSIZE bytes */ - char *p = luaL_prepbuffsize(&b, LUAL_BUFFERSIZE); + char *p = luaL_prepbuffer(&b); nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f); luaL_addsize(&b, nr); } while (nr == LUAL_BUFFERSIZE); diff --git a/plugins/MirLua/src/lua/llex.c b/plugins/MirLua/src/lua/llex.c index c35bd55fa7..16ea3ebebe 100644 --- a/plugins/MirLua/src/lua/llex.c +++ b/plugins/MirLua/src/lua/llex.c @@ -1,5 +1,5 @@ /* -** $Id: llex.c,v 2.93 2015/05/22 17:45:56 roberto Exp $ +** $Id: llex.c,v 2.95 2015/11/19 19:16:22 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -220,8 +220,6 @@ static void buffreplace (LexState *ls, char from, char to) { } -#define buff2num(b,o) (luaO_str2num(luaZ_buffer(b), o) != 0) - /* ** in case of format error, try to change decimal point separator to ** the one defined in the current locale and check again @@ -230,7 +228,7 @@ static void trydecpoint (LexState *ls, TValue *o) { char old = ls->decpoint; ls->decpoint = lua_getlocaledecpoint(); buffreplace(ls, old, ls->decpoint); /* try new decimal separator */ - if (!buff2num(ls->buff, o)) { + if (luaO_str2num(luaZ_buffer(ls->buff), o) == 0) { /* format error with correct decimal point: no more options */ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ lexerror(ls, "malformed number", TK_FLT); @@ -262,7 +260,7 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) { } save(ls, '\0'); buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ - if (!buff2num(ls->buff, &obj)) /* format error? */ + if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */ trydecpoint(ls, &obj); /* try to update decimal point separator */ if (ttisinteger(&obj)) { seminfo->i = ivalue(&obj); @@ -277,7 +275,7 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) { /* -** skip a sequence '[=*[' or ']=*]'; if sequence is wellformed, return +** skip a sequence '[=*[' or ']=*]'; if sequence is well formed, return ** its number of '='s; otherwise, return a negative number (-1 iff there ** are no '='s after initial bracket) */ diff --git a/plugins/MirLua/src/lua/llimits.h b/plugins/MirLua/src/lua/llimits.h index 277c724d90..f21377fef9 100644 --- a/plugins/MirLua/src/lua/llimits.h +++ b/plugins/MirLua/src/lua/llimits.h @@ -1,5 +1,5 @@ /* -** $Id: llimits.h,v 1.135 2015/06/09 14:21:00 roberto Exp $ +** $Id: llimits.h,v 1.141 2015/11/19 19:16:22 roberto Exp $ ** Limits, basic types, and some other 'installation-dependent' definitions ** See Copyright Notice in lua.h */ @@ -64,7 +64,13 @@ typedef unsigned char lu_byte; #if defined(LUAI_USER_ALIGNMENT_T) typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; #else -typedef union { double u; void *s; lua_Integer i; long l; } L_Umaxalign; +typedef union { + lua_Number n; + double u; + void *s; + lua_Integer i; + long l; +} L_Umaxalign; #endif @@ -78,7 +84,7 @@ typedef LUAI_UACINT l_uacInt; #if defined(lua_assert) #define check_exp(c,e) (lua_assert(c), (e)) /* to avoid problems with conditions too long */ -#define lua_longassert(c) { if (!(c)) lua_assert(0); } +#define lua_longassert(c) ((c) ? (void)0 : lua_assert(0)) #else #define lua_assert(c) ((void)0) #define check_exp(c,e) (e) @@ -184,10 +190,13 @@ typedef unsigned long Instruction; /* -** Size of cache for strings in the API (better be a prime) +** Size of cache for strings in the API. 'N' is the number of +** sets (better be a prime) and "M" is the size of each set (M == 1 +** makes a direct cache.) */ -#if !defined(STRCACHE_SIZE) -#define STRCACHE_SIZE 127 +#if !defined(STRCACHE_N) +#define STRCACHE_N 53 +#define STRCACHE_M 2 #endif @@ -198,7 +207,7 @@ typedef unsigned long Instruction; /* -** macros that are executed whenether program enters the Lua core +** macros that are executed whenever program enters the Lua core ** ('lua_lock') and leaves the core ('lua_unlock') */ #if !defined(lua_lock) @@ -297,17 +306,18 @@ typedef unsigned long Instruction; ** macro to control inclusion of some hard tests on stack reallocation */ #if !defined(HARDSTACKTESTS) -#define condmovestack(L) ((void)0) +#define condmovestack(L,pre,pos) ((void)0) #else /* realloc stack keeping its size */ -#define condmovestack(L) luaD_reallocstack((L), (L)->stacksize) +#define condmovestack(L,pre,pos) \ + { int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_); pos; } #endif #if !defined(HARDMEMTESTS) -#define condchangemem(L) condmovestack(L) +#define condchangemem(L,pre,pos) ((void)0) #else -#define condchangemem(L) \ - ((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1))) +#define condchangemem(L,pre,pos) \ + { if (G(L)->gcrunning) { pre; luaC_fullgc(L, 0); pos; } } #endif #endif diff --git a/plugins/MirLua/src/lua/lmathlib.c b/plugins/MirLua/src/lua/lmathlib.c index 4f2ec60aa2..94815f129f 100644 --- a/plugins/MirLua/src/lua/lmathlib.c +++ b/plugins/MirLua/src/lua/lmathlib.c @@ -1,5 +1,5 @@ /* -** $Id: lmathlib.c,v 1.115 2015/03/12 14:04:04 roberto Exp $ +** $Id: lmathlib.c,v 1.117 2015/10/02 15:39:23 roberto Exp $ ** Standard mathematical library ** See Copyright Notice in lua.h */ @@ -39,7 +39,7 @@ static int math_abs (lua_State *L) { if (lua_isinteger(L, 1)) { lua_Integer n = lua_tointeger(L, 1); - if (n < 0) n = (lua_Integer)(0u - n); + if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n); lua_pushinteger(L, n); } else @@ -273,7 +273,7 @@ static int math_random (lua_State *L) { static int math_randomseed (lua_State *L) { l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1)); - (void)rand(); /* discard first value to avoid undesirable correlations */ + (void)l_rand(); /* discard first value to avoid undesirable correlations */ return 0; } diff --git a/plugins/MirLua/src/lua/loadlib.c b/plugins/MirLua/src/lua/loadlib.c index bbf8f67afb..79119287ae 100644 --- a/plugins/MirLua/src/lua/loadlib.c +++ b/plugins/MirLua/src/lua/loadlib.c @@ -1,5 +1,5 @@ /* -** $Id: loadlib.c,v 1.126 2015/02/16 13:14:33 roberto Exp $ +** $Id: loadlib.c,v 1.127 2015/11/23 11:30:45 roberto Exp $ ** Dynamic library loader for Lua ** See Copyright Notice in lua.h ** @@ -732,7 +732,7 @@ static void createsearcherstable (lua_State *L) { int i; /* create 'searchers' table */ lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); - /* fill it with pre-defined searchers */ + /* fill it with predefined searchers */ for (i=0; searchers[i] != NULL; i++) { lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ lua_pushcclosure(L, searchers[i], 1); diff --git a/plugins/MirLua/src/lua/lobject.c b/plugins/MirLua/src/lua/lobject.c index 6c53b981df..e24723febe 100644 --- a/plugins/MirLua/src/lua/lobject.c +++ b/plugins/MirLua/src/lua/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 2.104 2015/04/11 18:30:08 roberto Exp $ +** $Id: lobject.c,v 2.108 2015/11/02 16:09:30 roberto Exp $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -55,9 +55,7 @@ int luaO_int2fb (unsigned int x) { /* converts back */ int luaO_fb2int (int x) { - int e = (x >> 3) & 0x1f; - if (e == 0) return x; - else return ((x & 7) + 8) << (e - 1); + return (x < 8) ? x : ((x & 7) + 8) << ((x >> 3) - 1); } @@ -333,9 +331,9 @@ void luaO_tostring (lua_State *L, StkId obj) { size_t len; lua_assert(ttisnumber(obj)); if (ttisinteger(obj)) - len = lua_integer2str(buff, ivalue(obj)); + len = lua_integer2str(buff, sizeof(buff), ivalue(obj)); else { - len = lua_number2str(buff, fltvalue(obj)); + len = lua_number2str(buff, sizeof(buff), fltvalue(obj)); #if !defined(LUA_COMPAT_FLOATSTRING) if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ buff[len++] = lua_getlocaledecpoint(); @@ -348,7 +346,8 @@ void luaO_tostring (lua_State *L, StkId obj) { static void pushstr (lua_State *L, const char *str, size_t l) { - setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); + setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); + luaD_inctop(L); } @@ -359,7 +358,6 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { for (;;) { const char *e = strchr(fmt, '%'); if (e == NULL) break; - luaD_checkstack(L, 2); /* fmt + item */ pushstr(L, fmt, e - fmt); switch (*(e+1)) { case 's': { @@ -377,23 +375,23 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { break; } case 'd': { - setivalue(L->top++, va_arg(argp, int)); - luaO_tostring(L, L->top - 1); - break; + setivalue(L->top, va_arg(argp, int)); + goto top2str; } case 'I': { - setivalue(L->top++, cast(lua_Integer, va_arg(argp, l_uacInt))); - luaO_tostring(L, L->top - 1); - break; + setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt))); + goto top2str; } case 'f': { - setfltvalue(L->top++, cast_num(va_arg(argp, l_uacNumber))); + setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); + top2str: + luaD_inctop(L); luaO_tostring(L, L->top - 1); break; } case 'p': { char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */ - int l = sprintf(buff, "%p", va_arg(argp, void *)); + int l = l_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *)); pushstr(L, buff, l); break; } diff --git a/plugins/MirLua/src/lua/lobject.h b/plugins/MirLua/src/lua/lobject.h index 9230b7a9f8..2d52b41592 100644 --- a/plugins/MirLua/src/lua/lobject.h +++ b/plugins/MirLua/src/lua/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.111 2015/06/09 14:21:42 roberto Exp $ +** $Id: lobject.h,v 2.116 2015/11/03 18:33:10 roberto Exp $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -19,8 +19,8 @@ /* ** Extra tags for non-values */ -#define LUA_TPROTO LUA_NUMTAGS -#define LUA_TDEADKEY (LUA_NUMTAGS+1) +#define LUA_TPROTO LUA_NUMTAGS /* function prototypes */ +#define LUA_TDEADKEY (LUA_NUMTAGS+1) /* removed keys in tables */ /* ** number of all possible tags (including LUA_TNONE but excluding DEADKEY) @@ -88,22 +88,32 @@ struct GCObject { -/* -** Union of all Lua values -*/ -typedef union Value Value; - - - /* ** Tagged Values. This is the basic representation of values in Lua, ** an actual value plus a tag with its type. */ +/* +** Union of all Lua values +*/ +typedef union Value { + GCObject *gc; /* collectable objects */ + void *p; /* light userdata */ + int b; /* booleans */ + lua_CFunction f; /* light C functions */ + lua_Integer i; /* integer numbers */ + lua_Number n; /* float numbers */ +} Value; + + #define TValuefields Value value_; int tt_ -typedef struct lua_TValue TValue; + +typedef struct lua_TValue { + TValuefields; +} TValue; + /* macro defining a nil value */ @@ -177,9 +187,9 @@ typedef struct lua_TValue TValue; /* Macros for internal tests */ #define righttt(obj) (ttype(obj) == gcvalue(obj)->tt) -#define checkliveness(g,obj) \ +#define checkliveness(L,obj) \ lua_longassert(!iscollectable(obj) || \ - (righttt(obj) && !isdead(g,gcvalue(obj)))) + (righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj))))) /* Macros to set values */ @@ -215,32 +225,32 @@ typedef struct lua_TValue TValue; #define setsvalue(L,obj,x) \ { TValue *io = (obj); TString *x_ = (x); \ val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \ - checkliveness(G(L),io); } + checkliveness(L,io); } #define setuvalue(L,obj,x) \ { TValue *io = (obj); Udata *x_ = (x); \ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \ - checkliveness(G(L),io); } + checkliveness(L,io); } #define setthvalue(L,obj,x) \ { TValue *io = (obj); lua_State *x_ = (x); \ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTHREAD)); \ - checkliveness(G(L),io); } + checkliveness(L,io); } #define setclLvalue(L,obj,x) \ { TValue *io = (obj); LClosure *x_ = (x); \ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \ - checkliveness(G(L),io); } + checkliveness(L,io); } #define setclCvalue(L,obj,x) \ { TValue *io = (obj); CClosure *x_ = (x); \ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \ - checkliveness(G(L),io); } + checkliveness(L,io); } #define sethvalue(L,obj,x) \ { TValue *io = (obj); Table *x_ = (x); \ val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \ - checkliveness(G(L),io); } + checkliveness(L,io); } #define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) @@ -248,7 +258,7 @@ typedef struct lua_TValue TValue; #define setobj(L,obj1,obj2) \ { TValue *io1=(obj1); *io1 = *(obj2); \ - (void)L; checkliveness(G(L),io1); } + (void)L; checkliveness(L,io1); } /* @@ -264,12 +274,13 @@ typedef struct lua_TValue TValue; #define setptvalue2s setptvalue /* from table to same table */ #define setobjt2t setobj -/* to table */ -#define setobj2t setobj /* to new object */ #define setobj2n setobj #define setsvalue2n setsvalue +/* to table (define it as an expression to be used in macros) */ +#define setobj2t(L,o1,o2) ((void)L, *(o1)=*(o2), checkliveness(L,(o1))) + @@ -280,21 +291,6 @@ typedef struct lua_TValue TValue; */ -union Value { - GCObject *gc; /* collectable objects */ - void *p; /* light userdata */ - int b; /* booleans */ - lua_CFunction f; /* light C functions */ - lua_Integer i; /* integer numbers */ - lua_Number n; /* float numbers */ -}; - - -struct lua_TValue { - TValuefields; -}; - - typedef TValue *StkId; /* index to stack elements */ @@ -329,9 +325,9 @@ typedef union UTString { ** Get the actual string (array of bytes) from a 'TString'. ** (Access to 'extra' ensures that value is really a 'TString'.) */ -#define getaddrstr(ts) (cast(char *, (ts)) + sizeof(UTString)) #define getstr(ts) \ - check_exp(sizeof((ts)->extra), cast(const char*, getaddrstr(ts))) + check_exp(sizeof((ts)->extra), cast(char *, (ts)) + sizeof(UTString)) + /* get the actual string (array of bytes) from a Lua value */ #define svalue(o) getstr(tsvalue(o)) @@ -375,13 +371,13 @@ typedef union UUdata { #define setuservalue(L,u,o) \ { const TValue *io=(o); Udata *iu = (u); \ iu->user_ = io->value_; iu->ttuv_ = rttype(io); \ - checkliveness(G(L),io); } + checkliveness(L,io); } #define getuservalue(L,u,o) \ { TValue *io=(o); const Udata *iu = (u); \ io->value_ = iu->user_; settt_(io, iu->ttuv_); \ - checkliveness(G(L),io); } + checkliveness(L,io); } /* @@ -411,7 +407,7 @@ typedef struct LocVar { typedef struct Proto { CommonHeader; lu_byte numparams; /* number of fixed parameters */ - lu_byte is_vararg; + lu_byte is_vararg; /* 2: declared vararg; 1: uses vararg */ lu_byte maxstacksize; /* number of registers needed by this function */ int sizeupvalues; /* size of 'upvalues' */ int sizek; /* size of 'k' */ @@ -419,8 +415,8 @@ typedef struct Proto { int sizelineinfo; int sizep; /* size of 'p' */ int sizelocvars; - int linedefined; - int lastlinedefined; + int linedefined; /* debug information */ + int lastlinedefined; /* debug information */ TValue *k; /* constants used by the function */ Instruction *code; /* opcodes */ struct Proto **p; /* functions defined inside the function */ @@ -489,7 +485,7 @@ typedef union TKey { #define setnodekey(L,key,obj) \ { TKey *k_=(key); const TValue *io_=(obj); \ k_->nk.value_ = io_->value_; k_->nk.tt_ = io_->tt_; \ - (void)L; checkliveness(G(L),io_); } + (void)L; checkliveness(L,io_); } typedef struct Node { diff --git a/plugins/MirLua/src/lua/loslib.c b/plugins/MirLua/src/lua/loslib.c index d747f26b90..7dae533661 100644 --- a/plugins/MirLua/src/lua/loslib.c +++ b/plugins/MirLua/src/lua/loslib.c @@ -1,5 +1,5 @@ /* -** $Id: loslib.c,v 1.57 2015/04/10 17:41:04 roberto Exp $ +** $Id: loslib.c,v 1.60 2015/11/19 19:16:22 roberto Exp $ ** Standard Operating System library ** See Copyright Notice in lua.h */ @@ -54,7 +54,12 @@ */ #define l_timet lua_Integer #define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t)) -#define l_checktime(L,a) ((time_t)luaL_checkinteger(L,a)) + +static time_t l_checktime (lua_State *L, int arg) { + lua_Integer t = luaL_checkinteger(L, arg); + luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds"); + return (time_t)t; +} #endif /* } */ @@ -198,17 +203,29 @@ static int getboolfield (lua_State *L, const char *key) { } -static int getfield (lua_State *L, const char *key, int d) { - int res, isnum; - lua_getfield(L, -1, key); - res = (int)lua_tointegerx(L, -1, &isnum); - if (!isnum) { - if (d < 0) +/* maximum value for date fields (to avoid arithmetic overflows with 'int') */ +#if !defined(L_MAXDATEFIELD) +#define L_MAXDATEFIELD (INT_MAX / 2) +#endif + +static int getfield (lua_State *L, const char *key, int d, int delta) { + int isnum; + int t = lua_getfield(L, -1, key); + lua_Integer res = lua_tointegerx(L, -1, &isnum); + if (!isnum) { /* field is not a number? */ + if (t != LUA_TNIL) /* some other value? */ + return luaL_error(L, "field '%s' not an integer", key); + else if (d < 0) /* absent field; no default? */ return luaL_error(L, "field '%s' missing in date table", key); res = d; } + else { + if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD)) + return luaL_error(L, "field '%s' out-of-bounds", key); + res -= delta; + } lua_pop(L, 1); - return res; + return (int)res; } @@ -232,9 +249,14 @@ static const char *checkoption (lua_State *L, const char *conv, char *buff) { } luaL_argerror(L, 1, lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); + return conv; /* to avoid warnings */ } +/* maximum size for an individual 'strftime' item */ +#define SIZETIMEFMT 250 + + static int os_date (lua_State *L) { const char *s = luaL_optstring(L, 1, "%c"); time_t t = luaL_opt(L, l_checktime, 2, time(NULL)); @@ -246,8 +268,8 @@ static int os_date (lua_State *L) { else stm = l_localtime(&t, &tmr); if (stm == NULL) /* invalid date? */ - lua_pushnil(L); - else if (strcmp(s, "*t") == 0) { + luaL_error(L, "time result cannot be represented in this installation"); + if (strcmp(s, "*t") == 0) { lua_createtable(L, 0, 9); /* 9 = number of fields */ setfield(L, "sec", stm->tm_sec); setfield(L, "min", stm->tm_min); @@ -265,14 +287,14 @@ static int os_date (lua_State *L) { cc[0] = '%'; luaL_buffinit(L, &b); while (*s) { - if (*s != '%') /* no conversion specifier? */ + if (*s != '%') /* not a conversion specifier? */ luaL_addchar(&b, *s++); else { size_t reslen; - char buff[200]; /* should be big enough for any conversion result */ + char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); s = checkoption(L, s + 1, cc); - reslen = strftime(buff, sizeof(buff), cc, stm); - luaL_addlstring(&b, buff, reslen); + reslen = strftime(buff, SIZETIMEFMT, cc, stm); + luaL_addsize(&b, reslen); } } luaL_pushresult(&b); @@ -289,21 +311,18 @@ static int os_time (lua_State *L) { struct tm ts; luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 1); /* make sure table is at the top */ - ts.tm_sec = getfield(L, "sec", 0); - ts.tm_min = getfield(L, "min", 0); - ts.tm_hour = getfield(L, "hour", 12); - ts.tm_mday = getfield(L, "day", -1); - ts.tm_mon = getfield(L, "month", -1) - 1; - ts.tm_year = getfield(L, "year", -1) - 1900; + ts.tm_sec = getfield(L, "sec", 0, 0); + ts.tm_min = getfield(L, "min", 0, 0); + ts.tm_hour = getfield(L, "hour", 12, 0); + ts.tm_mday = getfield(L, "day", -1, 0); + ts.tm_mon = getfield(L, "month", -1, 1); + ts.tm_year = getfield(L, "year", -1, 1900); ts.tm_isdst = getboolfield(L, "isdst"); t = mktime(&ts); } - if (t != (time_t)(l_timet)t) - luaL_error(L, "time result cannot be represented in this Lua installation"); - else if (t == (time_t)(-1)) - lua_pushnil(L); - else - l_pushtime(L, t); + if (t != (time_t)(l_timet)t || t == (time_t)(-1)) + luaL_error(L, "time result cannot be represented in this installation"); + l_pushtime(L, t); return 1; } diff --git a/plugins/MirLua/src/lua/lparser.c b/plugins/MirLua/src/lua/lparser.c index 9a54dfc98d..282a6b121c 100644 --- a/plugins/MirLua/src/lua/lparser.c +++ b/plugins/MirLua/src/lua/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.147 2014/12/27 20:31:43 roberto Exp $ +** $Id: lparser.c,v 2.149 2015/11/02 16:09:30 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -760,7 +760,7 @@ static void parlist (LexState *ls) { } case TK_DOTS: { /* param -> '...' */ luaX_next(ls); - f->is_vararg = 1; + f->is_vararg = 2; /* declared vararg */ break; } default: luaX_syntaxerror(ls, "<name> or '...' expected"); @@ -956,6 +956,7 @@ static void simpleexp (LexState *ls, expdesc *v) { FuncState *fs = ls->fs; check_condition(ls, fs->f->is_vararg, "cannot use '...' outside a vararg function"); + fs->f->is_vararg = 1; /* function actually uses vararg */ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); break; } @@ -1610,7 +1611,7 @@ static void mainfunc (LexState *ls, FuncState *fs) { BlockCnt bl; expdesc v; open_func(ls, fs, &bl); - fs->f->is_vararg = 1; /* main function is always vararg */ + fs->f->is_vararg = 2; /* main function is always declared vararg */ init_exp(&v, VLOCAL, 0); /* create and... */ newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ luaX_next(ls); /* read first token */ @@ -1626,10 +1627,10 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, FuncState funcstate; LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */ setclLvalue(L, L->top, cl); /* anchor it (to avoid being collected) */ - incr_top(L); + luaD_inctop(L); lexstate.h = luaH_new(L); /* create table for scanner */ sethvalue(L, L->top, lexstate.h); /* anchor it */ - incr_top(L); + luaD_inctop(L); funcstate.f = cl->p = luaF_newproto(L); funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ lua_assert(iswhite(funcstate.f)); /* do not need barrier here */ diff --git a/plugins/MirLua/src/lua/lstate.c b/plugins/MirLua/src/lua/lstate.c index 12e51d242f..9194ac3419 100644 --- a/plugins/MirLua/src/lua/lstate.c +++ b/plugins/MirLua/src/lua/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.128 2015/03/04 13:31:21 roberto Exp $ +** $Id: lstate.c,v 2.133 2015/11/13 12:16:51 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -76,7 +76,7 @@ typedef struct LG { */ #define addbuff(b,p,e) \ { size_t t = cast(size_t, e); \ - memcpy(buff + p, &t, sizeof(t)); p += sizeof(t); } + memcpy(b + p, &t, sizeof(t)); p += sizeof(t); } static unsigned int makeseed (lua_State *L) { char buff[4 * sizeof(size_t)]; @@ -93,10 +93,14 @@ static unsigned int makeseed (lua_State *L) { /* ** set GCdebt to a new value keeping the value (totalbytes + GCdebt) -** invariant +** invariant (and avoiding underflows in 'totalbytes') */ void luaE_setdebt (global_State *g, l_mem debt) { - g->totalbytes -= (debt - g->GCdebt); + l_mem tb = gettotalbytes(g); + lua_assert(tb > 0); + if (debt < tb - MAX_LMEM) + debt = tb - MAX_LMEM; /* will make 'totalbytes == MAX_LMEM' */ + g->totalbytes = tb - debt; g->GCdebt = debt; } @@ -107,6 +111,7 @@ CallInfo *luaE_extendCI (lua_State *L) { L->ci->next = ci; ci->previous = L->ci; ci->next = NULL; + L->nci++; return ci; } @@ -121,6 +126,7 @@ void luaE_freeCI (lua_State *L) { while ((ci = next) != NULL) { next = ci->next; luaM_free(L, ci); + L->nci--; } } @@ -130,13 +136,14 @@ void luaE_freeCI (lua_State *L) { */ void luaE_shrinkCI (lua_State *L) { CallInfo *ci = L->ci; - while (ci->next != NULL) { /* while there is 'next' */ - CallInfo *next2 = ci->next->next; /* next's next */ - if (next2 == NULL) break; - luaM_free(L, ci->next); /* remove next */ + CallInfo *next2; /* next's next */ + /* while there are two nexts */ + while (ci->next != NULL && (next2 = ci->next->next) != NULL) { + luaM_free(L, ci->next); /* free next */ + L->nci--; ci->next = next2; /* remove 'next' from the list */ next2->previous = ci; - ci = next2; + ci = next2; /* keep next's next */ } } @@ -166,6 +173,7 @@ static void freestack (lua_State *L) { return; /* stack not completely built yet */ L->ci = &L->base_ci; /* free the entire 'ci' list */ luaE_freeCI(L); + lua_assert(L->nci == 0); luaM_freearray(L, L->stack, L->stacksize); /* free stack array */ } @@ -214,6 +222,7 @@ static void preinit_thread (lua_State *L, global_State *g) { G(L) = g; L->stack = NULL; L->ci = NULL; + L->nci = 0; L->stacksize = 0; L->twups = L; /* thread has no upvalues */ L->errorJmp = NULL; @@ -237,7 +246,6 @@ static void close_state (lua_State *L) { if (g->version) /* closing a fully built state? */ luai_userstateclose(L); luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); - luaZ_freebuffer(L, &g->buff); freestack(L); lua_assert(gettotalbytes(g) == sizeof(LG)); (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ @@ -306,7 +314,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->strt.size = g->strt.nuse = 0; g->strt.hash = NULL; setnilvalue(&g->l_registry); - luaZ_initbuffer(L, &g->buff); g->panic = NULL; g->version = NULL; g->gcstate = GCSpause; diff --git a/plugins/MirLua/src/lua/lstate.h b/plugins/MirLua/src/lua/lstate.h index eefc217d26..65c914d274 100644 --- a/plugins/MirLua/src/lua/lstate.h +++ b/plugins/MirLua/src/lua/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.122 2015/06/01 16:34:37 roberto Exp $ +** $Id: lstate.h,v 2.128 2015/11/13 12:16:51 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -89,8 +89,8 @@ typedef struct CallInfo { #define CIST_OAH (1<<0) /* original value of 'allowhook' */ #define CIST_LUA (1<<1) /* call is running a Lua function */ #define CIST_HOOKED (1<<2) /* call is running a debug hook */ -#define CIST_REENTRY (1<<3) /* call is running on same invocation of - luaV_execute of previous call */ +#define CIST_FRESH (1<<3) /* call is running on a fresh invocation + of luaV_execute */ #define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ #define CIST_TAIL (1<<5) /* call was tail called */ #define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ @@ -109,7 +109,7 @@ typedef struct CallInfo { typedef struct global_State { lua_Alloc frealloc; /* function to reallocate memory */ void *ud; /* auxiliary data to 'frealloc' */ - lu_mem totalbytes; /* number of bytes currently allocated - GCdebt */ + l_mem totalbytes; /* number of bytes currently allocated - GCdebt */ l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ lu_mem GCmemtrav; /* memory traversed by the GC */ lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ @@ -131,7 +131,6 @@ typedef struct global_State { GCObject *tobefnz; /* list of userdata to be GC */ GCObject *fixedgc; /* list of objects not to be collected */ struct lua_State *twups; /* list of threads with open upvalues */ - Mbuffer buff; /* temporary buffer for string concatenation */ unsigned int gcfinnum; /* number of finalizers to call in each GC step */ int gcpause; /* size of pause between successive GCs */ int gcstepmul; /* GC 'granularity' */ @@ -141,7 +140,7 @@ typedef struct global_State { TString *memerrmsg; /* memory-error message */ TString *tmname[TM_N]; /* array with tag-method names */ struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ - TString *strcache[STRCACHE_SIZE][1]; /* cache for strings in API */ + TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ } global_State; @@ -150,6 +149,7 @@ typedef struct global_State { */ struct lua_State { CommonHeader; + unsigned short nci; /* number of items in 'ci' list */ lu_byte status; StkId top; /* first free slot in the stack */ global_State *l_G; @@ -212,7 +212,7 @@ union GCUnion { /* actual number of total bytes allocated */ -#define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt) +#define gettotalbytes(g) cast(lu_mem, (g)->totalbytes + (g)->GCdebt) LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); diff --git a/plugins/MirLua/src/lua/lstring.c b/plugins/MirLua/src/lua/lstring.c index 5e0e3c40be..9351766fd6 100644 --- a/plugins/MirLua/src/lua/lstring.c +++ b/plugins/MirLua/src/lua/lstring.c @@ -1,5 +1,5 @@ /* -** $Id: lstring.c,v 2.49 2015/06/01 16:34:37 roberto Exp $ +** $Id: lstring.c,v 2.56 2015/11/23 11:32:51 roberto Exp $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -48,14 +48,23 @@ int luaS_eqlngstr (TString *a, TString *b) { unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { unsigned int h = seed ^ cast(unsigned int, l); - size_t l1; size_t step = (l >> LUAI_HASHLIMIT) + 1; - for (l1 = l; l1 >= step; l1 -= step) - h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1 - 1])); + for (; l >= step; l -= step) + h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1])); return h; } +unsigned int luaS_hashlongstr (TString *ts) { + lua_assert(ts->tt == LUA_TLNGSTR); + if (ts->extra == 0) { /* no hash? */ + ts->hash = luaS_hash(getstr(ts), ts->u.lnglen, ts->hash); + ts->extra = 1; /* now it has its hash */ + } + return ts->hash; +} + + /* ** resizes the string table */ @@ -92,11 +101,12 @@ void luaS_resize (lua_State *L, int newsize) { ** a non-collectable string.) */ void luaS_clearcache (global_State *g) { - int i; - for (i = 0; i < STRCACHE_SIZE; i++) { - if (iswhite(g->strcache[i][0])) /* will entry be collected? */ - g->strcache[i][0] = g->memerrmsg; /* replace it with something fixed */ - } + int i, j; + for (i = 0; i < STRCACHE_N; i++) + for (j = 0; j < STRCACHE_M; j++) { + if (iswhite(g->strcache[i][j])) /* will entry be collected? */ + g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */ + } } @@ -105,13 +115,14 @@ void luaS_clearcache (global_State *g) { */ void luaS_init (lua_State *L) { global_State *g = G(L); - int i; + int i, j; luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ /* pre-create memory-error message */ g->memerrmsg = luaS_newliteral(L, MEMERRMSG); luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ - for (i = 0; i < STRCACHE_SIZE; i++) /* fill cache with valid strings */ - g->strcache[i][0] = g->memerrmsg; + for (i = 0; i < STRCACHE_N; i++) /* fill cache with valid strings */ + for (j = 0; j < STRCACHE_M; j++) + g->strcache[i][j] = g->memerrmsg; } @@ -119,8 +130,7 @@ void luaS_init (lua_State *L) { /* ** creates a new string object */ -static TString *createstrobj (lua_State *L, const char *str, size_t l, - int tag, unsigned int h) { +static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) { TString *ts; GCObject *o; size_t totalsize; /* total size of TString object */ @@ -129,8 +139,14 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l, ts = gco2ts(o); ts->hash = h; ts->extra = 0; - memcpy(getaddrstr(ts), str, l * sizeof(char)); - getaddrstr(ts)[l] = '\0'; /* ending 0 */ + getstr(ts)[l] = '\0'; /* ending 0 */ + return ts; +} + + +TString *luaS_createlngstrobj (lua_State *L, size_t l) { + TString *ts = createstrobj(L, l, LUA_TLNGSTR, G(L)->seed); + ts->u.lnglen = l; return ts; } @@ -153,6 +169,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { global_State *g = G(L); unsigned int h = luaS_hash(str, l, g->seed); TString **list = &g->strt.hash[lmod(h, g->strt.size)]; + lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */ for (ts = *list; ts != NULL; ts = ts->u.hnext) { if (l == ts->shrlen && (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { @@ -166,7 +183,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { luaS_resize(L, g->strt.size * 2); list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ } - ts = createstrobj(L, str, l, LUA_TSHRSTR, h); + ts = createstrobj(L, l, LUA_TSHRSTR, h); + memcpy(getstr(ts), str, l * sizeof(char)); ts->shrlen = cast_byte(l); ts->u.hnext = *list; *list = ts; @@ -183,10 +201,10 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { return internshrstr(L, str, l); else { TString *ts; - if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char)) + if (l >= (MAX_SIZE - sizeof(TString))/sizeof(char)) luaM_toobig(L); - ts = createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed); - ts->u.lnglen = l; + ts = luaS_createlngstrobj(L, l); + memcpy(getstr(ts), str, l * sizeof(char)); return ts; } } @@ -199,15 +217,19 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { ** check hits. */ TString *luaS_new (lua_State *L, const char *str) { - unsigned int i = point2uint(str) % STRCACHE_SIZE; /* hash */ + unsigned int i = point2uint(str) % STRCACHE_N; /* hash */ + int j; TString **p = G(L)->strcache[i]; - if (strcmp(str, getstr(p[0])) == 0) /* hit? */ - return p[0]; /* that it is */ - else { /* normal route */ - TString *s = luaS_newlstr(L, str, strlen(str)); - p[0] = s; - return s; + for (j = 0; j < STRCACHE_M; j++) { + if (strcmp(str, getstr(p[j])) == 0) /* hit? */ + return p[j]; /* that is it */ } + /* normal route */ + for (j = STRCACHE_M - 1; j > 0; j--) + p[j] = p[j - 1]; /* move out last element */ + /* new element is first in the list */ + p[0] = luaS_newlstr(L, str, strlen(str)); + return p[0]; } diff --git a/plugins/MirLua/src/lua/lstring.h b/plugins/MirLua/src/lua/lstring.h index e746f5fc8b..27efd20772 100644 --- a/plugins/MirLua/src/lua/lstring.h +++ b/plugins/MirLua/src/lua/lstring.h @@ -1,5 +1,5 @@ /* -** $Id: lstring.h,v 1.59 2015/03/25 13:42:19 roberto Exp $ +** $Id: lstring.h,v 1.61 2015/11/03 15:36:01 roberto Exp $ ** String table (keep all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -34,6 +34,7 @@ LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); +LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts); LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); LUAI_FUNC void luaS_resize (lua_State *L, int newsize); LUAI_FUNC void luaS_clearcache (global_State *g); @@ -42,6 +43,7 @@ LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); +LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); #endif diff --git a/plugins/MirLua/src/lua/lstrlib.c b/plugins/MirLua/src/lua/lstrlib.c index 19c350de15..fe30e34b95 100644 --- a/plugins/MirLua/src/lua/lstrlib.c +++ b/plugins/MirLua/src/lua/lstrlib.c @@ -1,5 +1,5 @@ /* -** $Id: lstrlib.c,v 1.229 2015/05/20 17:39:23 roberto Exp $ +** $Id: lstrlib.c,v 1.239 2015/11/25 16:28:17 roberto Exp $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ @@ -41,8 +41,10 @@ ** Some sizes are better limited to fit in 'int', but must also fit in ** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.) */ +#define MAX_SIZET ((size_t)(~(size_t)0)) + #define MAXSIZE \ - (sizeof(size_t) < sizeof(int) ? (~(size_t)0) : (size_t)(INT_MAX)) + (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX)) @@ -208,11 +210,12 @@ static int str_dump (lua_State *L) { typedef struct MatchState { - int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ const char *src_init; /* init of source string */ const char *src_end; /* end ('\0') of source string */ const char *p_end; /* end ('\0') of pattern */ lua_State *L; + size_t nrep; /* limit to avoid non-linear complexity */ + int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ int level; /* total number of captures (finished or unfinished) */ struct { const char *init; @@ -231,6 +234,17 @@ static const char *match (MatchState *ms, const char *s, const char *p); #endif +/* +** parameters to control the maximum number of operators handled in +** a match (to avoid non-linear complexity). The maximum will be: +** (subject length) * A_REPS + B_REPS +*/ +#if !defined(A_REPS) +#define A_REPS 4 +#define B_REPS 100000 +#endif + + #define L_ESC '%' #define SPECIALS "^$*+?.([%-" @@ -488,6 +502,8 @@ static const char *match (MatchState *ms, const char *s, const char *p) { s = NULL; /* fail */ } else { /* matched once */ + if (ms->nrep-- == 0) + luaL_error(ms->L, "pattern too complex"); switch (*ep) { /* handle optional suffix */ case '?': { /* optional */ const char *res; @@ -584,6 +600,26 @@ static int nospecials (const char *p, size_t l) { } +static void prepstate (MatchState *ms, lua_State *L, + const char *s, size_t ls, const char *p, size_t lp) { + ms->L = L; + ms->matchdepth = MAXCCALLS; + ms->src_init = s; + ms->src_end = s + ls; + ms->p_end = p + lp; + if (ls < (MAX_SIZET - B_REPS) / A_REPS) + ms->nrep = A_REPS * ls + B_REPS; + else /* overflow (very long subject) */ + ms->nrep = MAX_SIZET; /* no limit */ +} + + +static void reprepstate (MatchState *ms) { + ms->level = 0; + lua_assert(ms->matchdepth == MAXCCALLS); +} + + static int str_find_aux (lua_State *L, int find) { size_t ls, lp; const char *s = luaL_checklstring(L, 1, &ls); @@ -611,15 +647,10 @@ static int str_find_aux (lua_State *L, int find) { if (anchor) { p++; lp--; /* skip anchor character */ } - ms.L = L; - ms.matchdepth = MAXCCALLS; - ms.src_init = s; - ms.src_end = s + ls; - ms.p_end = p + lp; + prepstate(&ms, L, s, ls, p, lp); do { const char *res; - ms.level = 0; - lua_assert(ms.matchdepth == MAXCCALLS); + reprepstate(&ms); if ((res=match(&ms, s1, p)) != NULL) { if (find) { lua_pushinteger(L, (s1 - s) + 1); /* start */ @@ -646,29 +677,26 @@ static int str_match (lua_State *L) { } +/* state for 'gmatch' */ +typedef struct GMatchState { + const char *src; /* current position */ + const char *p; /* pattern */ + MatchState ms; /* match state */ +} GMatchState; + + static int gmatch_aux (lua_State *L) { - MatchState ms; - size_t ls, lp; - const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); - const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp); + GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3)); const char *src; - ms.L = L; - ms.matchdepth = MAXCCALLS; - ms.src_init = s; - ms.src_end = s+ls; - ms.p_end = p + lp; - for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); - src <= ms.src_end; - src++) { + for (src = gm->src; src <= gm->ms.src_end; src++) { const char *e; - ms.level = 0; - lua_assert(ms.matchdepth == MAXCCALLS); - if ((e = match(&ms, src, p)) != NULL) { - lua_Integer newstart = e-s; - if (e == src) newstart++; /* empty match? go at least one position */ - lua_pushinteger(L, newstart); - lua_replace(L, lua_upvalueindex(3)); - return push_captures(&ms, src, e); + reprepstate(&gm->ms); + if ((e = match(&gm->ms, src, gm->p)) != NULL) { + if (e == src) /* empty match? */ + gm->src =src + 1; /* go at least one position */ + else + gm->src = e; + return push_captures(&gm->ms, src, e); } } return 0; /* not found */ @@ -676,10 +704,14 @@ static int gmatch_aux (lua_State *L) { static int gmatch (lua_State *L) { - luaL_checkstring(L, 1); - luaL_checkstring(L, 2); - lua_settop(L, 2); - lua_pushinteger(L, 0); + size_t ls, lp; + const char *s = luaL_checklstring(L, 1, &ls); + const char *p = luaL_checklstring(L, 2, &lp); + GMatchState *gm; + lua_settop(L, 2); /* keep them on closure to avoid being collected */ + gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState)); + prepstate(&gm->ms, L, s, ls, p, lp); + gm->src = s; gm->p = p; lua_pushcclosure(L, gmatch_aux, 3); return 1; } @@ -761,17 +793,11 @@ static int str_gsub (lua_State *L) { if (anchor) { p++; lp--; /* skip anchor character */ } - ms.L = L; - ms.matchdepth = MAXCCALLS; - ms.src_init = src; - ms.src_end = src+srcl; - ms.p_end = p + lp; + prepstate(&ms, L, src, srcl, p, lp); while (n < max_s) { const char *e; - ms.level = 0; - lua_assert(ms.matchdepth == MAXCCALLS); - e = match(&ms, src, p); - if (e) { + reprepstate(&ms); + if ((e = match(&ms, src, p)) != NULL) { n++; add_value(&ms, &b, src, e, tr); } @@ -830,13 +856,12 @@ static lua_Number adddigit (char *buff, int n, lua_Number x) { } -static int num2straux (char *buff, lua_Number x) { +static int num2straux (char *buff, int sz, lua_Number x) { if (x != x || x == HUGE_VAL || x == -HUGE_VAL) /* inf or NaN? */ - return sprintf(buff, LUA_NUMBER_FMT, x); /* equal to '%g' */ + return l_sprintf(buff, sz, LUA_NUMBER_FMT, x); /* equal to '%g' */ else if (x == 0) { /* can be -0... */ - sprintf(buff, LUA_NUMBER_FMT, x); - strcat(buff, "x0p+0"); /* reuses '0/-0' from 'sprintf'... */ - return strlen(buff); + /* create "0" or "-0" followed by exponent */ + return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", x); } else { int e; @@ -855,15 +880,16 @@ static int num2straux (char *buff, lua_Number x) { m = adddigit(buff, n++, m * 16); } while (m > 0); } - n += sprintf(buff + n, "p%+d", e); /* add exponent */ + n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */ + lua_assert(n < sz); return n; } } -static int lua_number2strx (lua_State *L, char *buff, const char *fmt, - lua_Number x) { - int n = num2straux(buff, x); +static int lua_number2strx (lua_State *L, char *buff, int sz, + const char *fmt, lua_Number x) { + int n = num2straux(buff, sz, x); if (fmt[SIZELENMOD] == 'A') { int i; for (i = 0; i < n; i++) @@ -879,10 +905,12 @@ static int lua_number2strx (lua_State *L, char *buff, const char *fmt, /* ** Maximum size of each formatted item. This maximum size is produced -** by format('%.99f', minfloat), and is equal to 99 + 2 ('-' and '.') + -** number of decimal digits to represent minfloat. +** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.', +** and '\0') + number of decimal digits to represent maxfloat (which +** is maximum exponent + 1). (99+3+1 then rounded to 120 for "extra +** expenses", such as locale-dependent stuff) */ -#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP)) +#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP)) /* valid flags in a format specification */ @@ -906,9 +934,9 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { else if (*s == '\0' || iscntrl(uchar(*s))) { char buff[10]; if (!isdigit(uchar(*(s+1)))) - sprintf(buff, "\\%d", (int)uchar(*s)); + l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); else - sprintf(buff, "\\%03d", (int)uchar(*s)); + l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s)); luaL_addstring(b, buff); } else @@ -975,24 +1003,25 @@ static int str_format (lua_State *L) { strfrmt = scanformat(L, strfrmt, form); switch (*strfrmt++) { case 'c': { - nb = sprintf(buff, form, (int)luaL_checkinteger(L, arg)); + nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg)); break; } case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': { lua_Integer n = luaL_checkinteger(L, arg); addlenmod(form, LUA_INTEGER_FRMLEN); - nb = sprintf(buff, form, n); + nb = l_sprintf(buff, MAX_ITEM, form, n); break; } case 'a': case 'A': addlenmod(form, LUA_NUMBER_FRMLEN); - nb = lua_number2strx(L, buff, form, luaL_checknumber(L, arg)); + nb = lua_number2strx(L, buff, MAX_ITEM, form, + luaL_checknumber(L, arg)); break; case 'e': case 'E': case 'f': case 'g': case 'G': { addlenmod(form, LUA_NUMBER_FRMLEN); - nb = sprintf(buff, form, luaL_checknumber(L, arg)); + nb = l_sprintf(buff, MAX_ITEM, form, luaL_checknumber(L, arg)); break; } case 'q': { @@ -1002,14 +1031,18 @@ static int str_format (lua_State *L) { case 's': { size_t l; const char *s = luaL_tolstring(L, arg, &l); - if (!strchr(form, '.') && l >= 100) { - /* no precision and string is too long to be formatted; - keep original string */ - luaL_addvalue(&b); - } + if (form[2] == '\0') /* no modifiers? */ + luaL_addvalue(&b); /* keep entire string */ else { - nb = sprintf(buff, form, s); - lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ + luaL_argcheck(L, l == strlen(s), arg, "string contains zeros"); + if (!strchr(form, '.') && l >= 100) { + /* no precision and string is too long to be formatted */ + luaL_addvalue(&b); /* keep entire string */ + } + else { /* format the string into 'buff' */ + nb = l_sprintf(buff, MAX_ITEM, form, s); + lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ + } } break; } @@ -1018,6 +1051,7 @@ static int str_format (lua_State *L) { *(strfrmt - 1)); } } + lua_assert(nb < MAX_ITEM); luaL_addsize(&b, nb); } } @@ -1309,8 +1343,13 @@ static int str_pack (lua_State *L) { case Kchar: { /* fixed-size string */ size_t len; const char *s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, len == (size_t)size, arg, "wrong length"); - luaL_addlstring(&b, s, size); + if ((size_t)size <= len) /* string larger than (or equal to) needed? */ + luaL_addlstring(&b, s, size); /* truncate string to asked size */ + else { /* string smaller than needed */ + luaL_addlstring(&b, s, len); /* add it all */ + while (len++ < (size_t)size) /* pad extra space */ + luaL_addchar(&b, LUA_PACKPADBYTE); + } break; } case Kstring: { /* strings with length count */ @@ -1360,7 +1399,7 @@ static int str_packsize (lua_State *L) { case Kstring: /* strings with length count */ case Kzstr: /* zero-terminated string */ luaL_argerror(L, 1, "variable-length format"); - break; + /* call never return, but to avoid warnings: *//* FALLTHROUGH */ default: break; } } diff --git a/plugins/MirLua/src/lua/ltable.c b/plugins/MirLua/src/lua/ltable.c index 04f2a34735..7e15b71bad 100644 --- a/plugins/MirLua/src/lua/ltable.c +++ b/plugins/MirLua/src/lua/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.111 2015/06/09 14:21:13 roberto Exp $ +** $Id: ltable.c,v 2.117 2015/11/19 19:16:22 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -85,7 +85,7 @@ static const Node dummynode_ = { /* ** Hash for floating-point numbers. ** The main computation should be just -** n = frepx(n, &i); return (n * INT_MAX) + i +** n = frexp(n, &i); return (n * INT_MAX) + i ** but there are some numerical subtleties. ** In a two-complement representation, INT_MAX does not has an exact ** representation as a float, but INT_MIN does; because the absolute @@ -101,7 +101,7 @@ static int l_hashfloat (lua_Number n) { lua_Integer ni; n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN); if (!lua_numbertointeger(n, &ni)) { /* is 'n' inf/-inf/NaN? */ - lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == HUGE_VAL); + lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == cast_num(HUGE_VAL)); return 0; } else { /* normal case */ @@ -124,14 +124,8 @@ static Node *mainposition (const Table *t, const TValue *key) { return hashmod(t, l_hashfloat(fltvalue(key))); case LUA_TSHRSTR: return hashstr(t, tsvalue(key)); - case LUA_TLNGSTR: { - TString *s = tsvalue(key); - if (s->extra == 0) { /* no hash? */ - s->hash = luaS_hash(getstr(s), s->u.lnglen, s->hash); - s->extra = 1; /* now it has its hash */ - } - return hashstr(t, tsvalue(key)); - } + case LUA_TLNGSTR: + return hashpow2(t, luaS_hashlongstr(tsvalue(key))); case LUA_TBOOLEAN: return hashboolean(t, bvalue(key)); case LUA_TLIGHTUSERDATA: @@ -139,6 +133,7 @@ static Node *mainposition (const Table *t, const TValue *key) { case LUA_TLCF: return hashpointer(t, fvalue(key)); default: + lua_assert(!ttisdeadkey(key)); return hashpointer(t, gcvalue(key)); } } @@ -463,7 +458,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { Node *f = getfreepos(t); /* get a free place */ if (f == NULL) { /* cannot find a free place? */ rehash(L, t, key); /* grow table */ - /* whatever called 'newkey' takes care of TM cache and GC barrier */ + /* whatever called 'newkey' takes care of TM cache */ return luaH_set(L, t, key); /* insert key into grown table */ } lua_assert(!isdummy(f)); @@ -501,7 +496,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { */ const TValue *luaH_getint (Table *t, lua_Integer key) { /* (1 <= key && key <= t->sizearray) */ - if (l_castS2U(key - 1) < t->sizearray) + if (l_castS2U(key) - 1 < t->sizearray) return &t->array[key - 1]; else { Node *n = hashint(t, key); @@ -513,7 +508,7 @@ const TValue *luaH_getint (Table *t, lua_Integer key) { if (nx == 0) break; n += nx; } - }; + } return luaO_nilobject; } } @@ -522,7 +517,7 @@ const TValue *luaH_getint (Table *t, lua_Integer key) { /* ** search function for short strings */ -const TValue *luaH_getstr (Table *t, TString *key) { +const TValue *luaH_getshortstr (Table *t, TString *key) { Node *n = hashstr(t, key); lua_assert(key->tt == LUA_TSHRSTR); for (;;) { /* check whether 'key' is somewhere in the chain */ @@ -531,11 +526,41 @@ const TValue *luaH_getstr (Table *t, TString *key) { return gval(n); /* that's it */ else { int nx = gnext(n); - if (nx == 0) break; + if (nx == 0) + return luaO_nilobject; /* not found */ n += nx; } - }; - return luaO_nilobject; + } +} + + +/* +** "Generic" get version. (Not that generic: not valid for integers, +** which may be in array part, nor for floats with integral values.) +*/ +static const TValue *getgeneric (Table *t, const TValue *key) { + Node *n = mainposition(t, key); + for (;;) { /* check whether 'key' is somewhere in the chain */ + if (luaV_rawequalobj(gkey(n), key)) + return gval(n); /* that's it */ + else { + int nx = gnext(n); + if (nx == 0) + return luaO_nilobject; /* not found */ + n += nx; + } + } +} + + +const TValue *luaH_getstr (Table *t, TString *key) { + if (key->tt == LUA_TSHRSTR) + return luaH_getshortstr(t, key); + else { /* for long strings, use generic case */ + TValue ko; + setsvalue(cast(lua_State *, NULL), &ko, key); + return getgeneric(t, &ko); + } } @@ -544,7 +569,7 @@ const TValue *luaH_getstr (Table *t, TString *key) { */ const TValue *luaH_get (Table *t, const TValue *key) { switch (ttype(key)) { - case LUA_TSHRSTR: return luaH_getstr(t, tsvalue(key)); + case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key)); case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); case LUA_TNIL: return luaO_nilobject; case LUA_TNUMFLT: { @@ -553,19 +578,8 @@ const TValue *luaH_get (Table *t, const TValue *key) { return luaH_getint(t, k); /* use specialized version */ /* else... */ } /* FALLTHROUGH */ - default: { - Node *n = mainposition(t, key); - for (;;) { /* check whether 'key' is somewhere in the chain */ - if (luaV_rawequalobj(gkey(n), key)) - return gval(n); /* that's it */ - else { - int nx = gnext(n); - if (nx == 0) break; - n += nx; - } - }; - return luaO_nilobject; - } + default: + return getgeneric(t, key); } } diff --git a/plugins/MirLua/src/lua/ltable.h b/plugins/MirLua/src/lua/ltable.h index 53d25511ad..213cc13987 100644 --- a/plugins/MirLua/src/lua/ltable.h +++ b/plugins/MirLua/src/lua/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 2.20 2014/09/04 18:15:29 roberto Exp $ +** $Id: ltable.h,v 2.21 2015/11/03 15:47:30 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -18,6 +18,10 @@ /* 'const' to avoid wrong writings that can mess up field 'next' */ #define gkey(n) cast(const TValue*, (&(n)->i_key.tvk)) +/* +** writable version of 'gkey'; allows updates to individual fields, +** but not to the whole (which has incompatible type) +*/ #define wgkey(n) (&(n)->i_key.nk) #define invalidateTMcache(t) ((t)->flags = 0) @@ -31,6 +35,7 @@ LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value); +LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key); LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); diff --git a/plugins/MirLua/src/lua/ltablib.c b/plugins/MirLua/src/lua/ltablib.c index a05c885c03..b3c9a7c528 100644 --- a/plugins/MirLua/src/lua/ltablib.c +++ b/plugins/MirLua/src/lua/ltablib.c @@ -1,5 +1,5 @@ /* -** $Id: ltablib.c,v 1.80 2015/01/13 16:27:29 roberto Exp $ +** $Id: ltablib.c,v 1.90 2015/11/25 12:48:57 roberto Exp $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ @@ -12,6 +12,7 @@ #include <limits.h> #include <stddef.h> +#include <string.h> #include "lua.h" @@ -19,42 +20,44 @@ #include "lualib.h" - /* -** Structure with table-access functions +** Operations that an object must define to mimic a table +** (some functions only need some of them) */ -typedef struct { - int (*geti) (lua_State *L, int idx, lua_Integer n); - void (*seti) (lua_State *L, int idx, lua_Integer n); -} TabA; +#define TAB_R 1 /* read */ +#define TAB_W 2 /* write */ +#define TAB_L 4 /* length */ +#define TAB_RW (TAB_R | TAB_W) /* read/write */ + + +#define aux_getn(L,n,w) (checktab(L, n, (w) | TAB_L), luaL_len(L, n)) + + +static int checkfield (lua_State *L, const char *key, int n) { + lua_pushstring(L, key); + return (lua_rawget(L, -n) != LUA_TNIL); +} /* -** Check that 'arg' has a table and set access functions in 'ta' to raw -** or non-raw according to the presence of corresponding metamethods. +** Check that 'arg' either is a table or can behave like one (that is, +** has a metatable with the required metamethods) */ -static void checktab (lua_State *L, int arg, TabA *ta) { - ta->geti = NULL; ta->seti = NULL; - if (lua_getmetatable(L, arg)) { - lua_pushliteral(L, "__index"); /* 'index' metamethod */ - if (lua_rawget(L, -2) != LUA_TNIL) - ta->geti = lua_geti; - lua_pushliteral(L, "__newindex"); /* 'newindex' metamethod */ - if (lua_rawget(L, -3) != LUA_TNIL) - ta->seti = lua_seti; - lua_pop(L, 3); /* pop metatable plus both metamethods */ - } - if (ta->geti == NULL || ta->seti == NULL) { - luaL_checktype(L, arg, LUA_TTABLE); /* must be table for raw methods */ - if (ta->geti == NULL) ta->geti = lua_rawgeti; - if (ta->seti == NULL) ta->seti = lua_rawseti; +static void checktab (lua_State *L, int arg, int what) { + if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */ + int n = 1; /* number of elements to pop */ + if (lua_getmetatable(L, arg) && /* must have metatable */ + (!(what & TAB_R) || checkfield(L, "__index", ++n)) && + (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) && + (!(what & TAB_L) || checkfield(L, "__len", ++n))) { + lua_pop(L, n); /* pop metatable and tested metamethods */ + } + else + luaL_argerror(L, arg, "table expected"); /* force an error */ } } -#define aux_getn(L,n,ta) (checktab(L, n, ta), luaL_len(L, n)) - - #if defined(LUA_COMPAT_MAXN) static int maxn (lua_State *L) { lua_Number max = 0; @@ -74,8 +77,7 @@ static int maxn (lua_State *L) { static int tinsert (lua_State *L) { - TabA ta; - lua_Integer e = aux_getn(L, 1, &ta) + 1; /* first empty element */ + lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */ lua_Integer pos; /* where to insert new element */ switch (lua_gettop(L)) { case 2: { /* called with only 2 arguments */ @@ -87,8 +89,8 @@ static int tinsert (lua_State *L) { pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); for (i = e; i > pos; i--) { /* move up elements */ - (*ta.geti)(L, 1, i - 1); - (*ta.seti)(L, 1, i); /* t[i] = t[i - 1] */ + lua_geti(L, 1, i - 1); + lua_seti(L, 1, i); /* t[i] = t[i - 1] */ } break; } @@ -96,57 +98,57 @@ static int tinsert (lua_State *L) { return luaL_error(L, "wrong number of arguments to 'insert'"); } } - (*ta.seti)(L, 1, pos); /* t[pos] = v */ + lua_seti(L, 1, pos); /* t[pos] = v */ return 0; } static int tremove (lua_State *L) { - TabA ta; - lua_Integer size = aux_getn(L, 1, &ta); + lua_Integer size = aux_getn(L, 1, TAB_RW); lua_Integer pos = luaL_optinteger(L, 2, size); if (pos != size) /* validate 'pos' if given */ luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); - (*ta.geti)(L, 1, pos); /* result = t[pos] */ + lua_geti(L, 1, pos); /* result = t[pos] */ for ( ; pos < size; pos++) { - (*ta.geti)(L, 1, pos + 1); - (*ta.seti)(L, 1, pos); /* t[pos] = t[pos + 1] */ + lua_geti(L, 1, pos + 1); + lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */ } lua_pushnil(L); - (*ta.seti)(L, 1, pos); /* t[pos] = nil */ + lua_seti(L, 1, pos); /* t[pos] = nil */ return 1; } +/* +** Copy elements (1[f], ..., 1[e]) into (tt[t], tt[t+1], ...). Whenever +** possible, copy in increasing order, which is better for rehashing. +** "possible" means destination after original range, or smaller +** than origin, or copying to another table. +*/ static int tmove (lua_State *L) { - TabA ta; lua_Integer f = luaL_checkinteger(L, 2); lua_Integer e = luaL_checkinteger(L, 3); lua_Integer t = luaL_checkinteger(L, 4); int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */ + checktab(L, 1, TAB_R); + checktab(L, tt, TAB_W); if (e >= f) { /* otherwise, nothing to move */ lua_Integer n, i; - ta.geti = (luaL_getmetafield(L, 1, "__index") == LUA_TNIL) - ? (luaL_checktype(L, 1, LUA_TTABLE), lua_rawgeti) - : lua_geti; - ta.seti = (luaL_getmetafield(L, tt, "__newindex") == LUA_TNIL) - ? (luaL_checktype(L, tt, LUA_TTABLE), lua_rawseti) - : lua_seti; luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3, "too many elements to move"); n = e - f + 1; /* number of elements to move */ luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, "destination wrap around"); - if (t > f) { - for (i = n - 1; i >= 0; i--) { - (*ta.geti)(L, 1, f + i); - (*ta.seti)(L, tt, t + i); + if (t > e || t <= f || tt != 1) { + for (i = 0; i < n; i++) { + lua_geti(L, 1, f + i); + lua_seti(L, tt, t + i); } } else { - for (i = 0; i < n; i++) { - (*ta.geti)(L, 1, f + i); - (*ta.seti)(L, tt, t + i); + for (i = n - 1; i >= 0; i--) { + lua_geti(L, 1, f + i); + lua_seti(L, tt, t + i); } } } @@ -155,8 +157,8 @@ static int tmove (lua_State *L) { } -static void addfield (lua_State *L, luaL_Buffer *b, TabA *ta, lua_Integer i) { - (*ta->geti)(L, 1, i); +static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) { + lua_geti(L, 1, i); if (!lua_isstring(L, -1)) luaL_error(L, "invalid value (%s) at index %d in table for 'concat'", luaL_typename(L, -1), i); @@ -165,21 +167,19 @@ static void addfield (lua_State *L, luaL_Buffer *b, TabA *ta, lua_Integer i) { static int tconcat (lua_State *L) { - TabA ta; luaL_Buffer b; + lua_Integer last = aux_getn(L, 1, TAB_R); size_t lsep; - lua_Integer i, last; const char *sep = luaL_optlstring(L, 2, "", &lsep); - checktab(L, 1, &ta); - i = luaL_optinteger(L, 3, 1); - last = luaL_opt(L, luaL_checkinteger, 4, luaL_len(L, 1)); + lua_Integer i = luaL_optinteger(L, 3, 1); + last = luaL_opt(L, luaL_checkinteger, 4, last); luaL_buffinit(L, &b); for (; i < last; i++) { - addfield(L, &b, &ta, i); + addfield(L, &b, i); luaL_addlstring(&b, sep, lsep); } if (i == last) /* add last value (if interval was not empty) */ - addfield(L, &b, &ta, i); + addfield(L, &b, i); luaL_pushresult(&b); return 1; } @@ -197,7 +197,7 @@ static int pack (lua_State *L) { lua_createtable(L, n, 1); /* create result table */ lua_insert(L, 1); /* put it at index 1 */ for (i = n; i >= 1; i--) /* assign elements */ - lua_rawseti(L, 1, i); + lua_seti(L, 1, i); lua_pushinteger(L, n); lua_setfield(L, 1, "n"); /* t.n = number of elements */ return 1; /* return table */ @@ -205,20 +205,17 @@ static int pack (lua_State *L) { static int unpack (lua_State *L) { - TabA ta; - lua_Integer i, e; lua_Unsigned n; - checktab(L, 1, &ta); - i = luaL_optinteger(L, 2, 1); - e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); + lua_Integer i = luaL_optinteger(L, 2, 1); + lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); if (i > e) return 0; /* empty range */ n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n))) return luaL_error(L, "too many results to unpack"); - do { /* must have at least one element */ - (*ta.geti)(L, 1, i); /* push arg[i..e] */ - } while (i++ < e); - + for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */ + lua_geti(L, 1, i); + } + lua_geti(L, 1, e); /* push last element */ return (int)n; } @@ -235,97 +232,190 @@ static int unpack (lua_State *L) { */ -static void set2 (lua_State *L, TabA *ta, int i, int j) { - (*ta->seti)(L, 1, i); - (*ta->seti)(L, 1, j); +/* +** Produce a "random" 'unsigned int' to randomize pivot choice. This +** macro is used only when 'sort' detects a big imbalance in the result +** of a partition. (If you don't want/need this "randomness", ~0 is a +** good choice.) +*/ +#if !defined(l_randomizePivot) /* { */ + +#include <time.h> + +/* size of 'e' measured in number of 'unsigned int's */ +#define sof(e) (sizeof(e) / sizeof(unsigned int)) + +/* +** Use 'time' and 'clock' as sources of "randomness". Because we don't +** know the types 'clock_t' and 'time_t', we cannot cast them to +** anything without risking overflows. A safe way to use their values +** is to copy them to an array of a known type and use the array values. +*/ +static unsigned int l_randomizePivot (void) { + clock_t c = clock(); + time_t t = time(NULL); + unsigned int buff[sof(c) + sof(t)]; + unsigned int i, rnd = 0; + memcpy(buff, &c, sof(c) * sizeof(unsigned int)); + memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int)); + for (i = 0; i < sof(buff); i++) + rnd += buff[i]; + return rnd; +} + +#endif /* } */ + + +/* arrays larger than 'RANLIMIT' may use randomized pivots */ +#define RANLIMIT 100u + + +static void set2 (lua_State *L, unsigned int i, unsigned int j) { + lua_seti(L, 1, i); + lua_seti(L, 1, j); } + +/* +** Return true iff value at stack index 'a' is less than the value at +** index 'b' (according to the order of the sort). +*/ static int sort_comp (lua_State *L, int a, int b) { - if (!lua_isnil(L, 2)) { /* function? */ + if (lua_isnil(L, 2)) /* no function? */ + return lua_compare(L, a, b, LUA_OPLT); /* a < b */ + else { /* function */ int res; - lua_pushvalue(L, 2); + lua_pushvalue(L, 2); /* push function */ lua_pushvalue(L, a-1); /* -1 to compensate function */ lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */ - lua_call(L, 2, 1); - res = lua_toboolean(L, -1); - lua_pop(L, 1); + lua_call(L, 2, 1); /* call function */ + res = lua_toboolean(L, -1); /* get result */ + lua_pop(L, 1); /* pop result */ return res; } - else /* a < b? */ - return lua_compare(L, a, b, LUA_OPLT); } -static void auxsort (lua_State *L, TabA *ta, int l, int u) { - while (l < u) { /* for tail recursion */ - int i, j; - /* sort elements a[l], a[(l+u)/2] and a[u] */ - (*ta->geti)(L, 1, l); - (*ta->geti)(L, 1, u); - if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ - set2(L, ta, l, u); /* swap a[l] - a[u] */ + +/* +** Does the partition: Pivot P is at the top of the stack. +** precondition: a[lo] <= P == a[up-1] <= a[up], +** so it only needs to do the partition from lo + 1 to up - 2. +** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] +** returns 'i'. +*/ +static unsigned int partition (lua_State *L, unsigned int lo, + unsigned int up) { + unsigned int i = lo; /* will be incremented before first use */ + unsigned int j = up - 1; /* will be decremented before first use */ + /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ + for (;;) { + /* next loop: repeat ++i while a[i] < P */ + while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (i == up - 1) /* a[i] < P but a[up - 1] == P ?? */ + luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[i] */ + } + /* after the loop, a[i] >= P and a[lo .. i - 1] < P */ + /* next loop: repeat --j while P < a[j] */ + while (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) { + if (j < i) /* j < i but a[j] > P ?? */ + luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[j] */ + } + /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */ + if (j < i) { /* no elements out of place? */ + /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */ + lua_pop(L, 1); /* pop a[j] */ + /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */ + set2(L, up - 1, i); + return i; + } + /* otherwise, swap a[i] - a[j] to restore invariant and repeat */ + set2(L, i, j); + } +} + + +/* +** Choose an element in the middle (2nd-3th quarters) of [lo,up] +** "randomized" by 'rnd' +*/ +static unsigned int choosePivot (unsigned int lo, unsigned int up, + unsigned int rnd) { + unsigned int r4 = (unsigned int)(up - lo) / 4u; /* range/4 */ + unsigned int p = rnd % (r4 * 2) + (lo + r4); + lua_assert(lo + r4 <= p && p <= up - r4); + return p; +} + + +/* +** QuickSort algorithm (recursive function) +*/ +static void auxsort (lua_State *L, unsigned int lo, unsigned int up, + unsigned int rnd) { + while (lo < up) { /* loop for tail recursion */ + unsigned int p; /* Pivot index */ + unsigned int n; /* to be used later */ + /* sort elements 'lo', 'p', and 'up' */ + lua_geti(L, 1, lo); + lua_geti(L, 1, up); + if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */ + set2(L, lo, up); /* swap a[lo] - a[up] */ else - lua_pop(L, 2); - if (u-l == 1) break; /* only 2 elements */ - i = (l+u)/2; - (*ta->geti)(L, 1, i); - (*ta->geti)(L, 1, l); - if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */ - set2(L, ta, i, l); + lua_pop(L, 2); /* remove both values */ + if (up - lo == 1) /* only 2 elements? */ + return; /* already sorted */ + if (up - lo < RANLIMIT || rnd == 0) /* small interval or no randomize? */ + p = (lo + up)/2; /* middle element is a good pivot */ + else /* for larger intervals, it is worth a random pivot */ + p = choosePivot(lo, up, rnd); + lua_geti(L, 1, p); + lua_geti(L, 1, lo); + if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */ + set2(L, p, lo); /* swap a[p] - a[lo] */ else { - lua_pop(L, 1); /* remove a[l] */ - (*ta->geti)(L, 1, u); - if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */ - set2(L, ta, i, u); + lua_pop(L, 1); /* remove a[lo] */ + lua_geti(L, 1, up); + if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */ + set2(L, p, up); /* swap a[up] - a[p] */ else lua_pop(L, 2); } - if (u-l == 2) break; /* only 3 elements */ - (*ta->geti)(L, 1, i); /* Pivot */ - lua_pushvalue(L, -1); - (*ta->geti)(L, 1, u-1); - set2(L, ta, i, u-1); - /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */ - i = l; j = u-1; - for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ - /* repeat ++i until a[i] >= P */ - while ((*ta->geti)(L, 1, ++i), sort_comp(L, -1, -2)) { - if (i>=u) luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[i] */ - } - /* repeat --j until a[j] <= P */ - while ((*ta->geti)(L, 1, --j), sort_comp(L, -3, -1)) { - if (j<=l) luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[j] */ - } - if (j<i) { - lua_pop(L, 3); /* pop pivot, a[i], a[j] */ - break; - } - set2(L, ta, i, j); - } - (*ta->geti)(L, 1, u-1); - (*ta->geti)(L, 1, i); - set2(L, ta, u-1, i); /* swap pivot (a[u-1]) with a[i] */ - /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ - /* adjust so that smaller half is in [j..i] and larger one in [l..u] */ - if (i-l < u-i) { - j=l; i=i-1; l=i+2; + if (up - lo == 2) /* only 3 elements? */ + return; /* already sorted */ + lua_geti(L, 1, p); /* get middle element (Pivot) */ + lua_pushvalue(L, -1); /* push Pivot */ + lua_geti(L, 1, up - 1); /* push a[up - 1] */ + set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */ + p = partition(L, lo, up); + /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */ + if (p - lo < up - p) { /* lower interval is smaller? */ + auxsort(L, lo, p - 1, rnd); /* call recursively for lower interval */ + n = p - lo; /* size of smaller interval */ + lo = p + 1; /* tail call for [p + 1 .. up] (upper interval) */ } else { - j=i+1; i=u; u=j-2; + auxsort(L, p + 1, up, rnd); /* call recursively for upper interval */ + n = up - p; /* size of smaller interval */ + up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ } - auxsort(L, ta, j, i); /* call recursively the smaller one */ - } /* repeat the routine for the larger one */ + if ((up - lo) / 128u > n) /* partition too imbalanced? */ + rnd = l_randomizePivot(); /* try a new randomization */ + } /* tail call auxsort(L, lo, up, rnd) */ } + static int sort (lua_State *L) { - TabA ta; - int n = (int)aux_getn(L, 1, &ta); - luaL_checkstack(L, 50, ""); /* assume array is smaller than 2^50 */ - if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ - luaL_checktype(L, 2, LUA_TFUNCTION); - lua_settop(L, 2); /* make sure there are two arguments */ - auxsort(L, &ta, 1, n); + lua_Integer n = aux_getn(L, 1, TAB_RW); + if (n > 1) { /* non-trivial interval? */ + luaL_argcheck(L, n < INT_MAX, 1, "array too big"); + luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */ + if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ + luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ + lua_settop(L, 2); /* make sure there are two arguments */ + auxsort(L, 1, (unsigned int)n, 0u); + } return 0; } diff --git a/plugins/MirLua/src/lua/ltm.c b/plugins/MirLua/src/lua/ltm.c index c38e5c34b5..22b4df39df 100644 --- a/plugins/MirLua/src/lua/ltm.c +++ b/plugins/MirLua/src/lua/ltm.c @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 2.34 2015/03/30 15:42:27 roberto Exp $ +** $Id: ltm.c,v 2.36 2015/11/03 15:47:30 roberto Exp $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -57,7 +57,7 @@ void luaT_init (lua_State *L) { ** tag methods */ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { - const TValue *tm = luaH_getstr(events, ename); + const TValue *tm = luaH_getshortstr(events, ename); lua_assert(event <= TM_EQ); if (ttisnil(tm)) { /* no tag method? */ events->flags |= cast_byte(1u<<event); /* cache this fact */ @@ -79,20 +79,25 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { default: mt = G(L)->mt[ttnov(o)]; } - return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); + return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject); } void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, TValue *p3, int hasres) { ptrdiff_t result = savestack(L, p3); - setobj2s(L, L->top++, f); /* push function (assume EXTRA_STACK) */ - setobj2s(L, L->top++, p1); /* 1st argument */ - setobj2s(L, L->top++, p2); /* 2nd argument */ + StkId func = L->top; + setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ + setobj2s(L, func + 1, p1); /* 1st argument */ + setobj2s(L, func + 2, p2); /* 2nd argument */ + L->top += 3; if (!hasres) /* no result? 'p3' is third argument */ setobj2s(L, L->top++, p3); /* 3rd argument */ /* metamethod may yield only when called from Lua code */ - luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); + if (isLua(L->ci)) + luaD_call(L, func, hasres); + else + luaD_callnoyield(L, func, hasres); if (hasres) { /* if has result, move it to its place */ p3 = restorestack(L, result); setobjs2s(L, p3, --L->top); diff --git a/plugins/MirLua/src/lua/lua.h b/plugins/MirLua/src/lua/lua.h index 1c2b95ac4b..06381d7159 100644 --- a/plugins/MirLua/src/lua/lua.h +++ b/plugins/MirLua/src/lua/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.328 2015/06/03 13:03:38 roberto Exp $ +** $Id: lua.h,v 1.329 2015/11/13 17:18:42 roberto Exp $ ** Lua - A Scripting Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file @@ -19,7 +19,7 @@ #define LUA_VERSION_MAJOR "5" #define LUA_VERSION_MINOR "3" #define LUA_VERSION_NUM 503 -#define LUA_VERSION_RELEASE "1" +#define LUA_VERSION_RELEASE "2" #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE diff --git a/plugins/MirLua/src/lua/luaconf.h b/plugins/MirLua/src/lua/luaconf.h index 7cfa4faf77..b4ed500118 100644 --- a/plugins/MirLua/src/lua/luaconf.h +++ b/plugins/MirLua/src/lua/luaconf.h @@ -1,5 +1,5 @@ /* -** $Id: luaconf.h,v 1.251 2015/05/20 17:39:23 roberto Exp $ +** $Id: luaconf.h,v 1.254 2015/10/21 18:17:40 roberto Exp $ ** Configuration file for Lua ** See Copyright Notice in lua.h */ @@ -145,7 +145,7 @@ #if !defined(LUA_FLOAT_TYPE) #define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE -#endif /* } */ +#endif /* }================================================================== */ @@ -412,9 +412,33 @@ @@ LUA_NUMBER_FMT is the format for writing floats. @@ lua_number2str converts a float to a string. @@ l_mathop allows the addition of an 'l' or 'f' to all math operations. +@@ l_floor takes the floor of a float. @@ lua_str2number converts a decimal numeric string to a number. */ + +/* The following definitions are good for most cases here */ + +#define l_floor(x) (l_mathop(floor)(x)) + +#define lua_number2str(s,sz,n) l_sprintf((s), sz, LUA_NUMBER_FMT, (n)) + +/* +@@ lua_numbertointeger converts a float number to an integer, or +** returns 0 if float is not within the range of a lua_Integer. +** (The range comparisons are tricky because of rounding. The tests +** here assume a two-complement representation, where MININTEGER always +** has an exact representation as a float; MAXINTEGER may not have one, +** and therefore its conversion to float may have an ill-defined value.) +*/ +#define lua_numbertointeger(n,p) \ + ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \ + (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \ + (*(p) = (LUA_INTEGER)(n), 1)) + + +/* now the variable definitions */ + #if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */ #define LUA_NUMBER float @@ -468,25 +492,6 @@ #endif /* } */ -#define l_floor(x) (l_mathop(floor)(x)) - -#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) - - -/* -@@ lua_numbertointeger converts a float number to an integer, or -** returns 0 if float is not within the range of a lua_Integer. -** (The range comparisons are tricky because of rounding. The tests -** here assume a two-complement representation, where MININTEGER always -** has an exact representation as a float; MAXINTEGER may not have one, -** and therefore its conversion to float may have an ill-defined value.) -*/ -#define lua_numbertointeger(n,p) \ - ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \ - (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \ - (*(p) = (LUA_INTEGER)(n), 1)) - - /* @@ LUA_INTEGER is the integer type used by Lua. @@ -506,7 +511,7 @@ /* The following definitions are good for most cases here */ #define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d" -#define lua_integer2str(s,n) sprintf((s), LUA_INTEGER_FMT, (n)) +#define lua_integer2str(s,sz,n) l_sprintf((s), sz, LUA_INTEGER_FMT, (n)) #define LUAI_UACINT LUA_INTEGER @@ -537,6 +542,7 @@ #elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */ +/* use presence of macro LLONG_MAX as proxy for C99 compliance */ #if defined(LLONG_MAX) /* { */ /* use ISO C99 stuff */ @@ -578,13 +584,24 @@ */ /* +@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89. +** (All uses in Lua have only one format item.) +*/ +#if !defined(LUA_USE_C89) +#define l_sprintf(s,sz,f,i) snprintf(s,sz,f,i) +#else +#define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s,f,i)) +#endif + + +/* @@ lua_strx2number converts an hexadecimal numeric string to a number. ** In C99, 'strtod' does that conversion. Otherwise, you can ** leave 'lua_strx2number' undefined and Lua will provide its own ** implementation. */ #if !defined(LUA_USE_C89) -#define lua_strx2number(s,p) lua_str2number(s,p) +#define lua_strx2number(s,p) lua_str2number(s,p) #endif @@ -595,7 +612,7 @@ ** provide its own implementation. */ #if !defined(LUA_USE_C89) -#define lua_number2strx(L,b,f,n) sprintf(b,f,n) +#define lua_number2strx(L,b,sz,f,n) l_sprintf(b,sz,f,n) #endif diff --git a/plugins/MirLua/src/lua/lundump.c b/plugins/MirLua/src/lua/lundump.c index 510f325827..4080af9c0d 100644 --- a/plugins/MirLua/src/lua/lundump.c +++ b/plugins/MirLua/src/lua/lundump.c @@ -1,5 +1,5 @@ /* -** $Id: lundump.c,v 2.41 2014/11/02 19:19:04 roberto Exp $ +** $Id: lundump.c,v 2.44 2015/11/02 16:09:30 roberto Exp $ ** load precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -32,7 +32,6 @@ typedef struct { lua_State *L; ZIO *Z; - Mbuffer *b; const char *name; } LoadState; @@ -92,10 +91,15 @@ static TString *LoadString (LoadState *S) { LoadVar(S, size); if (size == 0) return NULL; - else { - char *s = luaZ_openspace(S->L, S->b, --size); - LoadVector(S, s, size); - return luaS_newlstr(S->L, s, size); + else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ + char buff[LUAI_MAXSHORTLEN]; + LoadVector(S, buff, size); + return luaS_newlstr(S->L, buff, size); + } + else { /* long string */ + TString *ts = luaS_createlngstrobj(S->L, size); + LoadVector(S, getstr(ts), size); /* load directly in final place */ + return ts; } } @@ -251,8 +255,7 @@ static void checkHeader (LoadState *S) { /* ** load precompiled chunk */ -LClosure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff, - const char *name) { +LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { LoadState S; LClosure *cl; if (*name == '@' || *name == '=') @@ -263,11 +266,10 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, Mbuffer *buff, S.name = name; S.L = L; S.Z = Z; - S.b = buff; checkHeader(&S); cl = luaF_newLclosure(L, LoadByte(&S)); setclLvalue(L, L->top, cl); - incr_top(L); + luaD_inctop(L); cl->p = luaF_newproto(L); LoadFunction(&S, cl->p, NULL); lua_assert(cl->nupvalues == cl->p->sizeupvalues); diff --git a/plugins/MirLua/src/lua/lundump.h b/plugins/MirLua/src/lua/lundump.h index ef43d51264..aa5cc82f1b 100644 --- a/plugins/MirLua/src/lua/lundump.h +++ b/plugins/MirLua/src/lua/lundump.h @@ -1,5 +1,5 @@ /* -** $Id: lundump.h,v 1.44 2014/06/19 18:27:20 roberto Exp $ +** $Id: lundump.h,v 1.45 2015/09/08 15:41:05 roberto Exp $ ** load precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -23,8 +23,7 @@ #define LUAC_FORMAT 0 /* this is the official format */ /* load one chunk; from lundump.c */ -LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, - const char* name); +LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name); /* dump one chunk; from ldump.c */ LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, diff --git a/plugins/MirLua/src/lua/lvm.c b/plugins/MirLua/src/lua/lvm.c index a8cefc52b1..aba7ace817 100644 --- a/plugins/MirLua/src/lua/lvm.c +++ b/plugins/MirLua/src/lua/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.245 2015/06/09 15:53:35 roberto Exp $ +** $Id: lvm.c,v 2.265 2015/11/23 11:30:45 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -153,30 +153,28 @@ static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, /* -** Main function for table access (invoking metamethods if needed). -** Compute 'val = t[key]' +** Complete a table access: if 't' is a table, 'tm' has its metamethod; +** otherwise, 'tm' is NULL. */ -void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { +void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, + const TValue *tm) { int loop; /* counter to avoid infinite loops */ + lua_assert(tm != NULL || !ttistable(t)); for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (ttistable(t)) { /* 't' is a table? */ - Table *h = hvalue(t); - const TValue *res = luaH_get(h, key); /* do a primitive get */ - if (!ttisnil(res) || /* result is not nil? */ - (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ - setobj2s(L, val, res); /* result is the raw get */ - return; - } - /* else will try metamethod */ + if (tm == NULL) { /* no metamethod (from a table)? */ + if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) + luaG_typeerror(L, t, "index"); /* no metamethod */ } - else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) - luaG_typeerror(L, t, "index"); /* no metamethod */ if (ttisfunction(tm)) { /* metamethod is a function */ - luaT_callTM(L, tm, t, key, val, 1); + luaT_callTM(L, tm, t, key, val, 1); /* call it */ return; } t = tm; /* else repeat access over 'tm' */ + if (luaV_fastget(L,t,key,tm,luaH_get)) { /* try fast track */ + setobj2s(L, val, tm); /* done */ + return; + } + /* else repeat */ } luaG_runerror(L, "gettable chain too long; possible loop"); } @@ -186,40 +184,41 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { ** Main function for table assignment (invoking metamethods if needed). ** Compute 't[key] = val' */ -void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { +void luaV_finishset (lua_State *L, const TValue *t, TValue *key, + StkId val, const TValue *oldval) { int loop; /* counter to avoid infinite loops */ for (loop = 0; loop < MAXTAGLOOP; loop++) { const TValue *tm; - if (ttistable(t)) { /* 't' is a table? */ - Table *h = hvalue(t); - TValue *oldval = cast(TValue *, luaH_get(h, key)); - /* if previous value is not nil, there must be a previous entry - in the table; a metamethod has no relevance */ - if (!ttisnil(oldval) || - /* previous value is nil; must check the metamethod */ - ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && + if (oldval != NULL) { + lua_assert(ttistable(t) && ttisnil(oldval)); + /* must check the metamethod */ + if ((tm = fasttm(L, hvalue(t)->metatable, TM_NEWINDEX)) == NULL && /* no metamethod; is there a previous entry in the table? */ (oldval != luaO_nilobject || /* no previous entry; must create one. (The next test is always true; we only need the assignment.) */ - (oldval = luaH_newkey(L, h, key), 1)))) { + (oldval = luaH_newkey(L, hvalue(t), key), 1))) { /* no metamethod and (now) there is an entry with given key */ - setobj2t(L, oldval, val); /* assign new value to that entry */ - invalidateTMcache(h); - luaC_barrierback(L, h, val); + setobj2t(L, cast(TValue *, oldval), val); + invalidateTMcache(hvalue(t)); + luaC_barrierback(L, hvalue(t), val); return; } /* else will try the metamethod */ } - else /* not a table; check metamethod */ + else { /* not a table; check metamethod */ if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) luaG_typeerror(L, t, "index"); + } /* try the metamethod */ if (ttisfunction(tm)) { luaT_callTM(L, tm, t, key, val, 0); return; } t = tm; /* else repeat assignment over 'tm' */ + if (luaV_fastset(L, t, key, oldval, luaH_get, val)) + return; /* done */ + /* else loop */ } luaG_runerror(L, "settable chain too long; possible loop"); } @@ -443,6 +442,17 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { #define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0) +/* copy strings in stack from top - n up to top - 1 to buffer */ +static void copy2buff (StkId top, int n, char *buff) { + size_t tl = 0; /* size already copied */ + do { + size_t l = vslen(top - n); /* length of string being copied */ + memcpy(buff + tl, svalue(top - n), l * sizeof(char)); + tl += l; + } while (--n > 0); +} + + /* ** Main operation for concatenation: concat 'total' values in the stack, ** from 'L->top - total' up to 'L->top - 1'. @@ -462,24 +472,24 @@ void luaV_concat (lua_State *L, int total) { else { /* at least two non-empty string values; get as many as possible */ size_t tl = vslen(top - 1); - char *buffer; - int i; - /* collect total length */ - for (i = 1; i < total && tostring(L, top-i-1); i++) { - size_t l = vslen(top - i - 1); + TString *ts; + /* collect total length and number of strings */ + for (n = 1; n < total && tostring(L, top - n - 1); n++) { + size_t l = vslen(top - n - 1); if (l >= (MAX_SIZE/sizeof(char)) - tl) luaG_runerror(L, "string length overflow"); tl += l; } - buffer = luaZ_openspace(L, &G(L)->buff, tl); - tl = 0; - n = i; - do { /* copy all strings to buffer */ - size_t l = vslen(top - i); - memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); - tl += l; - } while (--i > 0); - setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); /* create result */ + if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */ + char buff[LUAI_MAXSHORTLEN]; + copy2buff(top, n, buff); /* copy strings to buffer */ + ts = luaS_newlstr(L, buff, tl); + } + else { /* long string; copy strings directly to final result */ + ts = luaS_createlngstrobj(L, tl); + copy2buff(top, n, getstr(ts)); + } + setsvalue2s(L, top - n, ts); /* create result */ } total -= n-1; /* got 'n' strings to create 1 new */ L->top -= n-1; /* popped 'n' strings and pushed one */ @@ -700,27 +710,20 @@ void luaV_finishOp (lua_State *L) { ** some macros for common tasks in 'luaV_execute' */ -#if !defined(luai_runtimecheck) -#define luai_runtimecheck(L, c) /* void */ -#endif - #define RA(i) (base+GETARG_A(i)) -/* to be used after possible stack reallocation */ #define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) #define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) #define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) #define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) -#define KBx(i) \ - (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++))) /* execute a jump instruction */ #define dojump(ci,i,e) \ { int a = GETARG_A(i); \ - if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \ + if (a != 0) luaF_close(L, ci->u.l.base + a - 1); \ ci->u.l.savedpc += GETARG_sBx(i) + e; } /* for test instructions, execute the jump instruction that follows it */ @@ -730,34 +733,49 @@ void luaV_finishOp (lua_State *L) { #define Protect(x) { {x;}; base = ci->u.l.base; } #define checkGC(L,c) \ - Protect( luaC_condGC(L,{L->top = (c); /* limit of live values */ \ - luaC_step(L); \ - L->top = ci->top;}) /* restore top */ \ - luai_threadyield(L); ) + { luaC_condGC(L, L->top = (c), /* limit of live values */ \ + Protect(L->top = ci->top)); /* restore top */ \ + luai_threadyield(L); } #define vmdispatch(o) switch(o) #define vmcase(l) case l: #define vmbreak break + +/* +** copy of 'luaV_gettable', but protecting call to potential metamethod +** (which can reallocate the stack) +*/ +#define gettableProtected(L,t,k,v) { const TValue *aux; \ + if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \ + else Protect(luaV_finishget(L,t,k,v,aux)); } + + +/* same for 'luaV_settable' */ +#define settableProtected(L,t,k,v) { const TValue *slot; \ + if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \ + Protect(luaV_finishset(L,t,k,v,slot)); } + + + void luaV_execute (lua_State *L) { CallInfo *ci = L->ci; LClosure *cl; TValue *k; StkId base; + ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ newframe: /* reentry point when frame changes (call/return) */ lua_assert(ci == L->ci); - cl = clLvalue(ci->func); - k = cl->p->k; - base = ci->u.l.base; + cl = clLvalue(ci->func); /* local reference to function's closure */ + k = cl->p->k; /* local reference to function's constant table */ + base = ci->u.l.base; /* local copy of function's base */ /* main loop of interpreter */ for (;;) { Instruction i = *(ci->u.l.savedpc++); StkId ra; - if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && - (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { + if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) Protect(luaG_traceexec(L)); - } /* WARNING: several calls may realloc the stack and invalidate 'ra' */ ra = RA(i); lua_assert(base == ci->u.l.base); @@ -797,17 +815,22 @@ void luaV_execute (lua_State *L) { vmbreak; } vmcase(OP_GETTABUP) { - int b = GETARG_B(i); - Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); + TValue *upval = cl->upvals[GETARG_B(i)]->v; + TValue *rc = RKC(i); + gettableProtected(L, upval, rc, ra); vmbreak; } vmcase(OP_GETTABLE) { - Protect(luaV_gettable(L, RB(i), RKC(i), ra)); + StkId rb = RB(i); + TValue *rc = RKC(i); + gettableProtected(L, rb, rc, ra); vmbreak; } vmcase(OP_SETTABUP) { - int a = GETARG_A(i); - Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i))); + TValue *upval = cl->upvals[GETARG_A(i)]->v; + TValue *rb = RKB(i); + TValue *rc = RKC(i); + settableProtected(L, upval, rb, rc); vmbreak; } vmcase(OP_SETUPVAL) { @@ -817,7 +840,9 @@ void luaV_execute (lua_State *L) { vmbreak; } vmcase(OP_SETTABLE) { - Protect(luaV_settable(L, ra, RKB(i), RKC(i))); + TValue *rb = RKB(i); + TValue *rc = RKC(i); + settableProtected(L, ra, rb, rc); vmbreak; } vmcase(OP_NEWTABLE) { @@ -831,9 +856,15 @@ void luaV_execute (lua_State *L) { vmbreak; } vmcase(OP_SELF) { + const TValue *aux; StkId rb = RB(i); - setobjs2s(L, ra+1, rb); - Protect(luaV_gettable(L, rb, RKC(i), ra)); + TValue *rc = RKC(i); + TString *key = tsvalue(rc); /* key must be a string */ + setobjs2s(L, ra + 1, rb); + if (luaV_fastget(L, rb, key, aux, luaH_getstr)) { + setobj2s(L, ra, aux); + } + else Protect(luaV_finishget(L, rb, rc, ra, aux)); vmbreak; } vmcase(OP_ADD) { @@ -1020,7 +1051,7 @@ void luaV_execute (lua_State *L) { StkId rb; L->top = base + c + 1; /* mark the end of concat operands */ Protect(luaV_concat(L, c - b + 1)); - ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */ + ra = RA(i); /* 'luaV_concat' may invoke TMs and move the stack */ rb = base + b; setobjs2s(L, ra, rb); checkGC(L, (ra >= rb ? ra + 1 : rb)); @@ -1035,7 +1066,7 @@ void luaV_execute (lua_State *L) { TValue *rb = RKB(i); TValue *rc = RKC(i); Protect( - if (cast_int(luaV_equalobj(L, rb, rc)) != GETARG_A(i)) + if (luaV_equalobj(L, rb, rc) != GETARG_A(i)) ci->u.l.savedpc++; else donextjump(ci); @@ -1082,12 +1113,12 @@ void luaV_execute (lua_State *L) { int nresults = GETARG_C(i) - 1; if (b != 0) L->top = ra+b; /* else previous instruction set top */ if (luaD_precall(L, ra, nresults)) { /* C function? */ - if (nresults >= 0) L->top = ci->top; /* adjust results */ - base = ci->u.l.base; + if (nresults >= 0) + L->top = ci->top; /* adjust results */ + Protect((void)0); /* update 'base' */ } else { /* Lua function */ ci = L->ci; - ci->callstatus |= CIST_REENTRY; goto newframe; /* restart luaV_execute over new Lua function */ } vmbreak; @@ -1096,8 +1127,9 @@ void luaV_execute (lua_State *L) { int b = GETARG_B(i); if (b != 0) L->top = ra+b; /* else previous instruction set top */ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); - if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */ - base = ci->u.l.base; + if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */ + Protect((void)0); /* update 'base' */ + } else { /* tail call: put called frame (n) in place of caller one (o) */ CallInfo *nci = L->ci; /* called frame */ @@ -1125,8 +1157,8 @@ void luaV_execute (lua_State *L) { vmcase(OP_RETURN) { int b = GETARG_B(i); if (cl->p->sizep > 0) luaF_close(L, base); - b = luaD_poscall(L, ra, (b != 0 ? b - 1 : L->top - ra)); - if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */ + b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); + if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */ return; /* external invocation: return */ else { /* invocation via reentry: continue execution */ ci = L->ci; @@ -1139,7 +1171,7 @@ void luaV_execute (lua_State *L) { vmcase(OP_FORLOOP) { if (ttisinteger(ra)) { /* integer loop? */ lua_Integer step = ivalue(ra + 2); - lua_Integer idx = ivalue(ra) + step; /* increment index */ + lua_Integer idx = intop(+, ivalue(ra), step); /* increment index */ lua_Integer limit = ivalue(ra + 1); if ((0 < step) ? (idx <= limit) : (limit <= idx)) { ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ @@ -1171,7 +1203,7 @@ void luaV_execute (lua_State *L) { /* all values are integer */ lua_Integer initv = (stopnow ? 0 : ivalue(init)); setivalue(plimit, ilimit); - setivalue(init, initv - ivalue(pstep)); + setivalue(init, intop(-, initv, ivalue(pstep))); } else { /* try making all values floats */ lua_Number ninit; lua_Number nlimit; lua_Number nstep; @@ -1194,7 +1226,7 @@ void luaV_execute (lua_State *L) { setobjs2s(L, cb+1, ra+1); setobjs2s(L, cb, ra); L->top = cb + 3; /* func. + 2 args (state and index) */ - Protect(luaD_call(L, cb, GETARG_C(i), 1)); + Protect(luaD_call(L, cb, GETARG_C(i))); L->top = ci->top; i = *(ci->u.l.savedpc++); /* go to next instruction */ ra = RA(i); @@ -1219,11 +1251,10 @@ void luaV_execute (lua_State *L) { lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); c = GETARG_Ax(*ci->u.l.savedpc++); } - luai_runtimecheck(L, ttistable(ra)); h = hvalue(ra); last = ((c-1)*LFIELDS_PER_FLUSH) + n; if (last > h->sizearray) /* needs more space? */ - luaH_resizearray(L, h, last); /* pre-allocate it at once */ + luaH_resizearray(L, h, last); /* preallocate it at once */ for (; n > 0; n--) { TValue *val = ra+n; luaH_setint(L, h, last--, val); @@ -1243,23 +1274,21 @@ void luaV_execute (lua_State *L) { vmbreak; } vmcase(OP_VARARG) { - int b = GETARG_B(i) - 1; + int b = GETARG_B(i) - 1; /* required results */ int j; int n = cast_int(base - ci->func) - cl->p->numparams - 1; + if (n < 0) /* less arguments than parameters? */ + n = 0; /* no vararg arguments */ if (b < 0) { /* B == 0? */ b = n; /* get all var. arguments */ Protect(luaD_checkstack(L, n)); ra = RA(i); /* previous call may change the stack */ L->top = ra + n; } - for (j = 0; j < b; j++) { - if (j < n) { - setobjs2s(L, ra + j, base - n + j); - } - else { - setnilvalue(ra + j); - } - } + for (j = 0; j < b && j < n; j++) + setobjs2s(L, ra + j, base - n + j); + for (; j < b; j++) /* complete required results with nil */ + setnilvalue(ra + j); vmbreak; } vmcase(OP_EXTRAARG) { diff --git a/plugins/MirLua/src/lua/lvm.h b/plugins/MirLua/src/lua/lvm.h index 0613826a62..fd0e748d4e 100644 --- a/plugins/MirLua/src/lua/lvm.h +++ b/plugins/MirLua/src/lua/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.35 2015/02/20 14:27:53 roberto Exp $ +** $Id: lvm.h,v 2.39 2015/09/09 13:44:07 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -48,15 +48,61 @@ #define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) +/* +** fast track for 'gettable': 1 means 'aux' points to resulted value; +** 0 means 'aux' is metamethod (if 't' is a table) or NULL. 'f' is +** the raw get function to use. +*/ +#define luaV_fastget(L,t,k,aux,f) \ + (!ttistable(t) \ + ? (aux = NULL, 0) /* not a table; 'aux' is NULL and result is 0 */ \ + : (aux = f(hvalue(t), k), /* else, do raw access */ \ + !ttisnil(aux) ? 1 /* result not nil? 'aux' has it */ \ + : (aux = fasttm(L, hvalue(t)->metatable, TM_INDEX), /* get metamethod */\ + aux != NULL ? 0 /* has metamethod? must call it */ \ + : (aux = luaO_nilobject, 1)))) /* else, final result is nil */ + +/* +** standard implementation for 'gettable' +*/ +#define luaV_gettable(L,t,k,v) { const TValue *aux; \ + if (luaV_fastget(L,t,k,aux,luaH_get)) { setobj2s(L, v, aux); } \ + else luaV_finishget(L,t,k,v,aux); } + + +/* +** Fast track for set table. If 't' is a table and 't[k]' is not nil, +** call GC barrier, do a raw 't[k]=v', and return true; otherwise, +** return false with 'slot' equal to NULL (if 't' is not a table) or +** 'nil'. (This is needed by 'luaV_finishget'.) Note that, if the macro +** returns true, there is no need to 'invalidateTMcache', because the +** call is not creating a new entry. +*/ +#define luaV_fastset(L,t,k,slot,f,v) \ + (!ttistable(t) \ + ? (slot = NULL, 0) \ + : (slot = f(hvalue(t), k), \ + ttisnil(slot) ? 0 \ + : (luaC_barrierback(L, hvalue(t), v), \ + setobj2t(L, cast(TValue *,slot), v), \ + 1))) + + +#define luaV_settable(L,t,k,v) { const TValue *slot; \ + if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \ + luaV_finishset(L,t,k,v,slot); } + + + LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); -LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, - StkId val); -LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, - StkId val); +LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, + StkId val, const TValue *tm); +LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, + StkId val, const TValue *oldval); LUAI_FUNC void luaV_finishOp (lua_State *L); LUAI_FUNC void luaV_execute (lua_State *L); LUAI_FUNC void luaV_concat (lua_State *L, int total); diff --git a/plugins/MirLua/src/lua/lzio.c b/plugins/MirLua/src/lua/lzio.c index 46493920f4..c9e1f491f3 100644 --- a/plugins/MirLua/src/lua/lzio.c +++ b/plugins/MirLua/src/lua/lzio.c @@ -1,5 +1,5 @@ /* -** $Id: lzio.c,v 1.36 2014/11/02 19:19:04 roberto Exp $ +** $Id: lzio.c,v 1.37 2015/09/08 15:41:05 roberto Exp $ ** Buffered streams ** See Copyright Notice in lua.h */ @@ -66,13 +66,3 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) { return 0; } -/* ------------------------------------------------------------------------ */ -char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { - if (n > buff->buffsize) { - if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; - luaZ_resizebuffer(L, buff, n); - } - return buff->buffer; -} - - diff --git a/plugins/MirLua/src/lua/lzio.h b/plugins/MirLua/src/lua/lzio.h index b2e56bcd6e..e7b6f34b1e 100644 --- a/plugins/MirLua/src/lua/lzio.h +++ b/plugins/MirLua/src/lua/lzio.h @@ -1,5 +1,5 @@ /* -** $Id: lzio.h,v 1.30 2014/12/19 17:26:14 roberto Exp $ +** $Id: lzio.h,v 1.31 2015/09/08 15:41:05 roberto Exp $ ** Buffered streams ** See Copyright Notice in lua.h */ @@ -44,7 +44,6 @@ typedef struct Mbuffer { #define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) -LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data); LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ |