From 916587508c117decb2f4d70677fa06be18803874 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Sun, 11 Oct 2009 17:02:19 -0300 Subject: [PATCH] parser keeps list of active local variables in a single dynamic array, therefore saving C stack space --- ldo.c | 10 ++++--- llex.h | 3 ++- lparser.c | 80 ++++++++++++++++++++++++++++++++++++------------------- lparser.h | 14 +++++++--- ltests.c | 3 +-- lua.h | 4 +-- luaconf.h | 9 +------ 7 files changed, 76 insertions(+), 47 deletions(-) diff --git a/ldo.c b/ldo.c index d3c9906d..6affe61f 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.67 2009/09/14 14:30:39 roberto Exp roberto $ +** $Id: ldo.c,v 2.68 2009/09/28 16:32:50 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -563,6 +563,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, struct SParser { /* data to `f_parser' */ ZIO *z; Mbuffer buff; /* buffer to be used by the scanner */ + Varlist varl; /* list of local variables (to be used by the parser) */ const char *name; }; @@ -573,8 +574,9 @@ static void f_parser (lua_State *L, void *ud) { struct SParser *p = cast(struct SParser *, ud); int c = luaZ_lookahead(p->z); luaC_checkGC(L); - tf = (c == LUA_SIGNATURE[0]) ? luaU_undump(L, p->z, &p->buff, p->name) - : luaY_parser(L, p->z, &p->buff, p->name); + tf = (c == LUA_SIGNATURE[0]) + ? luaU_undump(L, p->z, &p->buff, p->name) + : luaY_parser(L, p->z, &p->buff, &p->varl, p->name); setptvalue2s(L, L->top, tf); incr_top(L); cl = luaF_newLclosure(L, tf->sizeupvalues, hvalue(gt(L))); @@ -589,9 +591,11 @@ int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { struct SParser p; int status; p.z = z; p.name = name; + p.varl.actvar = NULL; p.varl.nactvar = p.varl.actvarsize = 0; luaZ_initbuffer(L, &p.buff); status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); luaZ_freebuffer(L, &p.buff); + luaM_freearray(L, p.varl.actvar, p.varl.actvarsize); return status; } diff --git a/llex.h b/llex.h index 7c7d2746..3228f0e1 100644 --- a/llex.h +++ b/llex.h @@ -1,5 +1,5 @@ /* -** $Id: llex.h,v 1.60 2007/05/11 17:28:56 roberto Exp roberto $ +** $Id: llex.h,v 1.61 2007/10/25 16:45:47 roberto Exp roberto $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -58,6 +58,7 @@ typedef struct LexState { struct lua_State *L; ZIO *z; /* input stream */ Mbuffer *buff; /* buffer for tokens */ + struct Varlist *varl; /* list of all active local variables */ TString *source; /* current source name */ char decpoint; /* locale decimal point */ } LexState; diff --git a/lparser.c b/lparser.c index 1ab1cc69..a16de740 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.67 2009/09/28 16:32:50 roberto Exp roberto $ +** $Id: lparser.c,v 2.68 2009/09/30 15:38:37 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -27,9 +27,14 @@ +/* maximum number of local variables per function (must be smaller + than 250, due to the bytecode format) */ +#define MAXVARS 200 + + #define hasmultret(k) ((k) == VCALL || (k) == VVARARG) -#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i].idx]) + #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) @@ -157,15 +162,26 @@ static int registerlocalvar (LexState *ls, TString *varname) { } -#define new_localvarliteral(ls,v,n) \ - new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) +#define new_localvarliteral(ls,v) \ + new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1)) -static void new_localvar (LexState *ls, TString *name, int n) { +static void new_localvar (LexState *ls, TString *name) { FuncState *fs = ls->fs; + Varlist *vl = ls->varl; int reg = registerlocalvar(ls, name); - luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); - fs->actvar[fs->nactvar+n].idx = cast(unsigned short, reg); + luaY_checklimit(fs, vl->nactvar + 1 - fs->firstlocal, + MAXVARS, "local variables"); + luaM_growvector(ls->L, vl->actvar, vl->nactvar + 1, + vl->actvarsize, vardesc, MAX_INT, "local variables"); + vl->actvar[vl->nactvar++].idx = cast(unsigned short, reg); +} + + +static LocVar *getlocvar (FuncState *fs, int i) { + int idx = fs->ls->varl->actvar[fs->firstlocal + i].idx; + lua_assert(idx < fs->nlocvars); + return &fs->f->locvars[idx]; } @@ -173,14 +189,15 @@ static void adjustlocalvars (LexState *ls, int nvars) { FuncState *fs = ls->fs; fs->nactvar = cast_byte(fs->nactvar + nvars); for (; nvars; nvars--) { - getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; + getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; } } static void removevars (FuncState *fs, int tolevel) { + fs->ls->varl->nactvar -= (fs->nactvar - tolevel); while (fs->nactvar > tolevel) - getlocvar(fs, --fs->nactvar).endpc = fs->pc; + getlocvar(fs, --fs->nactvar)->endpc = fs->pc; } @@ -212,7 +229,7 @@ static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { static int searchvar (FuncState *fs, TString *n) { int i; for (i=fs->nactvar-1; i >= 0; i--) { - if (n == getlocvar(fs, i).varname) + if (n == getlocvar(fs, i)->varname) return i; } return -1; /* not found */ @@ -350,6 +367,7 @@ static void open_func (LexState *ls, FuncState *fs) { fs->nups = 0; fs->nlocvars = 0; fs->nactvar = 0; + fs->firstlocal = ls->varl->nactvar; fs->envreg = NO_REG; fs->bl = NULL; fs->h = luaH_new(L); @@ -392,13 +410,15 @@ static void close_func (LexState *ls) { } -Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { +Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, Varlist *varl, + const char *name) { struct LexState lexstate; struct FuncState funcstate; TString *tname = luaS_new(L, name); setsvalue2s(L, L->top, tname); /* protect name */ incr_top(L); lexstate.buff = buff; + lexstate.varl = varl; luaX_setinput(L, &lexstate, z, tname); open_func(&lexstate, &funcstate); funcstate.f->is_vararg = 1; /* main func. is always vararg */ @@ -565,7 +585,8 @@ static void parlist (LexState *ls) { do { switch (ls->t.token) { case TK_NAME: { /* param -> NAME */ - new_localvar(ls, str_checkname(ls), nparams++); + new_localvar(ls, str_checkname(ls)); + nparams++; break; } case TK_DOTS: { /* param -> `...' */ @@ -590,7 +611,7 @@ static void body (LexState *ls, expdesc *e, int needself, int line) { new_fs.f->linedefined = line; checknext(ls, '('); if (needself) { - new_localvarliteral(ls, "self", 0); + new_localvarliteral(ls, "self"); adjustlocalvars(ls, 1); } parlist(ls); @@ -1083,10 +1104,10 @@ static void fornum (LexState *ls, TString *varname, int line) { /* fornum -> NAME = exp1,exp1[,exp1] forbody */ FuncState *fs = ls->fs; int base = fs->freereg; - new_localvarliteral(ls, "(for index)", 0); - new_localvarliteral(ls, "(for limit)", 1); - new_localvarliteral(ls, "(for step)", 2); - new_localvar(ls, varname, 3); + new_localvarliteral(ls, "(for index)"); + new_localvarliteral(ls, "(for limit)"); + new_localvarliteral(ls, "(for step)"); + new_localvar(ls, varname); checknext(ls, '='); exp1(ls); /* initial value */ checknext(ls, ','); @@ -1105,17 +1126,19 @@ static void forlist (LexState *ls, TString *indexname) { /* forlist -> NAME {,NAME} IN explist1 forbody */ FuncState *fs = ls->fs; expdesc e; - int nvars = 0; + int nvars = 4; /* gen, state, control, plus at least one declared var */ int line; int base = fs->freereg; /* create control variables */ - new_localvarliteral(ls, "(for generator)", nvars++); - new_localvarliteral(ls, "(for state)", nvars++); - new_localvarliteral(ls, "(for control)", nvars++); + new_localvarliteral(ls, "(for generator)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for control)"); /* create declared variables */ - new_localvar(ls, indexname, nvars++); - while (testnext(ls, ',')) - new_localvar(ls, str_checkname(ls), nvars++); + new_localvar(ls, indexname); + while (testnext(ls, ',')) { + new_localvar(ls, str_checkname(ls)); + nvars++; + } checknext(ls, TK_IN); line = ls->linenumber; adjust_assign(ls, 3, explist1(ls, &e), &e); @@ -1180,14 +1203,14 @@ static void ifstat (LexState *ls, int line) { static void localfunc (LexState *ls) { expdesc v, b; FuncState *fs = ls->fs; - new_localvar(ls, str_checkname(ls), 0); + new_localvar(ls, str_checkname(ls)); init_exp(&v, VLOCAL, fs->freereg); luaK_reserveregs(fs, 1); adjustlocalvars(ls, 1); body(ls, &b, 0, ls->linenumber); luaK_storevar(fs, &v, &b); /* debug information will only see the variable after this point! */ - getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; + getlocvar(fs, fs->nactvar - 1)->startpc = fs->pc; } @@ -1197,7 +1220,8 @@ static void localstat (LexState *ls) { int nexps; expdesc e; do { - new_localvar(ls, str_checkname(ls), nvars++); + new_localvar(ls, str_checkname(ls)); + nvars++; } while (testnext(ls, ',')); if (testnext(ls, '=')) nexps = explist1(ls, &e); @@ -1243,7 +1267,7 @@ static void instat (LexState *ls, int line) { BlockCnt bl; luaX_next(ls); /* skip IN */ enterblock(fs, &bl, 0); /* scope for environment variable */ - new_localvarliteral(ls, "(environment)", 0); + new_localvarliteral(ls, "(environment)"); fs->envreg = exp1(ls); /* new environment */ adjustlocalvars(ls, 1); checknext(ls, TK_DO); diff --git a/lparser.h b/lparser.h index 850b787d..4fcdc621 100644 --- a/lparser.h +++ b/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.59 2009/09/28 16:32:50 roberto Exp roberto $ +** $Id: lparser.h,v 1.60 2009/09/30 15:38:37 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -51,6 +51,14 @@ typedef struct vardesc { } vardesc; +/* list of all active local variables */ +typedef struct Varlist { + vardesc *actvar; + int nactvar; + int actvarsize; +} Varlist; + + struct BlockCnt; /* defined in lparser.c */ @@ -68,16 +76,16 @@ typedef struct FuncState { int freereg; /* first free register */ int nk; /* number of elements in `k' */ int np; /* number of elements in `p' */ + int firstlocal; /* index of first local var of this function */ short nlocvars; /* number of elements in `locvars' */ lu_byte nactvar; /* number of active local variables */ lu_byte nups; /* number of upvalues */ lu_byte envreg; /* register holding current lexical environment */ - vardesc actvar[LUAI_MAXVARS]; /* stack of active variables */ } FuncState; LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - const char *name); + Varlist *varl, const char *name); #endif diff --git a/ltests.c b/ltests.c index 40a7f965..4fb7a4d2 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.74 2009/09/30 20:49:25 roberto Exp roberto $ +** $Id: ltests.c,v 2.75 2009/10/05 16:44:33 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -491,7 +491,6 @@ static int get_limits (lua_State *L) { lua_createtable(L, 0, 5); setnameval(L, "BITS_INT", LUAI_BITSINT); setnameval(L, "LFPF", LFIELDS_PER_FLUSH); - setnameval(L, "MAXVARS", LUAI_MAXVARS); setnameval(L, "MAXSTACK", MAXSTACK); setnameval(L, "NUM_OPCODES", NUM_OPCODES); return 1; diff --git a/lua.h b/lua.h index 478374e3..7492f4a5 100644 --- a/lua.h +++ b/lua.h @@ -1,6 +1,6 @@ /* -** $Id: lua.h,v 1.244 2009/09/21 12:09:52 roberto Exp roberto $ -** Lua - An Extensible Extension Language +** $Id: lua.h,v 1.245 2009/10/05 16:44:33 roberto Exp roberto $ +** Lua - A Scripting Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file */ diff --git a/luaconf.h b/luaconf.h index c18681dc..f9cd7283 100644 --- a/luaconf.h +++ b/luaconf.h @@ -1,5 +1,5 @@ /* -** $Id: luaconf.h,v 1.109 2009/08/25 19:58:08 roberto Exp roberto $ +** $Id: luaconf.h,v 1.110 2009/09/28 16:32:50 roberto Exp roberto $ ** Configuration file for Lua ** See Copyright Notice in lua.h */ @@ -454,13 +454,6 @@ #define LUAI_MAXCCALLS 200 -/* -@@ LUAI_MAXVARS is the maximum number of local variables per function -@* (must be smaller than 250). -*/ -#define LUAI_MAXVARS 200 - - /* @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. */