From 3d296304ef14ac9a6d1fa9357541ddd9bb54722f Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 10 Jul 2019 14:00:22 -0300 Subject: Towards constant propagation This commit detaches the number of active variables from the number of variables in the stack, during compilation. Soon, compile-time constants will be propagated and therefore will not exist during run time (in the stack). --- lparser.c | 113 ++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 37 deletions(-) (limited to 'lparser.c') diff --git a/lparser.c b/lparser.c index 1551cda9..c4626ba1 100644 --- a/lparser.c +++ b/lparser.c @@ -173,13 +173,13 @@ static void codename (LexState *ls, expdesc *e) { static int registerlocalvar (lua_State *L, FuncState *fs, TString *varname) { Proto *f = fs->f; int oldsize = f->sizelocvars; - luaM_growvector(L, f->locvars, fs->nlocvars, f->sizelocvars, + luaM_growvector(L, f->locvars, fs->ndebugvars, f->sizelocvars, LocVar, SHRT_MAX, "local variables"); while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; - f->locvars[fs->nlocvars].varname = varname; + f->locvars[fs->ndebugvars].varname = varname; luaC_objbarrier(L, f, varname); - return fs->nlocvars++; + return fs->ndebugvars++; } @@ -193,12 +193,13 @@ static Vardesc *new_localvar (LexState *ls, TString *name) { Vardesc *var; int reg = registerlocalvar(L, fs, name); checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, - MAXVARS, "local variables"); + MAXVARS, "local variables"); luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, dyd->actvar.size, Vardesc, USHRT_MAX, "local variables"); var = &dyd->actvar.arr[dyd->actvar.n++]; var->pidx = cast(short, reg); var->ro = 0; + var->name = name; setnilvalue(var); return var; } @@ -217,13 +218,42 @@ static Vardesc *getlocalvardesc (FuncState *fs, int i) { } +/* +** Convert 'nvar' (number of active variables at some point) to +** number of variables in the stack at that point. +*/ +static int stacklevel (FuncState *fs, int nvar) { + while (nvar > 0) { + Vardesc *vd = getlocalvardesc(fs, nvar - 1); + if (vdinstack(vd)) /* is in the stack? */ + return vd->sidx + 1; + else + nvar--; /* try previous variable */ + } + return 0; /* no variables */ +} + + +/* +** Return the number of variables in the stack for function 'fs' +*/ +int luaY_nvarstack (FuncState *fs) { + return stacklevel(fs, fs->nactvar); +} + + /* ** Get the debug-information entry for current variable 'i'. */ static LocVar *localdebuginfo (FuncState *fs, int i) { - int idx = getlocalvardesc(fs, i)->pidx; - lua_assert(idx < fs->nlocvars); - return &fs->f->locvars[idx]; + Vardesc *vd = getlocalvardesc(fs, i); + if (!vdinstack(vd)) + return NULL; /* no debug info. for constants */ + else { + int idx = vd->pidx; + lua_assert(idx < fs->ndebugvars); + return &fs->f->locvars[idx]; + } } @@ -242,7 +272,7 @@ static void check_readonly (LexState *ls, expdesc *e) { case VLOCAL: { Vardesc *vardesc = getlocalvardesc(fs, e->u.var.vidx); if (vardesc->ro) - varname = fs->f->locvars[vardesc->pidx].varname; + varname = vardesc->name; break; } case VUPVAL: { @@ -267,11 +297,12 @@ static void check_readonly (LexState *ls, expdesc *e) { */ static void adjustlocalvars (LexState *ls, int nvars) { FuncState *fs = ls->fs; + int stklevel = luaY_nvarstack(fs); int i; for (i = 0; i < nvars; i++) { int varidx = fs->nactvar++; Vardesc *var = getlocalvardesc(fs, varidx); - var->sidx = varidx; + var->sidx = stklevel++; fs->f->locvars[var->pidx].startpc = fs->pc; } } @@ -283,8 +314,11 @@ static void adjustlocalvars (LexState *ls, int nvars) { */ static void removevars (FuncState *fs, int tolevel) { fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); - while (fs->nactvar > tolevel) - localdebuginfo(fs, --fs->nactvar)->endpc = fs->pc; + while (fs->nactvar > tolevel) { + LocVar *var = localdebuginfo(fs, --fs->nactvar); + if (var) /* does it have debug information? */ + var->endpc = fs->pc; + } } @@ -321,7 +355,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { up->instack = 1; up->idx = v->u.var.sidx; up->ro = getlocalvardesc(prev, v->u.var.vidx)->ro; - lua_assert(eqstr(name, localdebuginfo(prev, v->u.var.vidx)->varname)); + lua_assert(eqstr(name, getlocalvardesc(prev, v->u.var.vidx)->name)); } else { up->instack = 0; @@ -342,7 +376,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 (eqstr(n, localdebuginfo(fs, i)->varname)) + if (eqstr(n, getlocalvardesc(fs, i)->name)) return i; } return -1; /* not found */ @@ -375,7 +409,7 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { if (v >= 0) { /* found? */ init_var(fs, var, v); /* variable is local */ if (!base) - markupval(fs, var->u.var.sidx); /* local will be used as an upval */ + markupval(fs, var->u.var.vidx); /* local will be used as an upval */ } else { /* not found as local at current level; try upvalues */ int idx = searchupvalue(fs, n); /* try existing upvalues */ @@ -449,7 +483,7 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { ** local variable. */ static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) { - const char *varname = getstr(localdebuginfo(ls->fs, gt->nactvar)->varname); + const char *varname = getstr(getlocalvardesc(ls->fs, gt->nactvar)->name); const char *msg = " at line %d jumps into the scope of local '%s'"; msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line, varname); luaK_semerror(ls, msg); /* raise the error */ @@ -552,7 +586,7 @@ static int createlabel (LexState *ls, TString *name, int line, ll->arr[l].nactvar = fs->bl->nactvar; } if (solvegotos(ls, &ll->arr[l])) { /* need close? */ - luaK_codeABC(fs, OP_CLOSE, fs->nactvar, 0, 0); + luaK_codeABC(fs, OP_CLOSE, luaY_nvarstack(fs), 0, 0); return 1; } return 0; @@ -568,10 +602,10 @@ static void movegotosout (FuncState *fs, BlockCnt *bl) { /* correct pending gotos to current block */ for (i = bl->firstgoto; i < gl->n; i++) { /* for each pending goto */ Labeldesc *gt = &gl->arr[i]; - if (gt->nactvar > bl->nactvar) { /* leaving a variable scope? */ - gt->nactvar = bl->nactvar; /* update goto level */ + /* leaving a variable scope? */ + if (stacklevel(fs, gt->nactvar) > stacklevel(fs, bl->nactvar)) gt->close |= bl->upval; /* jump may need a close */ - } + gt->nactvar = bl->nactvar; /* update goto level */ } } @@ -585,7 +619,7 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc); bl->previous = fs->bl; fs->bl = bl; - lua_assert(fs->freereg == fs->nactvar); + lua_assert(fs->freereg == luaY_nvarstack(fs)); } @@ -610,14 +644,15 @@ static void leaveblock (FuncState *fs) { BlockCnt *bl = fs->bl; LexState *ls = fs->ls; int hasclose = 0; + int stklevel = stacklevel(fs, bl->nactvar); /* level outside the block */ if (bl->isloop) /* fix pending breaks? */ hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); if (!hasclose && bl->previous && bl->upval) - luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + luaK_codeABC(fs, OP_CLOSE, stklevel, 0, 0); fs->bl = bl->previous; removevars(fs, bl->nactvar); lua_assert(bl->nactvar == fs->nactvar); - fs->freereg = fs->nactvar; /* free registers */ + fs->freereg = stklevel; /* free registers */ ls->dyd->label.n = bl->firstlabel; /* remove local labels */ if (bl->previous) /* inner block? */ movegotosout(fs, bl); /* update pending gotos to outer block */ @@ -675,7 +710,7 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { fs->nabslineinfo = 0; fs->np = 0; fs->nups = 0; - fs->nlocvars = 0; + fs->ndebugvars = 0; fs->nactvar = 0; fs->needclose = 0; fs->firstlocal = ls->dyd->actvar.n; @@ -691,7 +726,7 @@ static void close_func (LexState *ls) { lua_State *L = ls->L; FuncState *fs = ls->fs; Proto *f = fs->f; - luaK_ret(fs, fs->nactvar, 0); /* final return */ + luaK_ret(fs, luaY_nvarstack(fs), 0); /* final return */ leaveblock(fs); lua_assert(fs->bl == NULL); luaK_finish(fs); @@ -701,7 +736,7 @@ static void close_func (LexState *ls) { fs->nabslineinfo, AbsLineInfo); luaM_shrinkvector(L, f->k, f->sizek, fs->nk, TValue); luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *); - luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); + luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->ndebugvars, LocVar); luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); ls->fs = fs->prev; luaC_checkGC(L); @@ -1356,8 +1391,9 @@ static void gotostat (LexState *ls) { newgotoentry(ls, name, line, luaK_jump(fs)); else { /* found a label */ /* backward jump; will be resolved here */ - if (fs->nactvar > lb->nactvar) /* leaving the scope of some variable? */ - luaK_codeABC(fs, OP_CLOSE, lb->nactvar, 0, 0); + int lblevel = stacklevel(fs, lb->nactvar); /* label level */ + if (luaY_nvarstack(fs) > lblevel) /* leaving the scope of a variable? */ + luaK_codeABC(fs, OP_CLOSE, lblevel, 0, 0); /* create jump and link it to the label */ luaK_patchlist(fs, luaK_jump(fs), lb->pc); } @@ -1432,7 +1468,7 @@ static void repeatstat (LexState *ls, int line) { if (bl2.upval) { /* upvalues? */ int exit = luaK_jump(fs); /* normal exit must jump over fix */ luaK_patchtohere(fs, condexit); /* repetition must close upvalues */ - luaK_codeABC(fs, OP_CLOSE, bl2.nactvar, 0, 0); + luaK_codeABC(fs, OP_CLOSE, stacklevel(fs, bl2.nactvar), 0, 0); condexit = luaK_jump(fs); /* repeat after closing upvalues */ luaK_patchtohere(fs, exit); /* normal exit comes to here */ } @@ -1532,7 +1568,6 @@ static void forlist (LexState *ls, TString *indexname) { /* create control variables */ new_localvarliteral(ls, "(for generator)"); new_localvarliteral(ls, "(for state)"); - markupval(fs, fs->nactvar); /* state may create an upvalue */ new_localvarliteral(ls, "(for control)"); new_localvarliteral(ls, "(for toclose)"); /* create declared variables */ @@ -1545,6 +1580,7 @@ static void forlist (LexState *ls, TString *indexname) { line = ls->linenumber; adjust_assign(ls, 4, explist(ls, &e), &e); adjustlocalvars(ls, 4); /* control variables */ + markupval(fs, luaY_nvarstack(fs)); /* state may create an upvalue */ luaK_checkstack(fs, 3); /* extra space to call generator */ forbody(ls, base, line, nvars - 4, 1); } @@ -1587,7 +1623,8 @@ static int issinglejump (LexState *ls, TString **label, int *target) { TString *lname = ls->lookahead.seminfo.ts; /* label's id */ Labeldesc *lb = findlabel(ls, lname); if (lb) { /* a backward jump? */ - if (ls->fs->nactvar > lb->nactvar) /* needs to close variables? */ + /* 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; } @@ -1659,11 +1696,12 @@ static void ifstat (LexState *ls, int line) { static void localfunc (LexState *ls) { expdesc b; FuncState *fs = ls->fs; + int fvar = fs->nactvar; /* function's variable index */ new_localvar(ls, str_checkname(ls)); /* new local variable */ adjustlocalvars(ls, 1); /* enter its scope */ body(ls, &b, 0, ls->linenumber); /* function created in next register */ /* debug information will only see the variable after this point! */ - localdebuginfo(fs, b.u.info)->startpc = fs->pc; + localdebuginfo(fs, fvar)->startpc = fs->pc; } @@ -1687,9 +1725,10 @@ static int getlocalattribute (LexState *ls) { static void checktoclose (LexState *ls, int toclose) { if (toclose != -1) { /* is there a to-be-closed variable? */ FuncState *fs = ls->fs; - markupval(fs, fs->nactvar + toclose + 1); + int level = luaY_nvarstack(fs) + toclose; + markupval(fs, level + 1); fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */ - luaK_codeABC(fs, OP_TBC, fs->nactvar + toclose, 0, 0); + luaK_codeABC(fs, OP_TBC, level, 0, 0); } } @@ -1773,7 +1812,7 @@ static void retstat (LexState *ls) { FuncState *fs = ls->fs; expdesc e; int nret; /* number of values being returned */ - int first = fs->nactvar; /* first slot to be returned */ + int first = luaY_nvarstack(fs); /* first slot to be returned */ if (block_follow(ls, 1) || ls->t.token == ';') nret = 0; /* return no values */ else { @@ -1782,7 +1821,7 @@ static void retstat (LexState *ls) { luaK_setmultret(fs, &e); if (e.k == VCALL && nret == 1 && !fs->bl->insidetbc) { /* tail call? */ SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL); - lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar); + lua_assert(GETARG_A(getinstruction(fs,&e)) == luaY_nvarstack(fs)); } nret = LUA_MULTRET; /* return all values */ } @@ -1867,8 +1906,8 @@ static void statement (LexState *ls) { } } lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && - ls->fs->freereg >= ls->fs->nactvar); - ls->fs->freereg = ls->fs->nactvar; /* free registers */ + ls->fs->freereg >= luaY_nvarstack(ls->fs)); + ls->fs->freereg = luaY_nvarstack(ls->fs); /* free registers */ leavelevel(ls); } -- cgit v1.2.3-55-g6feb