Browse Source

parser keeps list of active local variables in a single dynamic array,
therefore saving C stack space

Roberto Ierusalimschy 16 years ago
parent
commit
916587508c
7 changed files with 76 additions and 47 deletions
  1. 7 3
      ldo.c
  2. 2 1
      llex.h
  3. 52 28
      lparser.c
  4. 11 3
      lparser.h
  5. 1 2
      ltests.c
  6. 2 2
      lua.h
  7. 1 8
      luaconf.h

+ 7 - 3
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;
 }
 

+ 2 - 1
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;

+ 52 - 28
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);

+ 11 - 3
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

+ 1 - 2
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;

+ 2 - 2
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
 */

+ 1 - 8
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.
 */