From a51a728d847e790329e41c75928a81630200b63f Mon Sep 17 00:00:00 2001 From: Li Jin Date: Thu, 22 Oct 2020 16:02:39 +0800 Subject: update Lua, fix cmakelists.txt. --- src/lua/lapi.c | 19 ++++--- src/lua/lctype.h | 14 ++++-- src/lua/ldblib.c | 29 ++++++----- src/lua/ldo.c | 145 +++++++++++++++++++++++++++++++++-------------------- src/lua/ldo.h | 1 + src/lua/lfunc.c | 2 +- src/lua/lgc.c | 52 ++++++++++--------- src/lua/llex.c | 1 - src/lua/llex.h | 8 ++- src/lua/llimits.h | 13 ++++- src/lua/lobject.h | 18 ++++--- src/lua/lopcodes.h | 4 +- src/lua/lparser.c | 8 ++- src/lua/lstate.c | 96 +++++++++++------------------------ src/lua/lstate.h | 102 ++++++++++++++----------------------- src/lua/lstring.c | 20 ++------ src/lua/lstring.h | 3 +- src/lua/lstrlib.c | 19 +++---- src/lua/ltable.c | 27 ++++++---- src/lua/lua.h | 2 +- src/lua/luaconf.h | 15 ------ src/lua/lvm.c | 75 ++++++++++++++++----------- src/lua/makefile | 3 -- 23 files changed, 342 insertions(+), 334 deletions(-) (limited to 'src') diff --git a/src/lua/lapi.c b/src/lua/lapi.c index 9048245..c824da2 100644 --- a/src/lua/lapi.c +++ b/src/lua/lapi.c @@ -1383,13 +1383,16 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { + static const UpVal *const nullup = NULL; LClosure *f; TValue *fi = index2value(L, fidx); api_check(L, ttisLclosure(fi), "Lua function expected"); f = clLvalue(fi); - api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); if (pf) *pf = f; - return &f->upvals[n - 1]; /* get its upvalue pointer */ + if (1 <= n && n <= f->p->sizeupvalues) + return &f->upvals[n - 1]; /* get its upvalue pointer */ + else + return (UpVal**)&nullup; } @@ -1401,11 +1404,14 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { } case LUA_VCCL: { /* C closure */ CClosure *f = clCvalue(fi); - api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); - return &f->upvalue[n - 1]; - } + if (1 <= n && n <= f->nupvalues) + return &f->upvalue[n - 1]; + /* else */ + } /* FALLTHROUGH */ + case LUA_VLCF: + return NULL; /* light C functions have no upvalues */ default: { - api_check(L, 0, "closure expected"); + api_check(L, 0, "function expected"); return NULL; } } @@ -1417,6 +1423,7 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, LClosure *f1; UpVal **up1 = getupvalref(L, fidx1, n1, &f1); UpVal **up2 = getupvalref(L, fidx2, n2, NULL); + api_check(L, *up1 != NULL && *up2 != NULL, "invalid upvalue index"); *up1 = *up2; luaC_objbarrier(L, f1, *up1); } diff --git a/src/lua/lctype.h b/src/lua/lctype.h index cbff4d7..864e190 100644 --- a/src/lua/lctype.h +++ b/src/lua/lctype.h @@ -13,7 +13,7 @@ /* ** WARNING: the functions defined here do not necessarily correspond ** to the similar functions in the standard C ctype.h. They are -** optimized for the specific needs of Lua +** optimized for the specific needs of Lua. */ #if !defined(LUA_USE_CTYPE) @@ -61,13 +61,19 @@ #define lisprint(c) testprop(c, MASK(PRINTBIT)) #define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) + /* -** this 'ltolower' only works for alphabetic characters +** In ASCII, this 'ltolower' is correct for alphabetic characters and +** for '.'. That is enough for Lua needs. ('check_exp' ensures that +** the character either is an upper-case letter or is unchanged by +** the transformation, which holds for lower-case letters and '.'.) */ -#define ltolower(c) ((c) | ('A' ^ 'a')) +#define ltolower(c) \ + check_exp(('A' <= (c) && (c) <= 'Z') || (c) == ((c) | ('A' ^ 'a')), \ + (c) | ('A' ^ 'a')) -/* two more entries for 0 and -1 (EOZ) */ +/* one entry for each character and for -1 (EOZ) */ LUAI_DDEC(const lu_byte luai_ctype_[UCHAR_MAX + 2];) diff --git a/src/lua/ldblib.c b/src/lua/ldblib.c index 59eb8f0..5a326ad 100644 --- a/src/lua/ldblib.c +++ b/src/lua/ldblib.c @@ -281,25 +281,33 @@ static int db_setupvalue (lua_State *L) { ** Check whether a given upvalue from a given closure exists and ** returns its index */ -static int checkupval (lua_State *L, int argf, int argnup) { +static void *checkupval (lua_State *L, int argf, int argnup, int *pnup) { + void *id; int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */ luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */ - luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup, - "invalid upvalue index"); - return nup; + id = lua_upvalueid(L, argf, nup); + if (pnup) { + luaL_argcheck(L, id != NULL, argnup, "invalid upvalue index"); + *pnup = nup; + } + return id; } static int db_upvalueid (lua_State *L) { - int n = checkupval(L, 1, 2); - lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); + void *id = checkupval(L, 1, 2, NULL); + if (id != NULL) + lua_pushlightuserdata(L, id); + else + luaL_pushfail(L); return 1; } static int db_upvaluejoin (lua_State *L) { - int n1 = checkupval(L, 1, 2); - int n2 = checkupval(L, 3, 4); + int n1, n2; + checkupval(L, 1, 2, &n1); + checkupval(L, 3, 4, &n2); luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); lua_upvaluejoin(L, 1, n1, 3, n2); @@ -440,10 +448,7 @@ static int db_traceback (lua_State *L) { static int db_setcstacklimit (lua_State *L) { int limit = (int)luaL_checkinteger(L, 1); int res = lua_setcstacklimit(L, limit); - if (res == 0) - lua_pushboolean(L, 0); - else - lua_pushinteger(L, res); + lua_pushinteger(L, res); return 1; } diff --git a/src/lua/ldo.c b/src/lua/ldo.c index 5473815..5729b19 100644 --- a/src/lua/ldo.c +++ b/src/lua/ldo.c @@ -139,8 +139,7 @@ l_noret luaD_throw (lua_State *L, int errcode) { int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { - global_State *g = G(L); - l_uint32 oldnCcalls = g->Cstacklimit - (L->nCcalls + L->nci); + l_uint32 oldnCcalls = L->nCcalls; struct lua_longjmp lj; lj.status = LUA_OK; lj.previous = L->errorJmp; /* chain new error handler */ @@ -149,7 +148,7 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { (*f)(L, ud); ); L->errorJmp = lj.previous; /* restore old error handler */ - L->nCcalls = g->Cstacklimit - oldnCcalls - L->nci; + L->nCcalls = oldnCcalls; return lj.status; } @@ -183,10 +182,10 @@ static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { - int lim = L->stacksize; - StkId newstack = luaM_reallocvector(L, L->stack, lim, newsize, StackValue); + int lim = stacksize(L); + StkId newstack = luaM_reallocvector(L, L->stack, + lim + EXTRA_STACK, newsize + EXTRA_STACK, StackValue); lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); if (unlikely(newstack == NULL)) { /* reallocation failed? */ if (raiseerror) luaM_error(L); @@ -196,8 +195,7 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { setnilvalue(s2v(newstack + lim)); /* erase new segment */ correctstack(L, L->stack, newstack); L->stack = newstack; - L->stacksize = newsize; - L->stack_last = L->stack + newsize - EXTRA_STACK; + L->stack_last = L->stack + newsize; return 1; } @@ -207,51 +205,73 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { ** is true, raises any error; otherwise, return 0 in case of errors. */ int luaD_growstack (lua_State *L, int n, int raiseerror) { - int size = L->stacksize; - int newsize = 2 * size; /* tentative new size */ - if (unlikely(size > LUAI_MAXSTACK)) { /* need more space after extra size? */ + int size = stacksize(L); + if (unlikely(size > LUAI_MAXSTACK)) { + /* if stack is larger than maximum, thread is already using the + extra space reserved for errors, that is, thread is handling + a stack error; cannot grow further than that. */ + lua_assert(stacksize(L) == ERRORSTACKSIZE); if (raiseerror) luaD_throw(L, LUA_ERRERR); /* error inside message handler */ - else return 0; + return 0; /* if not 'raiseerror', just signal it */ } else { - int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; + int newsize = 2 * size; /* tentative new size */ + int needed = cast_int(L->top - L->stack) + n; if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */ newsize = LUAI_MAXSTACK; if (newsize < needed) /* but must respect what was asked for */ newsize = needed; - if (unlikely(newsize > LUAI_MAXSTACK)) { /* stack overflow? */ + if (likely(newsize <= LUAI_MAXSTACK)) + return luaD_reallocstack(L, newsize, raiseerror); + else { /* stack overflow */ /* add extra size to be able to handle the error message */ luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror); if (raiseerror) luaG_runerror(L, "stack overflow"); - else return 0; + return 0; } - } /* else no errors */ - return luaD_reallocstack(L, newsize, raiseerror); + } } static int stackinuse (lua_State *L) { CallInfo *ci; + int res; StkId lim = L->top; for (ci = L->ci; ci != NULL; ci = ci->previous) { if (lim < ci->top) lim = ci->top; } lua_assert(lim <= L->stack_last); - return cast_int(lim - L->stack) + 1; /* part of stack in use */ + res = cast_int(lim - L->stack) + 1; /* part of stack in use */ + if (res < LUA_MINSTACK) + res = LUA_MINSTACK; /* ensure a minimum size */ + return res; } +/* +** If stack size is more than 3 times the current use, reduce that size +** to twice the current use. (So, the final stack size is at most 2/3 the +** previous size, and half of its entries are empty.) +** As a particular case, if stack was handling a stack overflow and now +** it is not, 'max' (limited by LUAI_MAXSTACK) will be smaller than +** stacksize (equal to ERRORSTACKSIZE in this case), and so the stack +** will be reduced to a "regular" size. +*/ void luaD_shrinkstack (lua_State *L) { int inuse = stackinuse(L); - int goodsize = inuse + BASIC_STACK_SIZE; - if (goodsize > LUAI_MAXSTACK) - goodsize = LUAI_MAXSTACK; /* respect stack limit */ + int nsize = inuse * 2; /* proposed new size */ + int max = inuse * 3; /* maximum "reasonable" size */ + if (max > LUAI_MAXSTACK) { + max = LUAI_MAXSTACK; /* respect stack limit */ + if (nsize > LUAI_MAXSTACK) + nsize = LUAI_MAXSTACK; + } /* if thread is currently not handling a stack overflow and its - good size is smaller than current size, shrink its stack */ - if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && goodsize < L->stacksize) - luaD_reallocstack(L, goodsize, 0); /* ok if that fails */ + size is larger than maximum "reasonable" size, shrink it */ + if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) + luaD_reallocstack(L, nsize, 0); /* ok if that fails */ else /* don't change stack */ condmovestack(L,{},{}); /* (change only for debugging) */ luaE_shrinkCI(L); /* shrink CI list */ @@ -348,7 +368,7 @@ static StkId rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) { /* ** Check whether 'func' has a '__call' metafield. If so, put it in the -** stack, below original 'func', so that 'luaD_call' can call it. Raise +** stack, below original 'func', so that 'luaD_precall' can call it. Raise ** an error if there is no '__call' metafield. */ void luaD_tryfuncTM (lua_State *L, StkId func) { @@ -449,12 +469,14 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { /* -** Call a function (C or Lua). The function to be called is at *func. -** The arguments are on the stack, right after the function. -** When returns, all the results are on the stack, starting at the original -** function position. +** Prepares the call to a function (C or Lua). For C functions, also do +** the call. The function to be called is at '*func'. The arguments +** are on the stack, right after the function. Returns the CallInfo +** to be executed, if it was a Lua function. Otherwise (a C function) +** returns NULL, with all the results on the stack, starting at the +** original function position. */ -void luaD_call (lua_State *L, StkId func, int nresults) { +CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { lua_CFunction f; retry: switch (ttypetag(s2v(func))) { @@ -482,7 +504,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) { lua_lock(L); api_checknelems(L, n); luaD_poscall(L, ci, n); - break; + return NULL; } case LUA_VLCL: { /* Lua function */ CallInfo *ci; @@ -494,15 +516,13 @@ void luaD_call (lua_State *L, StkId func, int nresults) { L->ci = ci = next_ci(L); ci->nresults = nresults; ci->u.l.savedpc = p->code; /* starting point */ - ci->callstatus = 0; ci->top = func + 1 + fsize; ci->func = func; L->ci = ci; for (; narg < nfixparams; narg++) setnilvalue(s2v(L->top++)); /* complete missing arguments */ lua_assert(ci->top <= L->stack_last); - luaV_execute(L, ci); /* run the function */ - break; + return ci; } default: { /* not a function */ checkstackGCp(L, 1, func); /* space for metamethod */ @@ -513,17 +533,37 @@ void luaD_call (lua_State *L, StkId func, int nresults) { } +/* +** Call a function (C or Lua). 'inc' can be 1 (increment number +** of recursive invocations in the C stack) or nyci (the same plus +** increment number of non-yieldable calls). +*/ +static void docall (lua_State *L, StkId func, int nResults, int inc) { + CallInfo *ci; + L->nCcalls += inc; + if (unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) + luaE_checkcstack(L); + if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */ + ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */ + luaV_execute(L, ci); /* call it */ + } + L->nCcalls -= inc; +} + + +/* +** External interface for 'docall' +*/ +void luaD_call (lua_State *L, StkId func, int nResults) { + return docall(L, func, nResults, 1); +} + + /* ** Similar to 'luaD_call', but does not allow yields during the call. */ void luaD_callnoyield (lua_State *L, StkId func, int nResults) { - incXCcalls(L); - if (getCcalls(L) <= CSTACKERR) { /* possible C stack overflow? */ - luaE_exitCcall(L); /* to compensate decrement in next call */ - luaE_enterCcall(L); /* check properly */ - } - luaD_call(L, func, nResults); - decXCcalls(L); + return docall(L, func, nResults, nyci); } @@ -601,12 +641,12 @@ static int recover (lua_State *L, int status) { if (ci == NULL) return 0; /* no recovery point */ /* "finish" luaD_pcall */ oldtop = restorestack(L, ci->u2.funcidx); - luaF_close(L, oldtop, status); /* may change the stack */ - oldtop = restorestack(L, ci->u2.funcidx); - luaD_seterrorobj(L, status, oldtop); L->ci = ci; L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ - luaD_shrinkstack(L); + status = luaF_close(L, oldtop, status); /* may change the stack */ + oldtop = restorestack(L, ci->u2.funcidx); + luaD_seterrorobj(L, status, oldtop); + luaD_shrinkstack(L); /* restore stack size in case of overflow */ L->errfunc = ci->u.c.old_errfunc; return 1; /* continue running the coroutine */ } @@ -637,12 +677,12 @@ static void resume (lua_State *L, void *ud) { int n = *(cast(int*, ud)); /* number of arguments */ StkId firstArg = L->top - n; /* first argument */ CallInfo *ci = L->ci; - if (L->status == LUA_OK) { /* starting a coroutine? */ - luaD_call(L, firstArg - 1, LUA_MULTRET); - } + if (L->status == LUA_OK) /* starting a coroutine? */ + docall(L, firstArg - 1, LUA_MULTRET, 1); /* just call its body */ else { /* resuming from previous yield */ lua_assert(L->status == LUA_YIELD); L->status = LUA_OK; /* mark that it is running (again) */ + luaE_incCstack(L); /* control the C stack */ if (isLua(ci)) /* yielded inside a hook? */ luaV_execute(L, ci); /* just continue running Lua code */ else { /* 'common' yield */ @@ -670,12 +710,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, } else if (L->status != LUA_YIELD) /* ended with errors? */ return resume_error(L, "cannot resume dead coroutine", nargs); - if (from == NULL) - L->nCcalls = CSTACKTHREAD; - else /* correct 'nCcalls' for this thread */ - L->nCcalls = getCcalls(from) - L->nci - CSTACKCF; - if (L->nCcalls <= CSTACKERR) - return resume_error(L, "C stack overflow", nargs); + L->nCcalls = (from) ? getCcalls(from) : 0; luai_userstateresume(L, nargs); api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); status = luaD_rawrunprotected(L, resume, &nargs); @@ -754,7 +789,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, status = luaF_close(L, oldtop, status); oldtop = restorestack(L, old_top); /* previous call may change stack */ luaD_seterrorobj(L, status, oldtop); - luaD_shrinkstack(L); + luaD_shrinkstack(L); /* restore stack size in case of overflow */ } L->errfunc = old_errfunc; return status; diff --git a/src/lua/ldo.h b/src/lua/ldo.h index 6c6cb28..4d30d07 100644 --- a/src/lua/ldo.h +++ b/src/lua/ldo.h @@ -59,6 +59,7 @@ LUAI_FUNC void luaD_hook (lua_State *L, int event, int line, int fTransfer, int nTransfer); LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci); LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n); +LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults); 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 void luaD_tryfuncTM (lua_State *L, StkId func); diff --git a/src/lua/lfunc.c b/src/lua/lfunc.c index 88d4532..c4360f0 100644 --- a/src/lua/lfunc.c +++ b/src/lua/lfunc.c @@ -53,7 +53,7 @@ void luaF_initupvals (lua_State *L, LClosure *cl) { uv->v = &uv->u.value; /* make it closed */ setnilvalue(uv->v); cl->upvals[i] = uv; - luaC_objbarrier(L, cl, o); + luaC_objbarrier(L, cl, uv); } } diff --git a/src/lua/lgc.c b/src/lua/lgc.c index 4a7bcae..5dba56f 100644 --- a/src/lua/lgc.c +++ b/src/lua/lgc.c @@ -161,18 +161,17 @@ static void linkgclist_ (GCObject *o, GCObject **pnext, GCObject **list) { /* -** Clear keys for empty entries in tables. If entry is empty -** and its key is not marked, mark its entry as dead. This allows the -** collection of the key, but keeps its entry in the table (its removal -** could break a chain). The main feature of a dead key is that it must -** be different from any other value, to do not disturb searches. -** Other places never manipulate dead keys, because its associated empty -** value is enough to signal that the entry is logically empty. +** Clear keys for empty entries in tables. If entry is empty, mark its +** entry as dead. This allows the collection of the key, but keeps its +** entry in the table: its removal could break a chain and could break +** a table traversal. Other places never manipulate dead keys, because +** its associated empty value is enough to signal that the entry is +** logically empty. */ static void clearkey (Node *n) { lua_assert(isempty(gval(n))); - if (keyiswhite(n)) - setdeadkey(n); /* unused and unmarked key; remove it */ + if (keyiscollectable(n)) + setdeadkey(n); /* unused key; remove it */ } @@ -301,7 +300,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { if (upisopen(uv)) set2gray(uv); /* open upvalues are kept gray */ else - set2black(o); /* closed upvalues are visited here */ + set2black(uv); /* closed upvalues are visited here */ markvalue(g, uv->v); /* mark its content */ break; } @@ -309,7 +308,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { Udata *u = gco2u(o); if (u->nuvalue == 0) { /* no user values? */ markobjectN(g, u->metatable); /* mark its metatable */ - set2black(o); /* nothing else to mark */ + set2black(u); /* nothing else to mark */ break; } /* else... */ @@ -633,8 +632,7 @@ static int traversethread (global_State *g, lua_State *th) { for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) markobject(g, uv); /* open upvalues cannot be collected */ if (g->gcstate == GCSatomic) { /* final traversal? */ - StkId lim = th->stack + th->stacksize; /* real end of stack */ - for (; o < lim; o++) /* clear not-marked stack slice */ + for (; o < th->stack_last; o++) /* clear not-marked stack slice */ setnilvalue(s2v(o)); /* 'remarkupvals' may have removed thread from 'twups' list */ if (!isintwups(th) && th->openupval != NULL) { @@ -644,7 +642,7 @@ static int traversethread (global_State *g, lua_State *th) { } else if (!g->gcemergency) luaD_shrinkstack(th); /* do not change stack in emergency cycle */ - return 1 + th->stacksize; + return 1 + stacksize(th); } @@ -771,12 +769,16 @@ static void freeobj (lua_State *L, GCObject *o) { case LUA_VUPVAL: freeupval(L, gco2upv(o)); break; - case LUA_VLCL: - luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); + case LUA_VLCL: { + LClosure *cl = gco2lcl(o); + luaM_freemem(L, cl, sizeLclosure(cl->nupvalues)); break; - case LUA_VCCL: - luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); + } + case LUA_VCCL: { + CClosure *cl = gco2ccl(o); + luaM_freemem(L, cl, sizeCclosure(cl->nupvalues)); break; + } case LUA_VTABLE: luaH_free(L, gco2t(o)); break; @@ -788,13 +790,17 @@ static void freeobj (lua_State *L, GCObject *o) { luaM_freemem(L, o, sizeudata(u->nuvalue, u->len)); break; } - case LUA_VSHRSTR: - luaS_remove(L, gco2ts(o)); /* remove it from hash table */ - luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); + case LUA_VSHRSTR: { + TString *ts = gco2ts(o); + luaS_remove(L, ts); /* remove it from hash table */ + luaM_freemem(L, ts, sizelstring(ts->shrlen)); break; - case LUA_VLNGSTR: - luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); + } + case LUA_VLNGSTR: { + TString *ts = gco2ts(o); + luaM_freemem(L, ts, sizelstring(ts->u.lnglen)); break; + } default: lua_assert(0); } } diff --git a/src/lua/llex.c b/src/lua/llex.c index 90a7951..3d6b2b9 100644 --- a/src/lua/llex.c +++ b/src/lua/llex.c @@ -81,7 +81,6 @@ void luaX_init (lua_State *L) { const char *luaX_token2str (LexState *ls, int token) { if (token < FIRST_RESERVED) { /* single-byte symbols? */ - lua_assert(token == cast_uchar(token)); if (lisprint(token)) return luaO_pushfstring(ls->L, "'%c'", token); else /* control character */ diff --git a/src/lua/llex.h b/src/lua/llex.h index d1a4cba..389d2f8 100644 --- a/src/lua/llex.h +++ b/src/lua/llex.h @@ -7,11 +7,17 @@ #ifndef llex_h #define llex_h +#include + #include "lobject.h" #include "lzio.h" -#define FIRST_RESERVED 257 +/* +** Single-char tokens (terminal symbols) are represented by their own +** numeric code. Other tokens start at the following value. +*/ +#define FIRST_RESERVED (UCHAR_MAX + 1) #if !defined(LUA_ENV) diff --git a/src/lua/llimits.h b/src/lua/llimits.h index 48c97f9..a76c13e 100644 --- a/src/lua/llimits.h +++ b/src/lua/llimits.h @@ -234,6 +234,17 @@ typedef l_uint32 Instruction; #endif +/* +** Maximum depth for nested C calls, syntactical nested non-terminals, +** and other features implemented through recursion in C. (Value must +** fit in a 16-bit unsigned integer. It must also be compatible with +** the size of the C stack.) +*/ +#if !defined(LUAI_MAXCCALLS) +#define LUAI_MAXCCALLS 200 +#endif + + /* ** macros that are executed whenever program enters the Lua core ** ('lua_lock') and leaves the core ('lua_unlock') @@ -344,7 +355,7 @@ typedef l_uint32 Instruction; #else /* realloc stack keeping its size */ #define condmovestack(L,pre,pos) \ - { int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_, 0); pos; } + { int sz_ = stacksize(L); pre; luaD_reallocstack((L), sz_, 0); pos; } #endif #if !defined(HARDMEMTESTS) diff --git a/src/lua/lobject.h b/src/lua/lobject.h index a9d4578..1cc8e75 100644 --- a/src/lua/lobject.h +++ b/src/lua/lobject.h @@ -21,10 +21,12 @@ */ #define LUA_TUPVAL LUA_NUMTYPES /* upvalues */ #define LUA_TPROTO (LUA_NUMTYPES+1) /* function prototypes */ +#define LUA_TDEADKEY (LUA_NUMTYPES+2) /* removed keys in tables */ + /* -** number of all possible types (including LUA_TNONE) +** number of all possible types (including LUA_TNONE but excluding DEADKEY) */ #define LUA_TOTALTYPES (LUA_TPROTO + 2) @@ -555,7 +557,7 @@ typedef struct Proto { /* ** {================================================================== -** Closures +** Functions ** =================================================================== */ @@ -743,13 +745,13 @@ typedef struct Table { /* -** Use a "nil table" to mark dead keys in a table. Those keys serve -** to keep space for removed entries, which may still be part of -** chains. Note that the 'keytt' does not have the BIT_ISCOLLECTABLE -** set, so these values are considered not collectable and are different -** from any valid value. +** Dead keys in tables have the tag DEADKEY but keep their original +** gcvalue. This distinguishes them from regular keys but allows them to +** be found when searched in a special way. ('next' needs that to find +** keys removed from a table during a traversal.) */ -#define setdeadkey(n) (keytt(n) = LUA_TTABLE, gckey(n) = NULL) +#define setdeadkey(node) (keytt(node) = LUA_TDEADKEY) +#define keyisdead(node) (keytt(node) == LUA_TDEADKEY) /* }================================================================== */ diff --git a/src/lua/lopcodes.h b/src/lua/lopcodes.h index 122e5d2..120cdd9 100644 --- a/src/lua/lopcodes.h +++ b/src/lua/lopcodes.h @@ -261,7 +261,7 @@ OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */ OP_UNM,/* A B R[A] := -R[B] */ OP_BNOT,/* A B R[A] := ~R[B] */ OP_NOT,/* A B R[A] := not R[B] */ -OP_LEN,/* A B R[A] := length of R[B] */ +OP_LEN,/* A B R[A] := #R[B] (length operator) */ OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */ @@ -297,7 +297,7 @@ OP_TFORPREP,/* A Bx create upvalue for R[A + 3]; pc+=Bx */ OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */ OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */ -OP_SETLIST,/* A B C k R[A][(C-1)*FPF+i] := R[A+i], 1 <= i <= B */ +OP_SETLIST,/* A B C k R[A][C+i] := R[A+i], 1 <= i <= B */ OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */ diff --git a/src/lua/lparser.c b/src/lua/lparser.c index bc7d9a4..bcdcfb6 100644 --- a/src/lua/lparser.c +++ b/src/lua/lparser.c @@ -489,12 +489,10 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { } -/* -** Macros to limit the maximum recursion depth while parsing -*/ -#define enterlevel(ls) luaE_enterCcall((ls)->L) +#define enterlevel(ls) luaE_incCstack(ls->L) + -#define leavelevel(ls) luaE_exitCcall((ls)->L) +#define leavelevel(ls) ((ls)->L->nCcalls--) /* diff --git a/src/lua/lstate.c b/src/lua/lstate.c index 86b3761..4227429 100644 --- a/src/lua/lstate.c +++ b/src/lua/lstate.c @@ -76,7 +76,7 @@ static unsigned int luai_makeseed (lua_State *L) { addbuff(buff, p, &h); /* local variable */ addbuff(buff, p, &lua_newstate); /* public function */ lua_assert(p == sizeof(buff)); - return luaS_hash(buff, p, h, 1); + return luaS_hash(buff, p, h); } #endif @@ -97,66 +97,14 @@ void luaE_setdebt (global_State *g, l_mem debt) { LUA_API int lua_setcstacklimit (lua_State *L, unsigned int limit) { - global_State *g = G(L); - int ccalls; - luaE_freeCI(L); /* release unused CIs */ - ccalls = getCcalls(L); - if (limit >= 40000) - return 0; /* out of bounds */ - limit += CSTACKERR; - if (L != g-> mainthread) - return 0; /* only main thread can change the C stack */ - else if (ccalls <= CSTACKERR) - return 0; /* handling overflow */ - else { - int diff = limit - g->Cstacklimit; - if (ccalls + diff <= CSTACKERR) - return 0; /* new limit would cause an overflow */ - g->Cstacklimit = limit; /* set new limit */ - L->nCcalls += diff; /* correct 'nCcalls' */ - return limit - diff - CSTACKERR; /* success; return previous limit */ - } -} - - -/* -** Decrement count of "C calls" and check for overflows. In case of -** a stack overflow, check appropriate error ("regular" overflow or -** overflow while handling stack overflow). If 'nCcalls' is smaller -** than CSTACKERR but larger than CSTACKMARK, it means it has just -** entered the "overflow zone", so the function raises an overflow -** error. If 'nCcalls' is smaller than CSTACKMARK (which means it is -** already handling an overflow) but larger than CSTACKERRMARK, does -** not report an error (to allow message handling to work). Otherwise, -** report a stack overflow while handling a stack overflow (probably -** caused by a repeating error in the message handling function). -*/ - -void luaE_enterCcall (lua_State *L) { - int ncalls = getCcalls(L); - L->nCcalls--; - if (ncalls <= CSTACKERR) { /* possible overflow? */ - luaE_freeCI(L); /* release unused CIs */ - ncalls = getCcalls(L); /* update call count */ - if (ncalls <= CSTACKERR) { /* still overflow? */ - if (ncalls <= CSTACKERRMARK) /* below error-handling zone? */ - luaD_throw(L, LUA_ERRERR); /* error while handling stack error */ - else if (ncalls >= CSTACKMARK) { - /* not in error-handling zone; raise the error now */ - L->nCcalls = (CSTACKMARK - 1); /* enter error-handling zone */ - luaG_runerror(L, "C stack overflow"); - } - /* else stack is in the error-handling zone; - allow message handler to work */ - } - } + UNUSED(L); UNUSED(limit); + return LUAI_MAXCCALLS; /* warning?? */ } CallInfo *luaE_extendCI (lua_State *L) { CallInfo *ci; lua_assert(L->ci->next == NULL); - luaE_enterCcall(L); ci = luaM_new(L, CallInfo); lua_assert(L->ci->next == NULL); L->ci->next = ci; @@ -175,13 +123,11 @@ void luaE_freeCI (lua_State *L) { CallInfo *ci = L->ci; CallInfo *next = ci->next; ci->next = NULL; - L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */ while ((ci = next) != NULL) { next = ci->next; luaM_free(L, ci); L->nci--; } - L->nCcalls -= L->nci; /* adjust result */ } @@ -194,7 +140,6 @@ void luaE_shrinkCI (lua_State *L) { CallInfo *next; if (ci == NULL) return; /* no extra elements */ - L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */ while ((next = ci->next) != NULL) { /* two extra elements? */ CallInfo *next2 = next->next; /* next's next */ ci->next = next2; /* remove next from the list */ @@ -207,19 +152,39 @@ void luaE_shrinkCI (lua_State *L) { ci = next2; /* continue */ } } - L->nCcalls -= L->nci; /* adjust result */ +} + + +/* +** Called when 'getCcalls(L)' larger or equal to LUAI_MAXCCALLS. +** If equal, raises an overflow error. If value is larger than +** LUAI_MAXCCALLS (which means it is handling an overflow) but +** not much larger, does not report an error (to allow overflow +** handling to work). +*/ +void luaE_checkcstack (lua_State *L) { + if (getCcalls(L) == LUAI_MAXCCALLS) + luaG_runerror(L, "C stack overflow"); + else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11)) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ +} + + +LUAI_FUNC void luaE_incCstack (lua_State *L) { + L->nCcalls++; + if (unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) + luaE_checkcstack(L); } static void stack_init (lua_State *L1, lua_State *L) { int i; CallInfo *ci; /* initialize stack array */ - L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, StackValue); - L1->stacksize = BASIC_STACK_SIZE; + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); for (i = 0; i < BASIC_STACK_SIZE; i++) setnilvalue(s2v(L1->stack + i)); /* erase new stack */ L1->top = L1->stack; - L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; + L1->stack_last = L1->stack + BASIC_STACK_SIZE; /* initialize first ci */ ci = &L1->base_ci; ci->next = ci->previous = NULL; @@ -240,7 +205,7 @@ static void freestack (lua_State *L) { 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 */ + luaM_freearray(L, L->stack, stacksize(L) + EXTRA_STACK); /* free stack */ } @@ -290,7 +255,6 @@ static void preinit_thread (lua_State *L, global_State *g) { L->stack = NULL; L->ci = NULL; L->nci = 0; - L->stacksize = 0; L->twups = L; /* thread has no upvalues */ L->errorJmp = NULL; L->hook = NULL; @@ -335,7 +299,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) { setthvalue2s(L, L->top, L1); api_incr_top(L); preinit_thread(L1, g); - L1->nCcalls = getCcalls(L); + L1->nCcalls = 0; L1->hookmask = L->hookmask; L1->basehookcount = L->basehookcount; L1->hook = L->hook; @@ -396,7 +360,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { preinit_thread(L, g); g->allgc = obj2gco(L); /* by now, only object is the main thread */ L->next = NULL; - g->Cstacklimit = L->nCcalls = LUAI_MAXCSTACK + CSTACKERR; + L->nCcalls = 0; incnny(L); /* main thread is always non yieldable */ g->frealloc = f; g->ud = ud; diff --git a/src/lua/lstate.h b/src/lua/lstate.h index 1b6bcdf..cbcf07e 100644 --- a/src/lua/lstate.h +++ b/src/lua/lstate.h @@ -87,48 +87,12 @@ /* -** About 'nCcalls': each thread in Lua (a lua_State) keeps a count of -** how many "C calls" it still can do in the C stack, to avoid C-stack -** overflow. This count is very rough approximation; it considers only -** recursive functions inside the interpreter, as non-recursive calls -** can be considered using a fixed (although unknown) amount of stack -** space. -** -** The count has two parts: the lower part is the count itself; the -** higher part counts the number of non-yieldable calls in the stack. -** (They are together so that we can change both with one instruction.) -** -** Because calls to external C functions can use an unknown amount -** of space (e.g., functions using an auxiliary buffer), calls -** to these functions add more than one to the count (see CSTACKCF). -** -** The proper count excludes the number of CallInfo structures allocated -** by Lua, as a kind of "potential" calls. So, when Lua calls a function -** (and "consumes" one CallInfo), it needs neither to decrement nor to -** check 'nCcalls', as its use of C stack is already accounted for. -*/ - -/* number of "C stack slots" used by an external C function */ -#define CSTACKCF 10 - - -/* -** The C-stack size is sliced in the following zones: -** - larger than CSTACKERR: normal stack; -** - [CSTACKMARK, CSTACKERR]: buffer zone to signal a stack overflow; -** - [CSTACKCF, CSTACKERRMARK]: error-handling zone; -** - below CSTACKERRMARK: buffer zone to signal overflow during overflow; -** (Because the counter can be decremented CSTACKCF at once, we need -** the so called "buffer zones", with at least that size, to properly -** detect a change from one zone to the next.) +** About 'nCcalls': This count has two parts: the lower 16 bits counts +** the number of recursive invocations in the C stack; the higher +** 16 bits counts the number of non-yieldable calls in the stack. +** (They are together so that we can change and save both with one +** instruction.) */ -#define CSTACKERR (8 * CSTACKCF) -#define CSTACKMARK (CSTACKERR - (CSTACKCF + 2)) -#define CSTACKERRMARK (CSTACKCF + 2) - - -/* initial limit for the C-stack of threads */ -#define CSTACKTHREAD (2 * CSTACKERR) /* true if this thread does not have non-yieldable calls in the stack */ @@ -144,13 +108,8 @@ /* Decrement the number of non-yieldable calls */ #define decnny(L) ((L)->nCcalls -= 0x10000) -/* Increment the number of non-yieldable calls and decrement nCcalls */ -#define incXCcalls(L) ((L)->nCcalls += 0x10000 - CSTACKCF) - -/* Decrement the number of non-yieldable calls and increment nCcalls */ -#define decXCcalls(L) ((L)->nCcalls -= 0x10000 - CSTACKCF) - - +/* Non-yieldable call increment */ +#define nyci (0x10000 | 1) @@ -168,12 +127,20 @@ struct lua_longjmp; /* defined in ldo.c */ #endif -/* extra stack space to handle TM calls and some other extras */ +/* +** Extra stack space to handle TM calls and some other extras. This +** space is not included in 'stack_last'. It is used only to avoid stack +** checks, either because the element will be promptly popped or because +** there will be a stack check soon after the push. Function frames +** never use this extra space, so it does not need to be kept clean. +*/ #define EXTRA_STACK 5 #define BASIC_STACK_SIZE (2*LUA_MINSTACK) +#define stacksize(th) cast_int((th)->stack_last - (th)->stack) + /* kinds of Garbage Collection */ #define KGC_INC 0 /* incremental gc */ @@ -224,14 +191,15 @@ typedef struct CallInfo { */ #define CIST_OAH (1<<0) /* original value of 'allowhook' */ #define CIST_C (1<<1) /* call is running a C function */ -#define CIST_HOOKED (1<<2) /* call is running a debug hook */ -#define CIST_YPCALL (1<<3) /* call is a yieldable protected call */ -#define CIST_TAIL (1<<4) /* call was tail called */ -#define CIST_HOOKYIELD (1<<5) /* last hook called yielded */ -#define CIST_FIN (1<<6) /* call is running a finalizer */ -#define CIST_TRAN (1<<7) /* 'ci' has transfer information */ +#define CIST_FRESH (1<<2) /* call is on a fresh "luaV_execute" frame */ +#define CIST_HOOKED (1<<3) /* call is running a debug hook */ +#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 */ +#define CIST_FIN (1<<7) /* call is running a finalizer */ +#define CIST_TRAN (1<<8) /* 'ci' has transfer information */ #if defined(LUA_COMPAT_LT_LE) -#define CIST_LEQ (1<<8) /* using __lt for __le */ +#define CIST_LEQ (1<<9) /* using __lt for __le */ #endif /* active function is a Lua function */ @@ -296,7 +264,6 @@ typedef struct global_State { TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ lua_WarnFunction warnf; /* warning function */ void *ud_warn; /* auxiliary data to 'warnf' */ - unsigned int Cstacklimit; /* current limit for the C stack */ } global_State; @@ -311,7 +278,7 @@ struct lua_State { StkId top; /* first free slot in the stack */ global_State *l_G; CallInfo *ci; /* call info for current function */ - StkId stack_last; /* last free slot in the stack */ + StkId stack_last; /* end of stack (last element + 1) */ StkId stack; /* stack base */ UpVal *openupval; /* list of open upvalues in this stack */ GCObject *gclist; @@ -320,9 +287,8 @@ struct lua_State { CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ volatile lua_Hook hook; ptrdiff_t errfunc; /* current error handling function (stack index) */ - l_uint32 nCcalls; /* number of allowed nested C calls - 'nci' */ + l_uint32 nCcalls; /* number of nested (non-yieldable | C) calls */ int oldpc; /* last pc traced */ - int stacksize; int basehookcount; int hookcount; volatile l_signalT hookmask; @@ -334,6 +300,12 @@ struct lua_State { /* ** Union of all collectable objects (only for conversions) +** ISO C99, 6.5.2.3 p.5: +** "if a union contains several structures that share a common initial +** sequence [...], and if the union object currently contains one +** of these structures, it is permitted to inspect the common initial +** part of any of them anywhere that a declaration of the complete type +** of the union is visible." */ union GCUnion { GCObject gc; /* common header */ @@ -347,6 +319,11 @@ union GCUnion { }; +/* +** ISO C99, 6.7.2.1 p.14: +** "A pointer to a union object, suitably converted, points to each of +** its members [...], and vice versa." +*/ #define cast_u(o) cast(union GCUnion *, (o)) /* macros to convert a GCObject into a specific value */ @@ -378,12 +355,11 @@ LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); LUAI_FUNC void luaE_freeCI (lua_State *L); LUAI_FUNC void luaE_shrinkCI (lua_State *L); -LUAI_FUNC void luaE_enterCcall (lua_State *L); +LUAI_FUNC void luaE_checkcstack (lua_State *L); +LUAI_FUNC void luaE_incCstack (lua_State *L); LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont); LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where); -#define luaE_exitCcall(L) ((L)->nCcalls++) - #endif diff --git a/src/lua/lstring.c b/src/lua/lstring.c index 6f15747..138871c 100644 --- a/src/lua/lstring.c +++ b/src/lua/lstring.c @@ -22,16 +22,6 @@ #include "lstring.h" -/* -** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a long string to -** compute its hash -*/ -#if !defined(LUAI_HASHLIMIT) -#define LUAI_HASHLIMIT 5 -#endif - - - /* ** Maximum size for string table. */ @@ -50,10 +40,9 @@ int luaS_eqlngstr (TString *a, TString *b) { } -unsigned int luaS_hash (const char *str, size_t l, unsigned int seed, - size_t step) { +unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { unsigned int h = seed ^ cast_uint(l); - for (; l >= step; l -= step) + for (; l > 0; l--) h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1])); return h; } @@ -63,8 +52,7 @@ unsigned int luaS_hashlongstr (TString *ts) { lua_assert(ts->tt == LUA_VLNGSTR); if (ts->extra == 0) { /* no hash? */ size_t len = ts->u.lnglen; - size_t step = (len >> LUAI_HASHLIMIT) + 1; - ts->hash = luaS_hash(getstr(ts), len, ts->hash, step); + ts->hash = luaS_hash(getstr(ts), len, ts->hash); ts->extra = 1; /* now it has its hash */ } return ts->hash; @@ -201,7 +189,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { TString *ts; global_State *g = G(L); stringtable *tb = &g->strt; - unsigned int h = luaS_hash(str, l, g->seed, 1); + unsigned int h = luaS_hash(str, l, g->seed); TString **list = &tb->hash[lmod(h, tb->size)]; lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */ for (ts = *list; ts != NULL; ts = ts->u.hnext) { diff --git a/src/lua/lstring.h b/src/lua/lstring.h index a413a9d..450c239 100644 --- a/src/lua/lstring.h +++ b/src/lua/lstring.h @@ -41,8 +41,7 @@ #define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b)) -LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, - unsigned int seed, size_t step); +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); diff --git a/src/lua/lstrlib.c b/src/lua/lstrlib.c index 2ba8bde..940a14c 100644 --- a/src/lua/lstrlib.c +++ b/src/lua/lstrlib.c @@ -1365,7 +1365,6 @@ typedef union Ftypes { float f; double d; lua_Number n; - char buff[5 * sizeof(lua_Number)]; /* enough for any float type */ } Ftypes; @@ -1535,12 +1534,10 @@ static void packint (luaL_Buffer *b, lua_Unsigned n, ** Copy 'size' bytes from 'src' to 'dest', correcting endianness if ** given 'islittle' is different from native endianness. */ -static void copywithendian (volatile char *dest, volatile const char *src, +static void copywithendian (char *dest, const char *src, int size, int islittle) { - if (islittle == nativeendian.little) { - while (size-- != 0) - *(dest++) = *(src++); - } + if (islittle == nativeendian.little) + memcpy(dest, src, size); else { dest += size - 1; while (size-- != 0) @@ -1584,14 +1581,14 @@ static int str_pack (lua_State *L) { break; } case Kfloat: { /* floating-point options */ - volatile Ftypes u; + Ftypes u; char *buff = luaL_prepbuffsize(&b, size); lua_Number n = luaL_checknumber(L, arg); /* get argument */ if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ else if (size == sizeof(u.d)) u.d = (double)n; else u.n = n; /* move 'u' to final result, correcting endianness if needed */ - copywithendian(buff, u.buff, size, h.islittle); + copywithendian(buff, (char *)&u, size, h.islittle); luaL_addsize(&b, size); break; } @@ -1717,9 +1714,9 @@ static int str_unpack (lua_State *L) { break; } case Kfloat: { - volatile Ftypes u; + Ftypes u; lua_Number num; - copywithendian(u.buff, data + pos, size, h.islittle); + copywithendian((char *)&u, data + pos, size, h.islittle); if (size == sizeof(u.f)) num = (lua_Number)u.f; else if (size == sizeof(u.d)) num = (lua_Number)u.d; else num = u.n; @@ -1738,7 +1735,7 @@ static int str_unpack (lua_State *L) { break; } case Kzstr: { - size_t len = (int)strlen(data + pos); + size_t len = strlen(data + pos); luaL_argcheck(L, pos + len < ld, 2, "unfinished string for format 'z'"); lua_pushlstring(L, data + pos, len); diff --git a/src/lua/ltable.c b/src/lua/ltable.c index 5a0d066..38bee1d 100644 --- a/src/lua/ltable.c +++ b/src/lua/ltable.c @@ -172,11 +172,17 @@ static Node *mainpositionTV (const Table *t, const TValue *key) { ** be equal to floats. It is assumed that 'eqshrstr' is simply ** pointer equality, so that short strings are handled in the ** default case. -*/ -static int equalkey (const TValue *k1, const Node *n2) { - if (rawtt(k1) != keytt(n2)) /* not the same variants? */ +** A true 'deadok' means to accept dead keys as equal to their original +** values, which can only happen if the original key was collectable. +** All dead values are compared in the default case, by pointer +** identity. (Note that dead long strings are also compared by +** identity). +*/ +static int equalkey (const TValue *k1, const Node *n2, int deadok) { + if ((rawtt(k1) != keytt(n2)) && /* not the same variants? */ + !(deadok && keyisdead(n2) && iscollectable(k1))) return 0; /* cannot be same key */ - switch (ttypetag(k1)) { + switch (keytt(n2)) { case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: return 1; case LUA_VNUMINT: @@ -187,7 +193,7 @@ static int equalkey (const TValue *k1, const Node *n2) { return pvalue(k1) == pvalueraw(keyval(n2)); case LUA_VLCF: return fvalue(k1) == fvalueraw(keyval(n2)); - case LUA_VLNGSTR: + case ctb(LUA_VLNGSTR): return luaS_eqlngstr(tsvalue(k1), keystrval(n2)); default: return gcvalue(k1) == gcvalueraw(keyval(n2)); @@ -251,11 +257,12 @@ static unsigned int setlimittosize (Table *t) { /* ** "Generic" get version. (Not that generic: not valid for integers, ** which may be in array part, nor for floats with integral values.) +** See explanation about 'deadok' in function 'equalkey'. */ -static const TValue *getgeneric (Table *t, const TValue *key) { +static const TValue *getgeneric (Table *t, const TValue *key, int deadok) { Node *n = mainpositionTV(t, key); for (;;) { /* check whether 'key' is somewhere in the chain */ - if (equalkey(key, n)) + if (equalkey(key, n, deadok)) return gval(n); /* that's it */ else { int nx = gnext(n); @@ -292,7 +299,7 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key, if (i - 1u < asize) /* is 'key' inside array part? */ return i; /* yes; that's the index */ else { - const TValue *n = getgeneric(t, key); + const TValue *n = getgeneric(t, key, 1); if (unlikely(isabstkey(n))) luaG_runerror(L, "invalid key to 'next'"); /* key not found */ i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */ @@ -730,7 +737,7 @@ const TValue *luaH_getstr (Table *t, TString *key) { else { /* for long strings, use generic case */ TValue ko; setsvalue(cast(lua_State *, NULL), &ko, key); - return getgeneric(t, &ko); + return getgeneric(t, &ko, 0); } } @@ -750,7 +757,7 @@ const TValue *luaH_get (Table *t, const TValue *key) { /* else... */ } /* FALLTHROUGH */ default: - return getgeneric(t, key); + return getgeneric(t, key, 0); } } diff --git a/src/lua/lua.h b/src/lua/lua.h index b348c14..c9d64d7 100644 --- a/src/lua/lua.h +++ b/src/lua/lua.h @@ -18,7 +18,7 @@ #define LUA_VERSION_MAJOR "5" #define LUA_VERSION_MINOR "4" -#define LUA_VERSION_RELEASE "0" +#define LUA_VERSION_RELEASE "2" #define LUA_VERSION_NUM 504 #define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 0) diff --git a/src/lua/luaconf.h b/src/lua/luaconf.h index bdf927e..d9cf18c 100644 --- a/src/lua/luaconf.h +++ b/src/lua/luaconf.h @@ -36,21 +36,6 @@ ** ===================================================================== */ -/* -@@ LUAI_MAXCSTACK defines the maximum depth for nested calls and -** also limits the maximum depth of other recursive algorithms in -** the implementation, such as syntactic analysis. A value too -** large may allow the interpreter to crash (C-stack overflow). -** The default value seems ok for regular machines, but may be -** too high for restricted hardware. -** The test file 'cstack.lua' may help finding a good limit. -** (It will crash with a limit too high.) -*/ -#if !defined(LUAI_MAXCSTACK) -#define LUAI_MAXCSTACK 2000 -#endif - - /* @@ LUA_USE_C89 controls the use of non-ISO-C89 features. ** Define it if you want Lua to avoid the use of a few C99 features diff --git a/src/lua/lvm.c b/src/lua/lvm.c index 08681af..aa3b22b 100644 --- a/src/lua/lvm.c +++ b/src/lua/lvm.c @@ -229,7 +229,7 @@ static int forprep (lua_State *L, StkId ra) { count /= l_castS2U(-(step + 1)) + 1u; } /* store the counter in place of the limit (which won't be - needed anymore */ + needed anymore) */ setivalue(plimit, l_castU2S(count)); } } @@ -1092,15 +1092,11 @@ void luaV_finishOp (lua_State *L) { #define ProtectNT(exp) (savepc(L), (exp), updatetrap(ci)) /* -** Protect code that will finish the loop (returns) or can only raise -** errors. (That is, it will not return to the interpreter main loop -** after changing the stack or hooks.) +** Protect code that can only raise errors. (That is, it cannnot change +** the stack or hooks.) */ #define halfProtect(exp) (savestate(L,ci), (exp)) -/* idem, but without changing the stack */ -#define halfProtectNT(exp) (savepc(L), (exp)) - /* 'c' is the limit of live values in the stack */ #define checkGC(L,c) \ { luaC_condGC(L, (savepc(L), L->top = (c)), \ @@ -1132,17 +1128,20 @@ void luaV_execute (lua_State *L, CallInfo *ci) { #if LUA_USE_JUMPTABLE #include "ljumptab.h" #endif - tailcall: + startfunc: trap = L->hookmask; + returning: /* trap already set */ cl = clLvalue(s2v(ci->func)); k = cl->p->k; pc = ci->u.l.savedpc; if (trap) { - if (cl->p->is_vararg) - trap = 0; /* hooks will start after VARARGPREP instruction */ - else if (pc == cl->p->code) /* first instruction (not resuming)? */ - luaD_hookcall(L, ci); - ci->u.l.trap = 1; /* there may be other hooks */ + if (pc == cl->p->code) { /* first instruction (not resuming)? */ + if (cl->p->is_vararg) + trap = 0; /* hooks will start after VARARGPREP instruction */ + else /* check 'call' hook */ + luaD_hookcall(L, ci); + } + ci->u.l.trap = 1; /* assume trap is on, for now */ } base = ci->func + 1; /* main loop of interpreter */ @@ -1151,7 +1150,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { StkId ra; /* instruction's A register */ vmfetch(); lua_assert(base == ci->func + 1); - lua_assert(base <= L->top && L->top < L->stack + L->stacksize); + lua_assert(base <= L->top && L->top < L->stack_last); /* invalidate top for instructions not expecting it */ lua_assert(isIT(i) || (cast_void(L->top = base), 1)); vmdispatch (GET_OPCODE(i)) { @@ -1606,24 +1605,32 @@ void luaV_execute (lua_State *L, CallInfo *ci) { vmbreak; } vmcase(OP_CALL) { + CallInfo *newci; int b = GETARG_B(i); int nresults = GETARG_C(i) - 1; if (b != 0) /* fixed number of arguments? */ L->top = ra + b; /* top signals number of arguments */ /* else previous instruction set top */ - ProtectNT(luaD_call(L, ra, nresults)); + savepc(L); /* in case of errors */ + if ((newci = luaD_precall(L, ra, nresults)) == NULL) + updatetrap(ci); /* C call; nothing else to be done */ + else { /* Lua call: run function in this same C frame */ + ci = newci; + ci->callstatus = 0; /* call re-uses 'luaV_execute' */ + goto startfunc; + } vmbreak; } vmcase(OP_TAILCALL) { int b = GETARG_B(i); /* number of arguments + 1 (function) */ int nparams1 = GETARG_C(i); - /* delat is virtual 'func' - real 'func' (vararg functions) */ + /* delta is virtual 'func' - real 'func' (vararg functions) */ int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0; if (b != 0) L->top = ra + b; else /* previous instruction set top */ b = cast_int(L->top - ra); - savepc(ci); /* some calls here can raise errors */ + savepc(ci); /* several calls here can raise errors */ if (TESTARG_k(i)) { /* close upvalues from current call; the compiler ensures that there are no to-be-closed variables here, so this @@ -1637,16 +1644,17 @@ void luaV_execute (lua_State *L, CallInfo *ci) { checkstackGCp(L, 1, ra); } if (!ttisLclosure(s2v(ra))) { /* C function? */ - luaD_call(L, ra, LUA_MULTRET); /* call it */ + luaD_precall(L, ra, LUA_MULTRET); /* call it */ updatetrap(ci); updatestack(ci); /* stack may have been relocated */ - ci->func -= delta; - luaD_poscall(L, ci, cast_int(L->top - ra)); - return; + ci->func -= delta; /* restore 'func' (if vararg) */ + luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */ + updatetrap(ci); /* 'luaD_poscall' can change hooks */ + goto ret; /* caller returns after the tail call */ } - ci->func -= delta; + ci->func -= delta; /* restore 'func' (if vararg) */ luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ - goto tailcall; + goto startfunc; /* execute the callee */ } vmcase(OP_RETURN) { int n = GETARG_B(i) - 1; /* number of results */ @@ -1665,12 +1673,15 @@ void luaV_execute (lua_State *L, CallInfo *ci) { ci->func -= ci->u.l.nextraargs + nparams1; L->top = ra + n; /* set call for 'luaD_poscall' */ luaD_poscall(L, ci, n); - return; + updatetrap(ci); /* 'luaD_poscall' can change hooks */ + goto ret; } vmcase(OP_RETURN0) { if (L->hookmask) { L->top = ra; - halfProtectNT(luaD_poscall(L, ci, 0)); /* no hurry... */ + savepc(ci); + luaD_poscall(L, ci, 0); /* no hurry... */ + trap = 1; } else { /* do the 'poscall' here */ int nres = ci->nresults; @@ -1679,12 +1690,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) { while (nres-- > 0) setnilvalue(s2v(L->top++)); /* all results are nil */ } - return; + goto ret; } vmcase(OP_RETURN1) { if (L->hookmask) { L->top = ra + 1; - halfProtectNT(luaD_poscall(L, ci, 1)); /* no hurry... */ + savepc(ci); + luaD_poscall(L, ci, 1); /* no hurry... */ + trap = 1; } else { /* do the 'poscall' here */ int nres = ci->nresults; @@ -1698,7 +1711,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) { setnilvalue(s2v(L->top++)); } } - return; + ret: /* return from a Lua function */ + if (ci->callstatus & CIST_FRESH) + return; /* end this frame */ + else { + ci = ci->previous; + goto returning; /* continue running caller in this frame */ + } } vmcase(OP_FORLOOP) { if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ diff --git a/src/lua/makefile b/src/lua/makefile index c4b0064..bf09f24 100644 --- a/src/lua/makefile +++ b/src/lua/makefile @@ -6,7 +6,6 @@ # Warnings valid for both C and C++ CWARNSCPP= \ - -fmax-errors=5 \ -Wextra \ -Wshadow \ -Wsign-compare \ @@ -15,8 +14,6 @@ CWARNSCPP= \ -Wredundant-decls \ -Wdisabled-optimization \ -Wdouble-promotion \ - -Wlogical-op \ - -Wno-aggressive-loop-optimizations \ # the next warnings might be useful sometimes, # but usually they generate too much noise # -Werror \ -- cgit v1.2.3-55-g6feb