diff --git a/lapi.c b/lapi.c index 6e3ef852..27fa5247 100644 --- a/lapi.c +++ b/lapi.c @@ -29,7 +29,6 @@ #include "ltm.h" #include "lundump.h" #include "lvm.h" -#include "lcmd.h" @@ -1136,27 +1135,6 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, setobj(L, f->upvals[0]->v.p, >); luaC_barrier(L, f->upvals[0], >); } - if (f->nupvalues >= LUSH_NUM_UPVALS) { /* has lush upvalues? */ - /* populate shell function upvalues from registry */ - Table *regt = hvalue(&G(L)->l_registry); - TValue lushtv; - lu_byte tag = luaH_getint(regt, LUA_RIDX_LUSH, &lushtv); - if (novariant(tag) == LUA_TTABLE) { - static const char *const fields[] = { - "command", "interactive", "getenv", "setenv" - }; - Table *lusht = hvalue(&lushtv); - int i; - for (i = 0; i < 4; i++) { - TValue val; - TString *key = luaS_new(L, fields[i]); - if (luaH_getstr(lusht, key, &val) != LUA_TNIL) { - setobj(L, f->upvals[i + 1]->v.p, &val); - luaC_barrier(L, f->upvals[i + 1], &val); - } - } - } - } } lua_unlock(L); return APIstatus(status); diff --git a/lcmd.h b/lcmd.h index 9954aac0..e5b8fb48 100644 --- a/lcmd.h +++ b/lcmd.h @@ -9,13 +9,12 @@ #include "lua.h" -/* Upvalue indices for shell functions on the main chunk. -** Index 0 is _ENV (standard). Indices 1-4 are lush shell functions. */ -#define LUSH_UPVAL_COMMAND 1 -#define LUSH_UPVAL_INTERACTIVE 2 -#define LUSH_UPVAL_GETENV 3 -#define LUSH_UPVAL_SETENV 4 -#define LUSH_NUM_UPVALS 5 /* total: _ENV(0) + 4 shell functions */ +/* OP_LUSH sub-operation indices (B operand selects which function) */ +#define LUSH_OP_COMMAND 0 +#define LUSH_OP_INTERACTIVE 1 +#define LUSH_OP_GETENV 2 +#define LUSH_OP_SETENV 3 +#define LUSH_OP_COUNT 4 int lushCmd_command (lua_State *L); int lushCmd_interactive (lua_State *L); diff --git a/linit.c b/linit.c index 456415ad..04e56fe7 100644 --- a/linit.c +++ b/linit.c @@ -45,18 +45,19 @@ static const luaL_Reg stdlibs[] = { /* ** Store shell functions in a registry table at LUA_RIDX_LUSH. -** These are populated as upvalues on the main chunk by lua_load(). +** Integer keys 1..4 hold the C functions (accessed by OP_LUSH). +** String key "builtins" holds the builtins table (set by luaopen_builtins). */ static void opencommand (lua_State *L) { - lua_createtable(L, 0, 5); + lua_createtable(L, LUSH_OP_COUNT, 1); lua_pushcfunction(L, lushCmd_command); - lua_setfield(L, -2, "command"); + lua_rawseti(L, -2, LUSH_OP_COMMAND + 1); lua_pushcfunction(L, lushCmd_interactive); - lua_setfield(L, -2, "interactive"); + lua_rawseti(L, -2, LUSH_OP_INTERACTIVE + 1); lua_pushcfunction(L, lushCmd_getenv); - lua_setfield(L, -2, "getenv"); + lua_rawseti(L, -2, LUSH_OP_GETENV + 1); lua_pushcfunction(L, lushCmd_setenv); - lua_setfield(L, -2, "setenv"); + lua_rawseti(L, -2, LUSH_OP_SETENV + 1); lua_rawseti(L, LUA_REGISTRYINDEX, LUA_RIDX_LUSH); } diff --git a/ljumptab.h b/ljumptab.h index 52fa6d74..376b274b 100644 --- a/ljumptab.h +++ b/ljumptab.h @@ -106,6 +106,7 @@ static const void *const disptab[NUM_OPCODES] = { &&L_OP_SETLIST, &&L_OP_CLOSURE, &&L_OP_VARARG, +&&L_OP_LUSH, &&L_OP_GETVARG, &&L_OP_ERRNNIL, &&L_OP_VARARGPREP, diff --git a/lopcodes.c b/lopcodes.c index 7e182315..d5005b90 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -102,6 +102,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 0, 1, 0, 0, ivABC) /* OP_SETLIST */ ,opmode(0, 0, 0, 0, 1, iABx) /* OP_CLOSURE */ ,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */ + ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LUSH */ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETVARG */ ,opmode(0, 0, 0, 0, 0, iABx) /* OP_ERRNNIL */ ,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */ diff --git a/lopcodes.h b/lopcodes.h index f7bded2c..d29bccc4 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -338,6 +338,8 @@ OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */ OP_VARARG,/* A C R[A], R[A+1], ..., R[A+C-2] = vararg */ +OP_LUSH,/* A B R[A] := lush_func[B] */ + OP_GETVARG, /* A B C R[A] := R[B][R[C]], R[B] is vararg parameter */ OP_ERRNNIL,/* A Bx raise error if R[A] ~= nil (K[Bx] is global name)*/ diff --git a/lopnames.h b/lopnames.h index 0554a2e9..0574ca74 100644 --- a/lopnames.h +++ b/lopnames.h @@ -94,6 +94,7 @@ static const char *const opnames[] = { "SETLIST", "CLOSURE", "VARARG", + "LUSH", "GETVARG", "ERRNNIL", "VARARGPREP", diff --git a/lparser.c b/lparser.c index 897ff5b2..9cc166c7 100644 --- a/lparser.c +++ b/lparser.c @@ -501,15 +501,14 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { /* -** Look up a lush shell function (e.g. __command) that is registered -** as an upvalue on the main chunk. singlevaraux will find it directly -** as VUPVAL, emitting OP_GETUPVAL instead of OP_GETTABUP. +** Emit OP_LUSH to load a shell C function into a register. +** 'lushop' selects which function (LUSH_OP_COMMAND, etc.). */ -static void buildlushvar (LexState *ls, TString *varname, expdesc *var) { - FuncState *fs = ls->fs; - init_exp(var, VGLOBAL, -1); - singlevaraux(fs, varname, var, 1); - lua_assert(var->k == VUPVAL); /* must be found as upvalue */ +static void codelushfunc (FuncState *fs, int lushop, expdesc *var) { + int reg = fs->freereg; + luaK_reserveregs(fs, 1); + init_exp(var, VNONRELOC, reg); + luaK_codeABC(fs, OP_LUSH, reg, lushop, 0); } @@ -564,11 +563,8 @@ static void codecommand (LexState *ls, expdesc *v, expdesc *cmdstr) { FuncState *fs = ls->fs; int base, line; expdesc func; - TString *cmdname = luaX_newstring(ls, "__command", 9); line = ls->linenumber; - /* look up __command as upvalue */ - buildlushvar(ls, cmdname, &func); - luaK_exp2nextreg(fs, &func); + codelushfunc(fs, LUSH_OP_COMMAND, &func); base = func.u.info; /* push the command string argument */ luaK_exp2nextreg(fs, cmdstr); @@ -1254,11 +1250,9 @@ static void commandexp (LexState *ls, expdesc *v) { expdesc func, cmdstr; int base, nconcat = 0; int line = ls->linenumber; - TString *cmdname = luaX_newstring(ls, "__command", 9); TString *tsname = luaX_newstring(ls, "tostring", 8); /* load __command function first so it occupies the base register */ - buildlushvar(ls, cmdname, &func); - luaK_exp2nextreg(fs, &func); + codelushfunc(fs, LUSH_OP_COMMAND, &func); base = func.u.info; /* load the first fragment */ codestring(&cmdstr, ls->t.seminfo.ts); @@ -1320,10 +1314,8 @@ static void codeenvget (LexState *ls, expdesc *v, TString *name) { FuncState *fs = ls->fs; int base, line; expdesc func, arg; - TString *fname = luaX_newstring(ls, "__getenv", 8); line = ls->linenumber; - buildlushvar(ls, fname, &func); - luaK_exp2nextreg(fs, &func); + codelushfunc(fs, LUSH_OP_GETENV, &func); base = func.u.info; codestring(&arg, name); luaK_exp2nextreg(fs, &arg); @@ -2202,13 +2194,10 @@ static void envstat (LexState *ls) { TString *name = ls->t.seminfo.ts; int base, line; expdesc func, arg, val; - TString *fname; line = ls->linenumber; luaX_next(ls); /* skip TK_ENVVAR */ checknext(ls, '='); - fname = luaX_newstring(ls, "__setenv", 8); - buildlushvar(ls, fname, &func); - luaK_exp2nextreg(fs, &func); + codelushfunc(fs, LUSH_OP_SETENV, &func); base = func.u.info; codestring(&arg, name); luaK_exp2nextreg(fs, &arg); @@ -2231,10 +2220,8 @@ static void interactivestat (LexState *ls) { /* simple interactive command, no interpolation */ int base, line; expdesc func, cmdstr, v; - TString *fname = luaX_newstring(ls, "__interactive", 13); line = ls->linenumber; - buildlushvar(ls, fname, &func); - luaK_exp2nextreg(fs, &func); + codelushfunc(fs, LUSH_OP_INTERACTIVE, &func); base = func.u.info; codestring(&cmdstr, ls->t.seminfo.ts); luaK_exp2nextreg(fs, &cmdstr); @@ -2248,10 +2235,8 @@ static void interactivestat (LexState *ls) { expdesc func, cmdstr, v; int base, nconcat = 0; int line = ls->linenumber; - TString *fname = luaX_newstring(ls, "__interactive", 13); TString *tsname = luaX_newstring(ls, "tostring", 8); - buildlushvar(ls, fname, &func); - luaK_exp2nextreg(fs, &func); + codelushfunc(fs, LUSH_OP_INTERACTIVE, &func); base = func.u.info; /* load the first fragment */ codestring(&cmdstr, ls->t.seminfo.ts); @@ -2410,12 +2395,8 @@ static void statement (LexState *ls) { ** upvalue named LUA_ENV */ static void mainfunc (LexState *ls, FuncState *fs) { - static const char *const lush_upval_names[] = { - "__command", "__interactive", "__getenv", "__setenv" - }; BlockCnt bl; Upvaldesc *env; - int i; open_func(ls, fs, &bl); setvararg(fs, PF_ISVARARG); /* main function is always vararg */ env = allocupvalue(fs); /* ...set environment upvalue */ @@ -2424,15 +2405,6 @@ static void mainfunc (LexState *ls, FuncState *fs) { env->kind = VDKREG; env->name = ls->envn; luaC_objbarrier(ls->L, fs->f, env->name); - /* allocate upvalues for lush shell functions */ - for (i = 0; i < 4; i++) { - Upvaldesc *uv = allocupvalue(fs); - uv->instack = 1; - uv->idx = 0; - uv->kind = VDKREG; - uv->name = luaS_new(ls->L, lush_upval_names[i]); - luaC_objbarrier(ls->L, fs->f, uv->name); - } luaX_next(ls); /* read first token */ statlist(ls); /* parse main body */ check(ls, TK_EOS); @@ -2444,7 +2416,7 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, Dyndata *dyd, const char *name, int firstchar) { LexState lexstate; FuncState funcstate; - LClosure *cl = luaF_newLclosure(L, LUSH_NUM_UPVALS); /* create main closure */ + LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */ setclLvalue2s(L, L->top.p, cl); /* anchor it (to avoid being collected) */ luaD_inctop(L); lexstate.h = luaH_new(L); /* create table for scanner */ @@ -2459,7 +2431,7 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); mainfunc(&lexstate, &funcstate); - lua_assert(!funcstate.prev && funcstate.nups == LUSH_NUM_UPVALS && !lexstate.fs); + 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); L->top.p--; /* remove scanner's table */ diff --git a/lvm.c b/lvm.c index 2c868c21..70747503 100644 --- a/lvm.c +++ b/lvm.c @@ -1939,6 +1939,19 @@ void luaV_execute (lua_State *L, CallInfo *ci) { Protect(luaT_getvarargs(L, ci, ra, n)); vmbreak; } + vmcase(OP_LUSH) { + StkId ra = RA(i); + int idx = GETARG_B(i); + Table *regt = hvalue(&G(L)->l_registry); + TValue lushtv; + lu_byte tag = luaH_getint(regt, LUA_RIDX_LUSH, &lushtv); + if (novariant(tag) == LUA_TTABLE) { + TValue func; + luaH_getint(hvalue(&lushtv), idx + 1, &func); /* 1-based */ + setobj2s(L, ra, &func); + } + vmbreak; + } vmcase(OP_GETVARG) { StkId ra = RA(i); TValue *rc = vRC(i);