diff --git a/3rd/lua/lcode.c b/3rd/lua/lcode.c index 6f241c94..14d41f1a 100644 --- a/3rd/lua/lcode.c +++ b/3rd/lua/lcode.c @@ -753,7 +753,7 @@ void luaK_setoneret (FuncState *fs, expdesc *e) { /* -** Ensure that expression 'e' is not a variable (nor a constant). +** Ensure that expression 'e' is not a variable (nor a ). ** (Expression still may have jump lists.) */ void luaK_dischargevars (FuncState *fs, expdesc *e) { @@ -805,8 +805,8 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { /* -** Ensures expression value is in register 'reg' (and therefore -** 'e' will become a non-relocatable expression). +** Ensure expression value is in register 'reg', making 'e' a +** non-relocatable expression. ** (Expression still may have jump lists.) */ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { @@ -860,7 +860,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { /* -** Ensures expression value is in any register. +** Ensure expression value is in a register, making 'e' a +** non-relocatable expression. ** (Expression still may have jump lists.) */ static void discharge2anyreg (FuncState *fs, expdesc *e) { @@ -946,8 +947,11 @@ int luaK_exp2anyreg (FuncState *fs, expdesc *e) { exp2reg(fs, e, e->u.info); /* put final result in it */ return e->u.info; } + /* else expression has jumps and cannot change its register + to hold the jump values, because it is a local variable. + Go through to the default case. */ } - luaK_exp2nextreg(fs, e); /* otherwise, use next available register */ + luaK_exp2nextreg(fs, e); /* default: use next available register */ return e->u.info; } diff --git a/3rd/lua/ldo.c b/3rd/lua/ldo.c index 5729b190..a60972b2 100644 --- a/3rd/lua/ldo.c +++ b/3rd/lua/ldo.c @@ -534,11 +534,11 @@ CallInfo *luaD_precall (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). +** Call a function (C or Lua) through C. '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) { +static void ccall (lua_State *L, StkId func, int nResults, int inc) { CallInfo *ci; L->nCcalls += inc; if (unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) @@ -552,10 +552,10 @@ static void docall (lua_State *L, StkId func, int nResults, int inc) { /* -** External interface for 'docall' +** External interface for 'ccall' */ void luaD_call (lua_State *L, StkId func, int nResults) { - return docall(L, func, nResults, 1); + ccall(L, func, nResults, 1); } @@ -563,7 +563,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) { ** Similar to 'luaD_call', but does not allow yields during the call. */ void luaD_callnoyield (lua_State *L, StkId func, int nResults) { - return docall(L, func, nResults, nyci); + ccall(L, func, nResults, nyci); } @@ -678,7 +678,7 @@ static void resume (lua_State *L, void *ud) { StkId firstArg = L->top - n; /* first argument */ CallInfo *ci = L->ci; if (L->status == LUA_OK) /* starting a coroutine? */ - docall(L, firstArg - 1, LUA_MULTRET, 1); /* just call its body */ + ccall(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) */ diff --git a/3rd/lua/llex.c b/3rd/lua/llex.c index 3d6b2b97..4b8dec99 100644 --- a/3rd/lua/llex.c +++ b/3rd/lua/llex.c @@ -254,9 +254,10 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) { /* -** reads a sequence '[=*[' or ']=*]', leaving the last bracket. -** If sequence is well formed, return its number of '='s + 2; otherwise, -** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...'). +** read a sequence '[=*[' or ']=*]', leaving the last bracket. If +** sequence is well formed, return its number of '='s + 2; otherwise, +** return 1 if it is a single bracket (no '='s and no 2nd bracket); +** otherwise (an unfinished '[==...') return 0. */ static size_t skip_sep (LexState *ls) { size_t count = 0; @@ -481,34 +482,34 @@ static int llex (LexState *ls, SemInfo *seminfo) { } case '=': { next(ls); - if (check_next1(ls, '=')) return TK_EQ; + if (check_next1(ls, '=')) return TK_EQ; /* '==' */ else return '='; } case '<': { next(ls); - if (check_next1(ls, '=')) return TK_LE; - else if (check_next1(ls, '<')) return TK_SHL; + if (check_next1(ls, '=')) return TK_LE; /* '<=' */ + else if (check_next1(ls, '<')) return TK_SHL; /* '<<' */ else return '<'; } case '>': { next(ls); - if (check_next1(ls, '=')) return TK_GE; - else if (check_next1(ls, '>')) return TK_SHR; + if (check_next1(ls, '=')) return TK_GE; /* '>=' */ + else if (check_next1(ls, '>')) return TK_SHR; /* '>>' */ else return '>'; } case '/': { next(ls); - if (check_next1(ls, '/')) return TK_IDIV; + if (check_next1(ls, '/')) return TK_IDIV; /* '//' */ else return '/'; } case '~': { next(ls); - if (check_next1(ls, '=')) return TK_NE; + if (check_next1(ls, '=')) return TK_NE; /* '~=' */ else return '~'; } case ':': { next(ls); - if (check_next1(ls, ':')) return TK_DBCOLON; + if (check_next1(ls, ':')) return TK_DBCOLON; /* '::' */ else return ':'; } case '"': case '\'': { /* short literal strings */ @@ -547,7 +548,7 @@ static int llex (LexState *ls, SemInfo *seminfo) { return TK_NAME; } } - else { /* single-char tokens (+ - / ...) */ + else { /* single-char tokens ('+', '*', '%', '{', '}', ...) */ int c = ls->current; next(ls); return c; diff --git a/3rd/lua/llimits.h b/3rd/lua/llimits.h index d6866d7c..a76c13ed 100644 --- a/3rd/lua/llimits.h +++ b/3rd/lua/llimits.h @@ -355,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/3rd/lua/lparser.c b/3rd/lua/lparser.c index bcdcfb6d..fb7a1264 100644 --- a/3rd/lua/lparser.c +++ b/3rd/lua/lparser.c @@ -945,7 +945,7 @@ static void setvararg (FuncState *fs, int nparams) { static void parlist (LexState *ls) { - /* parlist -> [ param { ',' param } ] */ + /* parlist -> [ {NAME ','} (NAME | '...') ] */ FuncState *fs = ls->fs; Proto *f = fs->f; int nparams = 0; @@ -953,12 +953,12 @@ static void parlist (LexState *ls) { if (ls->t.token != ')') { /* is 'parlist' not empty? */ do { switch (ls->t.token) { - case TK_NAME: { /* param -> NAME */ + case TK_NAME: { new_localvar(ls, str_checkname(ls)); nparams++; break; } - case TK_DOTS: { /* param -> '...' */ + case TK_DOTS: { luaX_next(ls); isvararg = 1; break; @@ -1752,7 +1752,7 @@ static void checktoclose (LexState *ls, int level) { static void localstat (LexState *ls) { - /* stat -> LOCAL ATTRIB NAME {',' ATTRIB NAME} ['=' explist] */ + /* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */ FuncState *fs = ls->fs; int toclose = -1; /* index of to-be-closed variable (if any) */ Vardesc *var; /* last variable */ diff --git a/3rd/lua/lparser.h b/3rd/lua/lparser.h index 618cb010..2e6dae72 100644 --- a/3rd/lua/lparser.h +++ b/3rd/lua/lparser.h @@ -23,7 +23,7 @@ /* kinds of variables/expressions */ typedef enum { - VVOID, /* when 'expdesc' describes the last expression a list, + VVOID, /* when 'expdesc' describes the last expression of a list, this kind means an empty list (so, no expression) */ VNIL, /* constant nil */ VTRUE, /* constant true */ @@ -38,7 +38,8 @@ typedef enum { VLOCAL, /* local variable; var.sidx = stack index (local register); var.vidx = relative index in 'actvar.arr' */ VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ - VCONST, /* compile-time constant; info = absolute index in 'actvar.arr' */ + VCONST, /* compile-time variable; + info = absolute index in 'actvar.arr' */ VINDEXED, /* indexed variable; ind.t = table register; ind.idx = key's R index */ diff --git a/3rd/lua/ltable.c b/3rd/lua/ltable.c index ecfd595a..b3840e77 100644 --- a/3rd/lua/ltable.c +++ b/3rd/lua/ltable.c @@ -166,17 +166,24 @@ static Node *mainpositionTV (const Table *t, const TValue *key) { /* -** Check whether key 'k1' is equal to the key in node 'n2'. -** This equality is raw, so there are no metamethods. Floats -** with integer values have been normalized, so integers cannot -** be equal to floats. It is assumed that 'eqshrstr' is simply -** pointer equality, so that short strings are handled in the -** default case. +** Check whether key 'k1' is equal to the key in node 'n2'. This +** equality is raw, so there are no metamethods. Floats with integer +** values have been normalized, so integers cannot be equal to +** floats. It is assumed that 'eqshrstr' is simply pointer equality, so +** that short strings are handled in the default case. ** 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). +** values. All dead keys are compared in the default case, by pointer +** identity. (Only collectable objects can produce dead keys.) Note that +** dead long strings are also compared by identity. +** Once a key is dead, its corresponding value may be collected, and +** then another value can be created with the same address. If this +** other value is given to 'next', 'equalkey' will signal a false +** positive. In a regular traversal, this situation should never happen, +** as all keys given to 'next' came from the table itself, and therefore +** could not have been collected. Outside a regular traversal, we +** have garbage in, garbage out. What is relevant is that this false +** positive does not break anything. (In particular, 'next' will return +** some other valid item on the table or nil.) */ static int equalkey (const TValue *k1, const Node *n2, int deadok) { if ((rawtt(k1) != keytt(n2)) && /* not the same variants? */ diff --git a/3rd/lua/lua.c b/3rd/lua/lua.c index 454ce12f..b5b884b6 100644 --- a/3rd/lua/lua.c +++ b/3rd/lua/lua.c @@ -416,14 +416,18 @@ static int handle_luainit (lua_State *L) { /* -** Returns the string to be used as a prompt by the interpreter. +** Return the string to be used as a prompt by the interpreter. Leave +** the string (or nil, if using the default value) on the stack, to keep +** it anchored. */ static const char *get_prompt (lua_State *L, int firstline) { - const char *p; - lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2"); - p = lua_tostring(L, -1); - if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); - return p; + if (lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2") == LUA_TNIL) + return (firstline ? LUA_PROMPT : LUA_PROMPT2); /* use the default */ + else { /* apply 'tostring' over the value */ + const char *p = luaL_tolstring(L, -1, NULL); + lua_remove(L, -2); /* remove original value */ + return p; + } } /* mark in error messages for incomplete statements */ diff --git a/3rd/lua/lvm.c b/3rd/lua/lvm.c index 24cc8155..e6e1033a 100644 --- a/3rd/lua/lvm.c +++ b/3rd/lua/lvm.c @@ -1094,15 +1094,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)), \ @@ -1134,17 +1130,20 @@ void luaV_execute (lua_State *L, CallInfo *ci) { #if LUA_USE_JUMPTABLE #include "ljumptab.h" #endif - execute: + 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 */ @@ -1617,10 +1616,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) { 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 invocation */ + else { /* Lua call: run function in this same C frame */ ci = newci; ci->callstatus = 0; /* call re-uses 'luaV_execute' */ - goto execute; + goto startfunc; } vmbreak; } @@ -1633,7 +1632,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { 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 @@ -1652,11 +1651,12 @@ void luaV_execute (lua_State *L, CallInfo *ci) { updatestack(ci); /* stack may have been relocated */ 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; /* restore 'func' (if vararg) */ luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ - goto execute; /* execute the callee */ + goto startfunc; /* execute the callee */ } vmcase(OP_RETURN) { int n = GETARG_B(i) - 1; /* number of results */ @@ -1675,12 +1675,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); + 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; @@ -1694,7 +1697,9 @@ void luaV_execute (lua_State *L, CallInfo *ci) { 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; @@ -1708,12 +1713,12 @@ void luaV_execute (lua_State *L, CallInfo *ci) { setnilvalue(s2v(L->top++)); } } - ret: + ret: /* return from a Lua function */ if (ci->callstatus & CIST_FRESH) return; /* end this frame */ else { ci = ci->previous; - goto execute; /* continue running caller in this frame */ + goto returning; /* continue running caller in this frame */ } } vmcase(OP_FORLOOP) {