Small corrections when setting 'L->top'
- OP_NEWTABLE can use 'ra + 1' to set top (instead of ci->top);
- OP_CLOSE doesn't need to set top ('Protect' already does that);
- OP_TFORCALL must use 'ProtectNT', to preserve the top already set.
(That was a small bug, because iterators could be called with
extra parameters besides the state and the control variable.)
- Comments and an extra test for the bug in previous item.
This commit is contained in:
10
lapi.h
10
lapi.h
@@ -11,12 +11,22 @@
|
|||||||
#include "llimits.h"
|
#include "llimits.h"
|
||||||
#include "lstate.h"
|
#include "lstate.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Increments 'L->top', checking for stack overflows */
|
||||||
#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \
|
#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \
|
||||||
"stack overflow");}
|
"stack overflow");}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** If a call returns too many multiple returns, the callee may not have
|
||||||
|
** stack space to accomodate all results. In this case, this macro
|
||||||
|
** increases its stack space ('L->ci->top').
|
||||||
|
*/
|
||||||
#define adjustresults(L,nres) \
|
#define adjustresults(L,nres) \
|
||||||
{ if ((nres) <= LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
|
{ if ((nres) <= LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
|
||||||
|
|
||||||
|
|
||||||
|
/* Ensure the stack has at least 'n' elements */
|
||||||
#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \
|
#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \
|
||||||
"not enough elements in the stack")
|
"not enough elements in the stack")
|
||||||
|
|
||||||
|
|||||||
@@ -694,9 +694,10 @@ static Proto *addprototype (LexState *ls) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** codes instruction to create new closure in parent function.
|
** codes instruction to create new closure in parent function.
|
||||||
** The OP_CLOSURE instruction must use the last available register,
|
** The OP_CLOSURE instruction uses the last available register,
|
||||||
** so that, if it invokes the GC, the GC knows which registers
|
** so that, if it invokes the GC, the GC knows which registers
|
||||||
** are in use at that time.
|
** are in use at that time.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
static void codeclosure (LexState *ls, expdesc *v) {
|
static void codeclosure (LexState *ls, expdesc *v) {
|
||||||
FuncState *fs = ls->fs->prev;
|
FuncState *fs = ls->fs->prev;
|
||||||
|
|||||||
7
lvm.c
7
lvm.c
@@ -1258,7 +1258,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
if (TESTARG_k(i))
|
if (TESTARG_k(i))
|
||||||
c += GETARG_Ax(*pc) * (MAXARG_C + 1);
|
c += GETARG_Ax(*pc) * (MAXARG_C + 1);
|
||||||
pc++; /* skip extra argument */
|
pc++; /* skip extra argument */
|
||||||
L->top = ci->top; /* correct top in case of GC */
|
L->top = ra + 1; /* correct top in case of emergency GC */
|
||||||
t = luaH_new(L); /* memory allocation */
|
t = luaH_new(L); /* memory allocation */
|
||||||
sethvalue2s(L, ra, t);
|
sethvalue2s(L, ra, t);
|
||||||
if (b != 0 || c != 0)
|
if (b != 0 || c != 0)
|
||||||
@@ -1478,7 +1478,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
vmcase(OP_CLOSE) {
|
vmcase(OP_CLOSE) {
|
||||||
L->top = ra + 1; /* everything is free after this slot */
|
|
||||||
Protect(luaF_close(L, ra, LUA_OK));
|
Protect(luaF_close(L, ra, LUA_OK));
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
@@ -1755,7 +1754,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
/* push function, state, and control variable */
|
/* push function, state, and control variable */
|
||||||
memcpy(ra + 4, ra, 3 * sizeof(*ra));
|
memcpy(ra + 4, ra, 3 * sizeof(*ra));
|
||||||
L->top = ra + 4 + 3;
|
L->top = ra + 4 + 3;
|
||||||
Protect(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */
|
ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */
|
||||||
updatestack(ci); /* stack may have changed */
|
updatestack(ci); /* stack may have changed */
|
||||||
i = *(pc++); /* go to next instruction */
|
i = *(pc++); /* go to next instruction */
|
||||||
lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
|
lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
|
||||||
@@ -1776,7 +1775,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
if (n == 0)
|
if (n == 0)
|
||||||
n = cast_int(L->top - ra) - 1; /* get up to the top */
|
n = cast_int(L->top - ra) - 1; /* get up to the top */
|
||||||
else
|
else
|
||||||
L->top = ci->top; /* correct top in case of GC */
|
L->top = ci->top; /* correct top in case of emergency GC */
|
||||||
last += n;
|
last += n;
|
||||||
if (TESTARG_k(i)) {
|
if (TESTARG_k(i)) {
|
||||||
last += GETARG_Ax(*pc) * (MAXARG_C + 1);
|
last += GETARG_Ax(*pc) * (MAXARG_C + 1);
|
||||||
|
|||||||
@@ -671,7 +671,8 @@ collectgarbage()
|
|||||||
|
|
||||||
local function f (n, p)
|
local function f (n, p)
|
||||||
local t = {}; for i=1,p do t[i] = i*10 end
|
local t = {}; for i=1,p do t[i] = i*10 end
|
||||||
return function (_,n)
|
return function (_, n, ...)
|
||||||
|
assert(select("#", ...) == 0) -- no extra arguments
|
||||||
if n > 0 then
|
if n > 0 then
|
||||||
n = n-1
|
n = n-1
|
||||||
return n, table.unpack(t)
|
return n, table.unpack(t)
|
||||||
|
|||||||
Reference in New Issue
Block a user