diffu-lua-5.4.1-lua-5.4.2
Makefile
@@ -46,7 +46,7 @@
# Lua version and release.
V= 5.4
-R= $V.1
+R= $V.2
# Targets start here.
all: $(PLAT)
README
@@ -1,5 +1,5 @@
-This is Lua 5.4.1, released on 30 Sep 2020.
+This is Lua 5.4.2, released on 13 Nov 2020.
For installation instructions, license details, and
further information about Lua, see doc/readme.html.
doc/contents.html
@@ -198,7 +198,6 @@
<A HREF="manual.html#pdf-debug.getregistry">debug.getregistry</A><BR>
<A HREF="manual.html#pdf-debug.getupvalue">debug.getupvalue</A><BR>
<A HREF="manual.html#pdf-debug.getuservalue">debug.getuservalue</A><BR>
-<A HREF="manual.html#pdf-debug.setcstacklimit">debug.setcstacklimit</A><BR>
<A HREF="manual.html#pdf-debug.sethook">debug.sethook</A><BR>
<A HREF="manual.html#pdf-debug.setlocal">debug.setlocal</A><BR>
<A HREF="manual.html#pdf-debug.setmetatable">debug.setmetatable</A><BR>
@@ -476,7 +475,6 @@
<A HREF="manual.html#lua_resume">lua_resume</A><BR>
<A HREF="manual.html#lua_rotate">lua_rotate</A><BR>
<A HREF="manual.html#lua_setallocf">lua_setallocf</A><BR>
-<A HREF="manual.html#lua_setcstacklimit">lua_setcstacklimit</A><BR>
<A HREF="manual.html#lua_setfield">lua_setfield</A><BR>
<A HREF="manual.html#lua_setglobal">lua_setglobal</A><BR>
<A HREF="manual.html#lua_sethook">lua_sethook</A><BR>
@@ -665,10 +663,10 @@
<P CLASS="footer">
Last update:
-Wed Sep 30 06:45:10 -03 2020
+Tue Nov 10 20:58:52 UTC 2020
</P>
<!--
-Last change: revised for Lua 5.4.1
+Last change: revised for Lua 5.4.2
-->
</BODY>
doc/manual.html
@@ -2966,8 +2966,18 @@
you are responsible for ensuring consistency.
In particular,
<em>you are responsible for controlling stack overflow</em>.
-You can use the function <a href="#lua_checkstack"><code>lua_checkstack</code></a>
-to ensure that the stack has enough space for pushing new elements.
+When you call any API function,
+you must ensure the stack has enough room to accommodate the results.
+
+
+<p>
+There is one exception to the above rule:
+When you call a Lua function
+without a fixed number of results (see <a href="#lua_call"><code>lua_call</code></a>),
+Lua ensures that the stack has enough space for all results.
+However, it does not ensure any extra space.
+So, before pushing anything on the stack after such a call
+you should use <a href="#lua_checkstack"><code>lua_checkstack</code></a>.
<p>
@@ -2978,15 +2988,9 @@
<code>LUA_MINSTACK</code> is defined as 20,
so that usually you do not have to worry about stack space
unless your code has loops pushing elements onto the stack.
-
-
-<p>
-When you call a Lua function
-without a fixed number of results (see <a href="#lua_call"><code>lua_call</code></a>),
-Lua ensures that the stack has enough space for all results,
-but it does not ensure any extra space.
-So, before pushing anything on the stack after such a call
-you should use <a href="#lua_checkstack"><code>lua_checkstack</code></a>.
+Whenever necessary,
+you can use the function <a href="#lua_checkstack"><code>lua_checkstack</code></a>
+to ensure that the stack has enough space for pushing new elements.
@@ -3062,7 +3066,8 @@
and then invalidate pointers to internal strings.
To allow a safe use of these pointers,
The API guarantees that any pointer to a string in a stack index
-is valid while the value at that index is neither modified nor popped.
+is valid while the string value at that index is not removed from the stack.
+(It can be moved to another index, though.)
When the index is a pseudo-index (referring to an upvalue),
the pointer is valid while the corresponding call is active and
the corresponding upvalue is not modified.
@@ -3282,7 +3287,7 @@
and this API function yields
(directly or indirectly by calling another function that yields),
Lua cannot return to <code>foo</code> any more,
-because the <code>longjmp</code> removes its frame from the C stack.
+because the <code>longjmp</code> removes its frame from the C stack.
<p>
@@ -3312,7 +3317,7 @@
it eventually will finish running the callee function.
However,
the callee function cannot return to the original function,
-because its frame in the C stack was destroyed by the yield.
+because its frame in the C stack was destroyed by the yield.
Instead, Lua calls a <em>continuation function</em>,
which was given as an argument to the callee function.
As the name implies,
@@ -3451,7 +3456,7 @@
<p>
Converts the acceptable index <code>idx</code>
into an equivalent absolute index
-(that is, one that does not depend on the stack top).
+(that is, one that does not depend on the stack size).
@@ -4647,13 +4652,18 @@
<hr><h3><a name="lua_pop"><code>lua_pop</code></a></h3><p>
-<span class="apii">[-n, +0, –]</span>
+<span class="apii">[-n, +0, <em>e</em>]</span>
<pre>void lua_pop (lua_State *L, int n);</pre>
<p>
Pops <code>n</code> elements from the stack.
+<p>
+This function can run arbitrary code when removing an index
+marked as to-be-closed from the stack.
+
+
@@ -5320,7 +5330,7 @@
<hr><h3><a name="lua_settop"><code>lua_settop</code></a></h3><p>
-<span class="apii">[-?, +?, –]</span>
+<span class="apii">[-?, +?, <em>e</em>]</span>
<pre>void lua_settop (lua_State *L, int index);</pre>
<p>
@@ -5331,6 +5341,11 @@
If <code>index</code> is 0, then all stack elements are removed.
+<p>
+This function can run arbitrary code when removing an index
+marked as to-be-closed from the stack.
+
+
@@ -5479,7 +5494,7 @@
Note that, both in case of errors and of a regular return,
by the time the <code>__close</code> metamethod runs,
the C stack was already unwound,
-so that any automatic C variable declared in the calling function
+so that any automatic C variable declared in the calling function
will be out of scope.
@@ -6267,24 +6282,6 @@
-<hr><h3><a name="lua_setcstacklimit"><code>lua_setcstacklimit</code></a></h3><p>
-<span class="apii">[-0, +0, –]</span>
-<pre>int (lua_setcstacklimit) (lua_State *L, unsigned int limit);</pre>
-
-<p>
-Sets a new limit for the C stack.
-This limit controls how deeply nested calls can go in Lua,
-with the intent of avoiding a stack overflow.
-Returns the old limit in case of success,
-or zero in case of error.
-For more details about this function,
-see <a href="#pdf-debug.setcstacklimit"><code>debug.setcstacklimit</code></a>,
-its equivalent in the standard library.
-
-
-
-
-
<hr><h3><a name="lua_sethook"><code>lua_sethook</code></a></h3><p>
<span class="apii">[-0, +0, –]</span>
<pre>void lua_sethook (lua_State *L, lua_Hook f, int mask, int count);</pre>
@@ -11281,43 +11278,6 @@
<p>
-<hr><h3><a name="pdf-debug.setcstacklimit"><code>debug.setcstacklimit (limit)</code></a></h3>
-
-
-<p>
-Sets a new limit for the C stack.
-This limit controls how deeply nested calls can go in Lua,
-with the intent of avoiding a stack overflow.
-A limit too small restricts recursive calls pointlessly;
-a limit too large exposes the interpreter to stack-overflow crashes.
-Unfortunately, there is no way to know a priori
-the maximum safe limit for a platform.
-
-
-<p>
-Each call made from Lua code counts one unit.
-Other operations (e.g., calls made from C to Lua or resuming a coroutine)
-may have a higher cost.
-
-
-<p>
-This function has the following restrictions:
-
-<ul>
-<li>It can only be called from the main coroutine (thread);</li>
-<li>It cannot be called while handling a stack-overflow error;</li>
-<li><code>limit</code> must be less than 40000;</li>
-<li><code>limit</code> cannot be less than the amount of C stack in use.</li>
-</ul><p>
-If a call does not respect some restriction,
-it returns a false value.
-Otherwise,
-the call returns the old limit.
-
-
-
-
-<p>
<hr><h3><a name="pdf-debug.sethook"><code>debug.sethook ([thread,] hook, mask [, count])</code></a></h3>
@@ -11948,10 +11908,10 @@
<P CLASS="footer">
Last update:
-Wed Sep 30 09:46:30 UTC 2020
+Fri Nov 13 15:35:22 UTC 2020
</P>
<!--
-Last change: revised for Lua 5.4.1
+Last change: revised for Lua 5.4.2
-->
</body></html>
doc/readme.html
@@ -110,7 +110,7 @@
<OL>
<LI>
Open a terminal window and move to
-the top-level directory, which is named <TT>lua-5.4.1</TT>.
+the top-level directory, which is named <TT>lua-5.4.2</TT>.
The <TT>Makefile</TT> there controls both the build process and the installation process.
<P>
<LI>
@@ -330,10 +330,10 @@
<P CLASS="footer">
Last update:
-Wed Sep 30 09:55:45 UTC 2020
+Tue Nov 10 20:55:28 UTC 2020
</P>
<!--
-Last change: revised for Lua 5.4.1
+Last change: revised for Lua 5.4.2
-->
</BODY>
src/Makefile
@@ -26,7 +26,7 @@
MYOBJS=
# Special flags for compiler modules; -Os reduces code size.
-CMCFLAGS= -Os
+CMCFLAGS=
# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
src/lapi.c
@@ -1383,13 +1383,16 @@
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 @@
}
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 @@
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);
}
src/lauxlib.c
@@ -283,10 +283,10 @@
LUALIB_API int luaL_execresult (lua_State *L, int stat) {
- const char *what = "exit"; /* type of termination */
if (stat != 0 && errno != 0) /* error with an 'errno'? */
return luaL_fileresult(L, 0, NULL);
else {
+ const char *what = "exit"; /* type of termination */
l_inspectstat(stat, what); /* interpret result */
if (*what == 'e' && stat == 0) /* successful termination? */
lua_pushboolean(L, 1);
@@ -1006,43 +1006,67 @@
/*
-** Emit a warning. '*warnstate' means:
-** 0 - warning system is off;
-** 1 - ready to start a new message;
-** 2 - previous message is to be continued.
-*/
-static void warnf (void *ud, const char *message, int tocont) {
- int *warnstate = (int *)ud;
- if (*warnstate != 2 && !tocont && *message == '@') { /* control message? */
- if (strcmp(message, "@off") == 0)
- *warnstate = 0;
- else if (strcmp(message, "@on") == 0)
- *warnstate = 1;
- return;
- }
- else if (*warnstate == 0) /* warnings off? */
- return;
- if (*warnstate == 1) /* previous message was the last? */
- lua_writestringerror("%s", "Lua warning: "); /* start a new warning */
+** Warning functions:
+** warnfoff: warning system is off
+** warnfon: ready to start a new message
+** warnfcont: previous message is to be continued
+*/
+static void warnfoff (void *ud, const char *message, int tocont);
+static void warnfon (void *ud, const char *message, int tocont);
+static void warnfcont (void *ud, const char *message, int tocont);
+
+
+/*
+** Check whether message is a control message. If so, execute the
+** control or ignore it if unknown.
+*/
+static int checkcontrol (lua_State *L, const char *message, int tocont) {
+ if (tocont || *(message++) != '@') /* not a control message? */
+ return 0;
+ else {
+ if (strcmp(message, "off") == 0)
+ lua_setwarnf(L, warnfoff, L); /* turn warnings off */
+ else if (strcmp(message, "on") == 0)
+ lua_setwarnf(L, warnfon, L); /* turn warnings on */
+ return 1; /* it was a control message */
+ }
+}
+
+
+static void warnfoff (void *ud, const char *message, int tocont) {
+ checkcontrol((lua_State *)ud, message, tocont);
+}
+
+
+/*
+** Writes the message and handle 'tocont', finishing the message
+** if needed and setting the next warn function.
+*/
+static void warnfcont (void *ud, const char *message, int tocont) {
+ lua_State *L = (lua_State *)ud;
lua_writestringerror("%s", message); /* write message */
if (tocont) /* not the last part? */
- *warnstate = 2; /* to be continued */
+ lua_setwarnf(L, warnfcont, L); /* to be continued */
else { /* last part */
lua_writestringerror("%s", "\n"); /* finish message with end-of-line */
- *warnstate = 1; /* ready to start a new message */
+ lua_setwarnf(L, warnfon, L); /* next call is a new message */
}
}
+static void warnfon (void *ud, const char *message, int tocont) {
+ if (checkcontrol((lua_State *)ud, message, tocont)) /* control message? */
+ return; /* nothing else to be done */
+ lua_writestringerror("%s", "Lua warning: "); /* start a new warning */
+ warnfcont(ud, message, tocont); /* finish processing */
+}
+
+
LUALIB_API lua_State *luaL_newstate (void) {
lua_State *L = lua_newstate(l_alloc, NULL);
if (L) {
- int *warnstate; /* space for warning state */
lua_atpanic(L, &panic);
- warnstate = (int *)lua_newuserdatauv(L, sizeof(int), 0);
- luaL_ref(L, LUA_REGISTRYINDEX); /* make sure it won't be collected */
- *warnstate = 0; /* default is warnings off */
- lua_setwarnf(L, warnf, warnstate);
+ lua_setwarnf(L, warnfoff, L); /* default is warnings off */
}
return L;
}
src/lcode.c
@@ -753,7 +753,7 @@
/*
-** Ensure that expression 'e' is not a variable (nor a constant).
+** Ensure that expression 'e' is not a variable (nor a <const>).
** (Expression still may have jump lists.)
*/
void luaK_dischargevars (FuncState *fs, expdesc *e) {
@@ -805,8 +805,8 @@
/*
-** 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 @@
/*
-** 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 @@
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;
}
src/ldblib.c
@@ -281,25 +281,33 @@
** 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_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;
}
src/ldo.c
@@ -139,8 +139,7 @@
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 @@
(*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,21 +182,20 @@
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);
else return 0; /* do not raise an error */
}
for (; lim < newsize; lim++)
- setnilvalue(s2v(newstack + lim)); /* erase new segment */
+ setnilvalue(s2v(newstack + lim + EXTRA_STACK)); /* 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 @@
** 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 @@
/*
** 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 @@
/*
-** 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 @@
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 @@
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 */
@@ -514,16 +534,36 @@
/*
+** 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 ccall (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 'ccall'
+*/
+void luaD_call (lua_State *L, StkId func, int nResults) {
+ ccall(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);
+ ccall(L, func, nResults, nyci);
}
@@ -601,12 +641,12 @@
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 @@
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? */
+ 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) */
+ 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 @@
}
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 @@
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;
src/ldo.h
@@ -59,6 +59,7 @@
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);
src/lfunc.c
@@ -53,7 +53,7 @@
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);
}
}
src/lgc.c
@@ -161,18 +161,17 @@
/*
-** 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 @@
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 @@
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,9 +632,8 @@
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 */
- setnilvalue(s2v(o));
+ for (; o < th->stack_last + EXTRA_STACK; o++)
+ setnilvalue(s2v(o)); /* clear dead stack slice */
/* 'remarkupvals' may have removed thread from 'twups' list */
if (!isintwups(th) && th->openupval != NULL) {
th->twups = g->twups; /* link it back to the list */
@@ -644,7 +642,7 @@
}
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 @@
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 @@
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);
}
}
src/llex.c
@@ -254,9 +254,10 @@
/*
-** 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 @@
}
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 @@
return TK_NAME;
}
}
- else { /* single-char tokens (+ - / ...) */
+ else { /* single-char tokens ('+', '*', '%', '{', '}', ...) */
int c = ls->current;
next(ls);
return c;
src/llimits.h
@@ -235,6 +235,17 @@
/*
+** 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')
*/
@@ -315,7 +326,8 @@
/* exponentiation */
#if !defined(luai_numpow)
-#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b))
+#define luai_numpow(L,a,b) \
+ ((void)L, (b == 2) ? (a)*(a) : l_mathop(pow)(a,b))
#endif
/* the others are quite standard operations */
@@ -344,7 +356,7 @@
#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)
src/lobject.c
@@ -258,7 +258,7 @@
if (endptr == NULL) { /* failed? may be a different locale */
char buff[L_MAXLENNUM + 1];
const char *pdot = strchr(s, '.');
- if (strlen(s) > L_MAXLENNUM || pdot == NULL)
+ if (pdot == NULL || strlen(s) > L_MAXLENNUM)
return NULL; /* string too long or no dot; fail */
strcpy(buff, s); /* copy string to buffer */
buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */
src/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 @@
/*
** {==================================================================
-** Closures
+** Functions
** ===================================================================
*/
@@ -743,13 +745,13 @@
/*
-** 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)
/* }================================================================== */
src/lopcodes.h
@@ -261,7 +261,7 @@
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_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]) */
src/lparser.c
@@ -489,12 +489,10 @@
}
-/*
-** 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--)
/*
@@ -947,7 +945,7 @@
static void parlist (LexState *ls) {
- /* parlist -> [ param { ',' param } ] */
+ /* parlist -> [ {NAME ','} (NAME | '...') ] */
FuncState *fs = ls->fs;
Proto *f = fs->f;
int nparams = 0;
@@ -955,12 +953,12 @@
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;
@@ -1625,59 +1623,21 @@
}
-/*
-** Check whether next instruction is a single jump (a 'break', a 'goto'
-** to a forward label, or a 'goto' to a backward label with no variable
-** to close). If so, set the name of the 'label' it is jumping to
-** ("break" for a 'break') or to where it is jumping to ('target') and
-** return true. If not a single jump, leave input unchanged, to be
-** handled as a regular statement.
-*/
-static int issinglejump (LexState *ls, TString **label, int *target) {
- if (testnext(ls, TK_BREAK)) { /* a break? */
- *label = luaS_newliteral(ls->L, "break");
- return 1;
- }
- else if (ls->t.token != TK_GOTO || luaX_lookahead(ls) != TK_NAME)
- return 0; /* not a valid goto */
- else {
- TString *lname = ls->lookahead.seminfo.ts; /* label's id */
- Labeldesc *lb = findlabel(ls, lname);
- if (lb) { /* a backward jump? */
- /* does it need to close variables? */
- if (luaY_nvarstack(ls->fs) > stacklevel(ls->fs, lb->nactvar))
- return 0; /* not a single jump; cannot optimize */
- *target = lb->pc;
- }
- else /* jump forward */
- *label = lname;
- luaX_next(ls); /* skip goto */
- luaX_next(ls); /* skip name */
- return 1;
- }
-}
-
-
static void test_then_block (LexState *ls, int *escapelist) {
/* test_then_block -> [IF | ELSEIF] cond THEN block */
BlockCnt bl;
- int line;
FuncState *fs = ls->fs;
- TString *jlb = NULL;
- int target = NO_JUMP;
expdesc v;
int jf; /* instruction to skip 'then' code (if condition is false) */
luaX_next(ls); /* skip IF or ELSEIF */
expr(ls, &v); /* read condition */
checknext(ls, TK_THEN);
- line = ls->linenumber;
- if (issinglejump(ls, &jlb, &target)) { /* 'if x then goto' ? */
- luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */
+ if (ls->t.token == TK_BREAK) { /* 'if x then break' ? */
+ int line = ls->linenumber;
+ luaK_goiffalse(ls->fs, &v); /* will jump if condition is true */
+ luaX_next(ls); /* skip 'break' */
enterblock(fs, &bl, 0); /* must enter block before 'goto' */
- if (jlb != NULL) /* forward jump? */
- newgotoentry(ls, jlb, line, v.t); /* will be resolved later */
- else /* backward jump */
- luaK_patchlist(fs, v.t, target); /* jump directly to 'target' */
+ newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t);
while (testnext(ls, ';')) {} /* skip semicolons */
if (block_follow(ls, 0)) { /* jump is the entire block? */
leaveblock(fs);
@@ -1686,7 +1646,7 @@
else /* must skip over 'then' part if condition is false */
jf = luaK_jump(fs);
}
- else { /* regular case (not a jump) */
+ else { /* regular case (not a break) */
luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */
enterblock(fs, &bl, 0);
jf = v.f;
@@ -1754,7 +1714,7 @@
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 */
src/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 @@
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 <const> variable;
+ info = absolute index in 'actvar.arr' */
VINDEXED, /* indexed variable;
ind.t = table register;
ind.idx = key's R index */
src/lstate.c
@@ -76,7 +76,7 @@
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 @@
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 @@
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 @@
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 @@
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;
- for (i = 0; i < BASIC_STACK_SIZE; i++)
+ L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue);
+ for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; 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 @@
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 @@
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 @@
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 @@
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;
src/lstate.h
@@ -87,49 +87,13 @@
/*
-** 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.
+** 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.)
*/
-/* 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.)
-*/
-#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 */
#define yieldable(L) (((L)->nCcalls & 0xffff0000) == 0)
@@ -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 @@
#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 @@
*/
#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 @@
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 @@
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 @@
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;
@@ -389,12 +355,11 @@
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
src/lstring.c
@@ -23,16 +23,6 @@
/*
-** 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.
*/
#define MAXSTRTB cast_int(luaM_limitN(MAX_INT, TString*))
@@ -50,10 +40,9 @@
}
-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 @@
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 @@
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) {
src/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);
src/lstrlib.c
@@ -1365,7 +1365,6 @@
float f;
double d;
lua_Number n;
- char buff[5 * sizeof(lua_Number)]; /* enough for any float type */
} Ftypes;
@@ -1535,12 +1534,10 @@
** 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 @@
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 @@
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 @@
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);
src/ltable.c
@@ -166,17 +166,30 @@
/*
-** 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.
-*/
-static int equalkey (const TValue *k1, const Node *n2) {
- if (rawtt(k1) != keytt(n2)) /* not the same variants? */
+** 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. 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? */
+ !(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 +200,7 @@
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 +264,12 @@
/*
** "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 +306,7 @@
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 +744,7 @@
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 +764,7 @@
/* else... */
} /* FALLTHROUGH */
default:
- return getgeneric(t, key);
+ return getgeneric(t, key, 0);
}
}
src/lua.c
@@ -416,14 +416,18 @@
/*
-** 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 */
src/lua.h
@@ -18,7 +18,7 @@
#define LUA_VERSION_MAJOR "5"
#define LUA_VERSION_MINOR "4"
-#define LUA_VERSION_RELEASE "1"
+#define LUA_VERSION_RELEASE "2"
#define LUA_VERSION_NUM 504
#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 0)
src/luaconf.h
@@ -37,21 +37,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
** or Windows-specific features on Windows.
src/lvm.c
@@ -229,7 +229,7 @@
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 @@
#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 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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? */