diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-07-10 14:00:22 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-07-10 14:00:22 -0300 |
| commit | 3d296304ef14ac9a6d1fa9357541ddd9bb54722f (patch) | |
| tree | e7c8ac1ff0a0750b5db63da68adc0bfa676d1cc3 | |
| parent | 54f7b46c1e8a0188e1649046a3a72522f2d769f4 (diff) | |
| download | lua-3d296304ef14ac9a6d1fa9357541ddd9bb54722f.tar.gz lua-3d296304ef14ac9a6d1fa9357541ddd9bb54722f.tar.bz2 lua-3d296304ef14ac9a6d1fa9357541ddd9bb54722f.zip | |
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).
| -rw-r--r-- | lcode.c | 4 | ||||
| -rw-r--r-- | lparser.c | 113 | ||||
| -rw-r--r-- | lparser.h | 12 |
3 files changed, 87 insertions, 42 deletions
| @@ -458,7 +458,7 @@ void luaK_reserveregs (FuncState *fs, int n) { | |||
| 458 | ) | 458 | ) |
| 459 | */ | 459 | */ |
| 460 | static void freereg (FuncState *fs, int reg) { | 460 | static void freereg (FuncState *fs, int reg) { |
| 461 | if (reg >= fs->nactvar) { | 461 | if (reg >= luaY_nvarstack(fs)) { |
| 462 | fs->freereg--; | 462 | fs->freereg--; |
| 463 | lua_assert(reg == fs->freereg); | 463 | lua_assert(reg == fs->freereg); |
| 464 | } | 464 | } |
| @@ -850,7 +850,7 @@ int luaK_exp2anyreg (FuncState *fs, expdesc *e) { | |||
| 850 | if (e->k == VNONRELOC) { /* expression already has a register? */ | 850 | if (e->k == VNONRELOC) { /* expression already has a register? */ |
| 851 | if (!hasjumps(e)) /* no jumps? */ | 851 | if (!hasjumps(e)) /* no jumps? */ |
| 852 | return e->u.info; /* result is already in a register */ | 852 | return e->u.info; /* result is already in a register */ |
| 853 | if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ | 853 | if (e->u.info >= luaY_nvarstack(fs)) { /* reg. is not a local? */ |
| 854 | exp2reg(fs, e, e->u.info); /* put final result in it */ | 854 | exp2reg(fs, e, e->u.info); /* put final result in it */ |
| 855 | return e->u.info; | 855 | return e->u.info; |
| 856 | } | 856 | } |
| @@ -173,13 +173,13 @@ static void codename (LexState *ls, expdesc *e) { | |||
| 173 | static int registerlocalvar (lua_State *L, FuncState *fs, TString *varname) { | 173 | static int registerlocalvar (lua_State *L, FuncState *fs, TString *varname) { |
| 174 | Proto *f = fs->f; | 174 | Proto *f = fs->f; |
| 175 | int oldsize = f->sizelocvars; | 175 | int oldsize = f->sizelocvars; |
| 176 | luaM_growvector(L, f->locvars, fs->nlocvars, f->sizelocvars, | 176 | luaM_growvector(L, f->locvars, fs->ndebugvars, f->sizelocvars, |
| 177 | LocVar, SHRT_MAX, "local variables"); | 177 | LocVar, SHRT_MAX, "local variables"); |
| 178 | while (oldsize < f->sizelocvars) | 178 | while (oldsize < f->sizelocvars) |
| 179 | f->locvars[oldsize++].varname = NULL; | 179 | f->locvars[oldsize++].varname = NULL; |
| 180 | f->locvars[fs->nlocvars].varname = varname; | 180 | f->locvars[fs->ndebugvars].varname = varname; |
| 181 | luaC_objbarrier(L, f, varname); | 181 | luaC_objbarrier(L, f, varname); |
| 182 | return fs->nlocvars++; | 182 | return fs->ndebugvars++; |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | 185 | ||
| @@ -193,12 +193,13 @@ static Vardesc *new_localvar (LexState *ls, TString *name) { | |||
| 193 | Vardesc *var; | 193 | Vardesc *var; |
| 194 | int reg = registerlocalvar(L, fs, name); | 194 | int reg = registerlocalvar(L, fs, name); |
| 195 | checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, | 195 | checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, |
| 196 | MAXVARS, "local variables"); | 196 | MAXVARS, "local variables"); |
| 197 | luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, | 197 | luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, |
| 198 | dyd->actvar.size, Vardesc, USHRT_MAX, "local variables"); | 198 | dyd->actvar.size, Vardesc, USHRT_MAX, "local variables"); |
| 199 | var = &dyd->actvar.arr[dyd->actvar.n++]; | 199 | var = &dyd->actvar.arr[dyd->actvar.n++]; |
| 200 | var->pidx = cast(short, reg); | 200 | var->pidx = cast(short, reg); |
| 201 | var->ro = 0; | 201 | var->ro = 0; |
| 202 | var->name = name; | ||
| 202 | setnilvalue(var); | 203 | setnilvalue(var); |
| 203 | return var; | 204 | return var; |
| 204 | } | 205 | } |
| @@ -218,12 +219,41 @@ static Vardesc *getlocalvardesc (FuncState *fs, int i) { | |||
| 218 | 219 | ||
| 219 | 220 | ||
| 220 | /* | 221 | /* |
| 222 | ** Convert 'nvar' (number of active variables at some point) to | ||
| 223 | ** number of variables in the stack at that point. | ||
| 224 | */ | ||
| 225 | static int stacklevel (FuncState *fs, int nvar) { | ||
| 226 | while (nvar > 0) { | ||
| 227 | Vardesc *vd = getlocalvardesc(fs, nvar - 1); | ||
| 228 | if (vdinstack(vd)) /* is in the stack? */ | ||
| 229 | return vd->sidx + 1; | ||
| 230 | else | ||
| 231 | nvar--; /* try previous variable */ | ||
| 232 | } | ||
| 233 | return 0; /* no variables */ | ||
| 234 | } | ||
| 235 | |||
| 236 | |||
| 237 | /* | ||
| 238 | ** Return the number of variables in the stack for function 'fs' | ||
| 239 | */ | ||
| 240 | int luaY_nvarstack (FuncState *fs) { | ||
| 241 | return stacklevel(fs, fs->nactvar); | ||
| 242 | } | ||
| 243 | |||
| 244 | |||
| 245 | /* | ||
| 221 | ** Get the debug-information entry for current variable 'i'. | 246 | ** Get the debug-information entry for current variable 'i'. |
| 222 | */ | 247 | */ |
| 223 | static LocVar *localdebuginfo (FuncState *fs, int i) { | 248 | static LocVar *localdebuginfo (FuncState *fs, int i) { |
| 224 | int idx = getlocalvardesc(fs, i)->pidx; | 249 | Vardesc *vd = getlocalvardesc(fs, i); |
| 225 | lua_assert(idx < fs->nlocvars); | 250 | if (!vdinstack(vd)) |
| 226 | return &fs->f->locvars[idx]; | 251 | return NULL; /* no debug info. for constants */ |
| 252 | else { | ||
| 253 | int idx = vd->pidx; | ||
| 254 | lua_assert(idx < fs->ndebugvars); | ||
| 255 | return &fs->f->locvars[idx]; | ||
| 256 | } | ||
| 227 | } | 257 | } |
| 228 | 258 | ||
| 229 | 259 | ||
| @@ -242,7 +272,7 @@ static void check_readonly (LexState *ls, expdesc *e) { | |||
| 242 | case VLOCAL: { | 272 | case VLOCAL: { |
| 243 | Vardesc *vardesc = getlocalvardesc(fs, e->u.var.vidx); | 273 | Vardesc *vardesc = getlocalvardesc(fs, e->u.var.vidx); |
| 244 | if (vardesc->ro) | 274 | if (vardesc->ro) |
| 245 | varname = fs->f->locvars[vardesc->pidx].varname; | 275 | varname = vardesc->name; |
| 246 | break; | 276 | break; |
| 247 | } | 277 | } |
| 248 | case VUPVAL: { | 278 | case VUPVAL: { |
| @@ -267,11 +297,12 @@ static void check_readonly (LexState *ls, expdesc *e) { | |||
| 267 | */ | 297 | */ |
| 268 | static void adjustlocalvars (LexState *ls, int nvars) { | 298 | static void adjustlocalvars (LexState *ls, int nvars) { |
| 269 | FuncState *fs = ls->fs; | 299 | FuncState *fs = ls->fs; |
| 300 | int stklevel = luaY_nvarstack(fs); | ||
| 270 | int i; | 301 | int i; |
| 271 | for (i = 0; i < nvars; i++) { | 302 | for (i = 0; i < nvars; i++) { |
| 272 | int varidx = fs->nactvar++; | 303 | int varidx = fs->nactvar++; |
| 273 | Vardesc *var = getlocalvardesc(fs, varidx); | 304 | Vardesc *var = getlocalvardesc(fs, varidx); |
| 274 | var->sidx = varidx; | 305 | var->sidx = stklevel++; |
| 275 | fs->f->locvars[var->pidx].startpc = fs->pc; | 306 | fs->f->locvars[var->pidx].startpc = fs->pc; |
| 276 | } | 307 | } |
| 277 | } | 308 | } |
| @@ -283,8 +314,11 @@ static void adjustlocalvars (LexState *ls, int nvars) { | |||
| 283 | */ | 314 | */ |
| 284 | static void removevars (FuncState *fs, int tolevel) { | 315 | static void removevars (FuncState *fs, int tolevel) { |
| 285 | fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); | 316 | fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); |
| 286 | while (fs->nactvar > tolevel) | 317 | while (fs->nactvar > tolevel) { |
| 287 | localdebuginfo(fs, --fs->nactvar)->endpc = fs->pc; | 318 | LocVar *var = localdebuginfo(fs, --fs->nactvar); |
| 319 | if (var) /* does it have debug information? */ | ||
| 320 | var->endpc = fs->pc; | ||
| 321 | } | ||
| 288 | } | 322 | } |
| 289 | 323 | ||
| 290 | 324 | ||
| @@ -321,7 +355,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { | |||
| 321 | up->instack = 1; | 355 | up->instack = 1; |
| 322 | up->idx = v->u.var.sidx; | 356 | up->idx = v->u.var.sidx; |
| 323 | up->ro = getlocalvardesc(prev, v->u.var.vidx)->ro; | 357 | up->ro = getlocalvardesc(prev, v->u.var.vidx)->ro; |
| 324 | lua_assert(eqstr(name, localdebuginfo(prev, v->u.var.vidx)->varname)); | 358 | lua_assert(eqstr(name, getlocalvardesc(prev, v->u.var.vidx)->name)); |
| 325 | } | 359 | } |
| 326 | else { | 360 | else { |
| 327 | up->instack = 0; | 361 | up->instack = 0; |
| @@ -342,7 +376,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { | |||
| 342 | static int searchvar (FuncState *fs, TString *n) { | 376 | static int searchvar (FuncState *fs, TString *n) { |
| 343 | int i; | 377 | int i; |
| 344 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { | 378 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { |
| 345 | if (eqstr(n, localdebuginfo(fs, i)->varname)) | 379 | if (eqstr(n, getlocalvardesc(fs, i)->name)) |
| 346 | return i; | 380 | return i; |
| 347 | } | 381 | } |
| 348 | return -1; /* not found */ | 382 | return -1; /* not found */ |
| @@ -375,7 +409,7 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | |||
| 375 | if (v >= 0) { /* found? */ | 409 | if (v >= 0) { /* found? */ |
| 376 | init_var(fs, var, v); /* variable is local */ | 410 | init_var(fs, var, v); /* variable is local */ |
| 377 | if (!base) | 411 | if (!base) |
| 378 | markupval(fs, var->u.var.sidx); /* local will be used as an upval */ | 412 | markupval(fs, var->u.var.vidx); /* local will be used as an upval */ |
| 379 | } | 413 | } |
| 380 | else { /* not found as local at current level; try upvalues */ | 414 | else { /* not found as local at current level; try upvalues */ |
| 381 | int idx = searchupvalue(fs, n); /* try existing upvalues */ | 415 | int idx = searchupvalue(fs, n); /* try existing upvalues */ |
| @@ -449,7 +483,7 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | |||
| 449 | ** local variable. | 483 | ** local variable. |
| 450 | */ | 484 | */ |
| 451 | static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) { | 485 | static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) { |
| 452 | const char *varname = getstr(localdebuginfo(ls->fs, gt->nactvar)->varname); | 486 | const char *varname = getstr(getlocalvardesc(ls->fs, gt->nactvar)->name); |
| 453 | const char *msg = "<goto %s> at line %d jumps into the scope of local '%s'"; | 487 | const char *msg = "<goto %s> at line %d jumps into the scope of local '%s'"; |
| 454 | msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line, varname); | 488 | msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line, varname); |
| 455 | luaK_semerror(ls, msg); /* raise the error */ | 489 | luaK_semerror(ls, msg); /* raise the error */ |
| @@ -552,7 +586,7 @@ static int createlabel (LexState *ls, TString *name, int line, | |||
| 552 | ll->arr[l].nactvar = fs->bl->nactvar; | 586 | ll->arr[l].nactvar = fs->bl->nactvar; |
| 553 | } | 587 | } |
| 554 | if (solvegotos(ls, &ll->arr[l])) { /* need close? */ | 588 | if (solvegotos(ls, &ll->arr[l])) { /* need close? */ |
| 555 | luaK_codeABC(fs, OP_CLOSE, fs->nactvar, 0, 0); | 589 | luaK_codeABC(fs, OP_CLOSE, luaY_nvarstack(fs), 0, 0); |
| 556 | return 1; | 590 | return 1; |
| 557 | } | 591 | } |
| 558 | return 0; | 592 | return 0; |
| @@ -568,10 +602,10 @@ static void movegotosout (FuncState *fs, BlockCnt *bl) { | |||
| 568 | /* correct pending gotos to current block */ | 602 | /* correct pending gotos to current block */ |
| 569 | for (i = bl->firstgoto; i < gl->n; i++) { /* for each pending goto */ | 603 | for (i = bl->firstgoto; i < gl->n; i++) { /* for each pending goto */ |
| 570 | Labeldesc *gt = &gl->arr[i]; | 604 | Labeldesc *gt = &gl->arr[i]; |
| 571 | if (gt->nactvar > bl->nactvar) { /* leaving a variable scope? */ | 605 | /* leaving a variable scope? */ |
| 572 | gt->nactvar = bl->nactvar; /* update goto level */ | 606 | if (stacklevel(fs, gt->nactvar) > stacklevel(fs, bl->nactvar)) |
| 573 | gt->close |= bl->upval; /* jump may need a close */ | 607 | gt->close |= bl->upval; /* jump may need a close */ |
| 574 | } | 608 | gt->nactvar = bl->nactvar; /* update goto level */ |
| 575 | } | 609 | } |
| 576 | } | 610 | } |
| 577 | 611 | ||
| @@ -585,7 +619,7 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { | |||
| 585 | bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc); | 619 | bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc); |
| 586 | bl->previous = fs->bl; | 620 | bl->previous = fs->bl; |
| 587 | fs->bl = bl; | 621 | fs->bl = bl; |
| 588 | lua_assert(fs->freereg == fs->nactvar); | 622 | lua_assert(fs->freereg == luaY_nvarstack(fs)); |
| 589 | } | 623 | } |
| 590 | 624 | ||
| 591 | 625 | ||
| @@ -610,14 +644,15 @@ static void leaveblock (FuncState *fs) { | |||
| 610 | BlockCnt *bl = fs->bl; | 644 | BlockCnt *bl = fs->bl; |
| 611 | LexState *ls = fs->ls; | 645 | LexState *ls = fs->ls; |
| 612 | int hasclose = 0; | 646 | int hasclose = 0; |
| 647 | int stklevel = stacklevel(fs, bl->nactvar); /* level outside the block */ | ||
| 613 | if (bl->isloop) /* fix pending breaks? */ | 648 | if (bl->isloop) /* fix pending breaks? */ |
| 614 | hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); | 649 | hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); |
| 615 | if (!hasclose && bl->previous && bl->upval) | 650 | if (!hasclose && bl->previous && bl->upval) |
| 616 | luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); | 651 | luaK_codeABC(fs, OP_CLOSE, stklevel, 0, 0); |
| 617 | fs->bl = bl->previous; | 652 | fs->bl = bl->previous; |
| 618 | removevars(fs, bl->nactvar); | 653 | removevars(fs, bl->nactvar); |
| 619 | lua_assert(bl->nactvar == fs->nactvar); | 654 | lua_assert(bl->nactvar == fs->nactvar); |
| 620 | fs->freereg = fs->nactvar; /* free registers */ | 655 | fs->freereg = stklevel; /* free registers */ |
| 621 | ls->dyd->label.n = bl->firstlabel; /* remove local labels */ | 656 | ls->dyd->label.n = bl->firstlabel; /* remove local labels */ |
| 622 | if (bl->previous) /* inner block? */ | 657 | if (bl->previous) /* inner block? */ |
| 623 | movegotosout(fs, bl); /* update pending gotos to outer block */ | 658 | movegotosout(fs, bl); /* update pending gotos to outer block */ |
| @@ -675,7 +710,7 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { | |||
| 675 | fs->nabslineinfo = 0; | 710 | fs->nabslineinfo = 0; |
| 676 | fs->np = 0; | 711 | fs->np = 0; |
| 677 | fs->nups = 0; | 712 | fs->nups = 0; |
| 678 | fs->nlocvars = 0; | 713 | fs->ndebugvars = 0; |
| 679 | fs->nactvar = 0; | 714 | fs->nactvar = 0; |
| 680 | fs->needclose = 0; | 715 | fs->needclose = 0; |
| 681 | fs->firstlocal = ls->dyd->actvar.n; | 716 | fs->firstlocal = ls->dyd->actvar.n; |
| @@ -691,7 +726,7 @@ static void close_func (LexState *ls) { | |||
| 691 | lua_State *L = ls->L; | 726 | lua_State *L = ls->L; |
| 692 | FuncState *fs = ls->fs; | 727 | FuncState *fs = ls->fs; |
| 693 | Proto *f = fs->f; | 728 | Proto *f = fs->f; |
| 694 | luaK_ret(fs, fs->nactvar, 0); /* final return */ | 729 | luaK_ret(fs, luaY_nvarstack(fs), 0); /* final return */ |
| 695 | leaveblock(fs); | 730 | leaveblock(fs); |
| 696 | lua_assert(fs->bl == NULL); | 731 | lua_assert(fs->bl == NULL); |
| 697 | luaK_finish(fs); | 732 | luaK_finish(fs); |
| @@ -701,7 +736,7 @@ static void close_func (LexState *ls) { | |||
| 701 | fs->nabslineinfo, AbsLineInfo); | 736 | fs->nabslineinfo, AbsLineInfo); |
| 702 | luaM_shrinkvector(L, f->k, f->sizek, fs->nk, TValue); | 737 | luaM_shrinkvector(L, f->k, f->sizek, fs->nk, TValue); |
| 703 | luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *); | 738 | luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *); |
| 704 | luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); | 739 | luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->ndebugvars, LocVar); |
| 705 | luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); | 740 | luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); |
| 706 | ls->fs = fs->prev; | 741 | ls->fs = fs->prev; |
| 707 | luaC_checkGC(L); | 742 | luaC_checkGC(L); |
| @@ -1356,8 +1391,9 @@ static void gotostat (LexState *ls) { | |||
| 1356 | newgotoentry(ls, name, line, luaK_jump(fs)); | 1391 | newgotoentry(ls, name, line, luaK_jump(fs)); |
| 1357 | else { /* found a label */ | 1392 | else { /* found a label */ |
| 1358 | /* backward jump; will be resolved here */ | 1393 | /* backward jump; will be resolved here */ |
| 1359 | if (fs->nactvar > lb->nactvar) /* leaving the scope of some variable? */ | 1394 | int lblevel = stacklevel(fs, lb->nactvar); /* label level */ |
| 1360 | luaK_codeABC(fs, OP_CLOSE, lb->nactvar, 0, 0); | 1395 | if (luaY_nvarstack(fs) > lblevel) /* leaving the scope of a variable? */ |
| 1396 | luaK_codeABC(fs, OP_CLOSE, lblevel, 0, 0); | ||
| 1361 | /* create jump and link it to the label */ | 1397 | /* create jump and link it to the label */ |
| 1362 | luaK_patchlist(fs, luaK_jump(fs), lb->pc); | 1398 | luaK_patchlist(fs, luaK_jump(fs), lb->pc); |
| 1363 | } | 1399 | } |
| @@ -1432,7 +1468,7 @@ static void repeatstat (LexState *ls, int line) { | |||
| 1432 | if (bl2.upval) { /* upvalues? */ | 1468 | if (bl2.upval) { /* upvalues? */ |
| 1433 | int exit = luaK_jump(fs); /* normal exit must jump over fix */ | 1469 | int exit = luaK_jump(fs); /* normal exit must jump over fix */ |
| 1434 | luaK_patchtohere(fs, condexit); /* repetition must close upvalues */ | 1470 | luaK_patchtohere(fs, condexit); /* repetition must close upvalues */ |
| 1435 | luaK_codeABC(fs, OP_CLOSE, bl2.nactvar, 0, 0); | 1471 | luaK_codeABC(fs, OP_CLOSE, stacklevel(fs, bl2.nactvar), 0, 0); |
| 1436 | condexit = luaK_jump(fs); /* repeat after closing upvalues */ | 1472 | condexit = luaK_jump(fs); /* repeat after closing upvalues */ |
| 1437 | luaK_patchtohere(fs, exit); /* normal exit comes to here */ | 1473 | luaK_patchtohere(fs, exit); /* normal exit comes to here */ |
| 1438 | } | 1474 | } |
| @@ -1532,7 +1568,6 @@ static void forlist (LexState *ls, TString *indexname) { | |||
| 1532 | /* create control variables */ | 1568 | /* create control variables */ |
| 1533 | new_localvarliteral(ls, "(for generator)"); | 1569 | new_localvarliteral(ls, "(for generator)"); |
| 1534 | new_localvarliteral(ls, "(for state)"); | 1570 | new_localvarliteral(ls, "(for state)"); |
| 1535 | markupval(fs, fs->nactvar); /* state may create an upvalue */ | ||
| 1536 | new_localvarliteral(ls, "(for control)"); | 1571 | new_localvarliteral(ls, "(for control)"); |
| 1537 | new_localvarliteral(ls, "(for toclose)"); | 1572 | new_localvarliteral(ls, "(for toclose)"); |
| 1538 | /* create declared variables */ | 1573 | /* create declared variables */ |
| @@ -1545,6 +1580,7 @@ static void forlist (LexState *ls, TString *indexname) { | |||
| 1545 | line = ls->linenumber; | 1580 | line = ls->linenumber; |
| 1546 | adjust_assign(ls, 4, explist(ls, &e), &e); | 1581 | adjust_assign(ls, 4, explist(ls, &e), &e); |
| 1547 | adjustlocalvars(ls, 4); /* control variables */ | 1582 | adjustlocalvars(ls, 4); /* control variables */ |
| 1583 | markupval(fs, luaY_nvarstack(fs)); /* state may create an upvalue */ | ||
| 1548 | luaK_checkstack(fs, 3); /* extra space to call generator */ | 1584 | luaK_checkstack(fs, 3); /* extra space to call generator */ |
| 1549 | forbody(ls, base, line, nvars - 4, 1); | 1585 | forbody(ls, base, line, nvars - 4, 1); |
| 1550 | } | 1586 | } |
| @@ -1587,7 +1623,8 @@ static int issinglejump (LexState *ls, TString **label, int *target) { | |||
| 1587 | TString *lname = ls->lookahead.seminfo.ts; /* label's id */ | 1623 | TString *lname = ls->lookahead.seminfo.ts; /* label's id */ |
| 1588 | Labeldesc *lb = findlabel(ls, lname); | 1624 | Labeldesc *lb = findlabel(ls, lname); |
| 1589 | if (lb) { /* a backward jump? */ | 1625 | if (lb) { /* a backward jump? */ |
| 1590 | if (ls->fs->nactvar > lb->nactvar) /* needs to close variables? */ | 1626 | /* does it need to close variables? */ |
| 1627 | if (luaY_nvarstack(ls->fs) > stacklevel(ls->fs, lb->nactvar)) | ||
| 1591 | return 0; /* not a single jump; cannot optimize */ | 1628 | return 0; /* not a single jump; cannot optimize */ |
| 1592 | *target = lb->pc; | 1629 | *target = lb->pc; |
| 1593 | } | 1630 | } |
| @@ -1659,11 +1696,12 @@ static void ifstat (LexState *ls, int line) { | |||
| 1659 | static void localfunc (LexState *ls) { | 1696 | static void localfunc (LexState *ls) { |
| 1660 | expdesc b; | 1697 | expdesc b; |
| 1661 | FuncState *fs = ls->fs; | 1698 | FuncState *fs = ls->fs; |
| 1699 | int fvar = fs->nactvar; /* function's variable index */ | ||
| 1662 | new_localvar(ls, str_checkname(ls)); /* new local variable */ | 1700 | new_localvar(ls, str_checkname(ls)); /* new local variable */ |
| 1663 | adjustlocalvars(ls, 1); /* enter its scope */ | 1701 | adjustlocalvars(ls, 1); /* enter its scope */ |
| 1664 | body(ls, &b, 0, ls->linenumber); /* function created in next register */ | 1702 | body(ls, &b, 0, ls->linenumber); /* function created in next register */ |
| 1665 | /* debug information will only see the variable after this point! */ | 1703 | /* debug information will only see the variable after this point! */ |
| 1666 | localdebuginfo(fs, b.u.info)->startpc = fs->pc; | 1704 | localdebuginfo(fs, fvar)->startpc = fs->pc; |
| 1667 | } | 1705 | } |
| 1668 | 1706 | ||
| 1669 | 1707 | ||
| @@ -1687,9 +1725,10 @@ static int getlocalattribute (LexState *ls) { | |||
| 1687 | static void checktoclose (LexState *ls, int toclose) { | 1725 | static void checktoclose (LexState *ls, int toclose) { |
| 1688 | if (toclose != -1) { /* is there a to-be-closed variable? */ | 1726 | if (toclose != -1) { /* is there a to-be-closed variable? */ |
| 1689 | FuncState *fs = ls->fs; | 1727 | FuncState *fs = ls->fs; |
| 1690 | markupval(fs, fs->nactvar + toclose + 1); | 1728 | int level = luaY_nvarstack(fs) + toclose; |
| 1729 | markupval(fs, level + 1); | ||
| 1691 | fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */ | 1730 | fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */ |
| 1692 | luaK_codeABC(fs, OP_TBC, fs->nactvar + toclose, 0, 0); | 1731 | luaK_codeABC(fs, OP_TBC, level, 0, 0); |
| 1693 | } | 1732 | } |
| 1694 | } | 1733 | } |
| 1695 | 1734 | ||
| @@ -1773,7 +1812,7 @@ static void retstat (LexState *ls) { | |||
| 1773 | FuncState *fs = ls->fs; | 1812 | FuncState *fs = ls->fs; |
| 1774 | expdesc e; | 1813 | expdesc e; |
| 1775 | int nret; /* number of values being returned */ | 1814 | int nret; /* number of values being returned */ |
| 1776 | int first = fs->nactvar; /* first slot to be returned */ | 1815 | int first = luaY_nvarstack(fs); /* first slot to be returned */ |
| 1777 | if (block_follow(ls, 1) || ls->t.token == ';') | 1816 | if (block_follow(ls, 1) || ls->t.token == ';') |
| 1778 | nret = 0; /* return no values */ | 1817 | nret = 0; /* return no values */ |
| 1779 | else { | 1818 | else { |
| @@ -1782,7 +1821,7 @@ static void retstat (LexState *ls) { | |||
| 1782 | luaK_setmultret(fs, &e); | 1821 | luaK_setmultret(fs, &e); |
| 1783 | if (e.k == VCALL && nret == 1 && !fs->bl->insidetbc) { /* tail call? */ | 1822 | if (e.k == VCALL && nret == 1 && !fs->bl->insidetbc) { /* tail call? */ |
| 1784 | SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL); | 1823 | SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL); |
| 1785 | lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar); | 1824 | lua_assert(GETARG_A(getinstruction(fs,&e)) == luaY_nvarstack(fs)); |
| 1786 | } | 1825 | } |
| 1787 | nret = LUA_MULTRET; /* return all values */ | 1826 | nret = LUA_MULTRET; /* return all values */ |
| 1788 | } | 1827 | } |
| @@ -1867,8 +1906,8 @@ static void statement (LexState *ls) { | |||
| 1867 | } | 1906 | } |
| 1868 | } | 1907 | } |
| 1869 | lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && | 1908 | lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && |
| 1870 | ls->fs->freereg >= ls->fs->nactvar); | 1909 | ls->fs->freereg >= luaY_nvarstack(ls->fs)); |
| 1871 | ls->fs->freereg = ls->fs->nactvar; /* free registers */ | 1910 | ls->fs->freereg = luaY_nvarstack(ls->fs); /* free registers */ |
| 1872 | leavelevel(ls); | 1911 | leavelevel(ls); |
| 1873 | } | 1912 | } |
| 1874 | 1913 | ||
| @@ -83,19 +83,24 @@ typedef struct expdesc { | |||
| 83 | 83 | ||
| 84 | /* description of an active local variable */ | 84 | /* description of an active local variable */ |
| 85 | typedef struct Vardesc { | 85 | typedef struct Vardesc { |
| 86 | TValuefields; /* constant value (if variable is 'const') */ | 86 | TValuefields; /* constant value (if it is a compile-time constant) */ |
| 87 | lu_byte ro; /* true if variable is 'const' */ | 87 | lu_byte ro; /* true if variable is 'const' */ |
| 88 | lu_byte sidx; /* index of the variable in the stack */ | 88 | lu_byte sidx; /* index of the variable in the stack */ |
| 89 | short pidx; /* index of the variable in the Proto's 'locvars' array */ | 89 | short pidx; /* index of the variable in the Proto's 'locvars' array */ |
| 90 | TString *name; /* variable name */ | ||
| 90 | } Vardesc; | 91 | } Vardesc; |
| 91 | 92 | ||
| 92 | 93 | ||
| 94 | /* check whether Vardesc is in the stack (not a compile-time constant) */ | ||
| 95 | #define vdinstack(vd) (ttisnil(vd)) | ||
| 96 | |||
| 97 | |||
| 93 | /* description of pending goto statements and label statements */ | 98 | /* description of pending goto statements and label statements */ |
| 94 | typedef struct Labeldesc { | 99 | typedef struct Labeldesc { |
| 95 | TString *name; /* label identifier */ | 100 | TString *name; /* label identifier */ |
| 96 | int pc; /* position in code */ | 101 | int pc; /* position in code */ |
| 97 | int line; /* line where it appeared */ | 102 | int line; /* line where it appeared */ |
| 98 | lu_byte nactvar; /* local level where it appears in current block */ | 103 | lu_byte nactvar; /* number of active variables in that position */ |
| 99 | lu_byte close; /* goto that escapes upvalues */ | 104 | lu_byte close; /* goto that escapes upvalues */ |
| 100 | } Labeldesc; | 105 | } Labeldesc; |
| 101 | 106 | ||
| @@ -138,7 +143,7 @@ typedef struct FuncState { | |||
| 138 | int nabslineinfo; /* number of elements in 'abslineinfo' */ | 143 | int nabslineinfo; /* number of elements in 'abslineinfo' */ |
| 139 | int firstlocal; /* index of first local var (in Dyndata array) */ | 144 | int firstlocal; /* index of first local var (in Dyndata array) */ |
| 140 | int firstlabel; /* index of first label (in 'dyd->label->arr') */ | 145 | int firstlabel; /* index of first label (in 'dyd->label->arr') */ |
| 141 | short nlocvars; /* number of elements in 'f->locvars' */ | 146 | short ndebugvars; /* number of elements in 'f->locvars' */ |
| 142 | lu_byte nactvar; /* number of active local variables */ | 147 | lu_byte nactvar; /* number of active local variables */ |
| 143 | lu_byte nups; /* number of upvalues */ | 148 | lu_byte nups; /* number of upvalues */ |
| 144 | lu_byte freereg; /* first free register */ | 149 | lu_byte freereg; /* first free register */ |
| @@ -147,6 +152,7 @@ typedef struct FuncState { | |||
| 147 | } FuncState; | 152 | } FuncState; |
| 148 | 153 | ||
| 149 | 154 | ||
| 155 | LUAI_FUNC int luaY_nvarstack (FuncState *fs); | ||
| 150 | LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, | 156 | LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, |
| 151 | Dyndata *dyd, const char *name, int firstchar); | 157 | Dyndata *dyd, const char *name, int firstchar); |
| 152 | 158 | ||
