bug (GC can collect long identifier during parser) + change (using

a single constant table for all functions in a chunk)
This commit is contained in:
Roberto Ierusalimschy
2013-08-30 13:01:37 -03:00
parent 4f292d753c
commit 8ef9e8460e
6 changed files with 47 additions and 46 deletions

View File

@@ -1,5 +1,5 @@
/*
** $Id: lparser.c,v 2.133 2013/04/26 13:07:53 roberto Exp roberto $
** $Id: lparser.c,v 2.134 2013/08/16 18:55:49 roberto Exp roberto $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -35,6 +35,10 @@
#define hasmultret(k) ((k) == VCALL || (k) == VVARARG)
/* because all strings are unified by the scanner, the parser
can use pointer equality for string equality */
#define eqstr(a,b) ((a) == (b))
/*
** nodes for block list (list of active blocks)
@@ -57,16 +61,6 @@ static void statement (LexState *ls);
static void expr (LexState *ls, expdesc *v);
static void anchor_token (LexState *ls) {
/* last token from outer function must be EOS */
lua_assert(ls->fs != NULL || ls->t.token == TK_EOS);
if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {
TString *ts = ls->t.seminfo.ts;
luaX_newstring(ls, getstr(ts), ts->tsv.len);
}
}
/* semantic error */
static l_noret semerror (LexState *ls, const char *msg) {
ls->t.token = 0; /* remove 'near to' from final message */
@@ -222,7 +216,7 @@ static int searchupvalue (FuncState *fs, TString *name) {
int i;
Upvaldesc *up = fs->f->upvalues;
for (i = 0; i < fs->nups; i++) {
if (luaS_eqstr(up[i].name, name)) return i;
if (eqstr(up[i].name, name)) return i;
}
return -1; /* not found */
}
@@ -246,7 +240,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
static int searchvar (FuncState *fs, TString *n) {
int i;
for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) {
if (luaS_eqstr(n, getlocvar(fs, i)->varname))
if (eqstr(n, getlocvar(fs, i)->varname))
return i;
}
return -1; /* not found */
@@ -342,7 +336,7 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) {
FuncState *fs = ls->fs;
Labellist *gl = &ls->dyd->gt;
Labeldesc *gt = &gl->arr[g];
lua_assert(luaS_eqstr(gt->name, label->name));
lua_assert(eqstr(gt->name, label->name));
if (gt->nactvar < label->nactvar) {
TString *vname = getlocvar(fs, gt->nactvar)->varname;
const char *msg = luaO_pushfstring(ls->L,
@@ -369,7 +363,7 @@ static int findlabel (LexState *ls, int g) {
/* check labels in current block for a match */
for (i = bl->firstlabel; i < dyd->label.n; i++) {
Labeldesc *lb = &dyd->label.arr[i];
if (luaS_eqstr(lb->name, gt->name)) { /* correct label? */
if (eqstr(lb->name, gt->name)) { /* correct label? */
if (gt->nactvar > lb->nactvar &&
(bl->upval || dyd->label.n > bl->firstlabel))
luaK_patchclose(ls->fs, gt->pc, lb->nactvar);
@@ -403,7 +397,7 @@ static void findgotos (LexState *ls, Labeldesc *lb) {
Labellist *gl = &ls->dyd->gt;
int i = ls->fs->bl->firstgoto;
while (i < gl->n) {
if (luaS_eqstr(gl->arr[i].name, lb->name))
if (eqstr(gl->arr[i].name, lb->name))
closegoto(ls, i, lb);
else
i++;
@@ -525,7 +519,6 @@ static void codeclosure (LexState *ls, expdesc *v) {
static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
lua_State *L = ls->L;
Proto *f;
fs->prev = ls->fs; /* linked list of funcstates */
fs->ls = ls;
@@ -544,10 +537,6 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
f = fs->f;
f->source = ls->source;
f->maxstacksize = 2; /* registers 0/1 are always valid */
fs->h = luaH_new(L);
/* anchor table of constants (to avoid being collected) */
sethvalue2s(L, L->top, fs->h);
incr_top(L);
enterblock(fs, bl, 0);
}
@@ -572,9 +561,6 @@ static void close_func (LexState *ls) {
f->sizeupvalues = fs->nups;
lua_assert(fs->bl == NULL);
ls->fs = fs->prev;
/* last token read was anchored in defunct function; must re-anchor it */
anchor_token(ls);
L->top--; /* pop table of constants */
luaC_checkGC(L);
}
@@ -1202,7 +1188,7 @@ static void gotostat (LexState *ls, int pc) {
static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) {
int i;
for (i = fs->bl->firstlabel; i < ll->n; i++) {
if (luaS_eqstr(label, ll->arr[i].name)) {
if (eqstr(label, ll->arr[i].name)) {
const char *msg = luaO_pushfstring(fs->ls->L,
"label " LUA_QS " already defined on line %d",
getstr(label), ll->arr[i].line);
@@ -1627,8 +1613,10 @@ Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
LexState lexstate;
FuncState funcstate;
Closure *cl = luaF_newLclosure(L, 1); /* create main closure */
/* anchor closure (to avoid being collected) */
setclLvalue(L, L->top, cl);
setclLvalue(L, L->top, cl); /* anchor it (to avoid being collected) */
incr_top(L);
lexstate.h = luaH_new(L); /* create table for scanner */
sethvalue(L, L->top, lexstate.h); /* anchor it */
incr_top(L);
funcstate.f = cl->l.p = luaF_newproto(L);
funcstate.f->source = luaS_new(L, name); /* create and anchor TString */
@@ -1641,6 +1629,7 @@ Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
/* all scopes should be correctly finished */
lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0);
return cl; /* it's on the stack too */
L->top--; /* remove scanner's table */
return cl; /* closure is on the stack, too */
}