浏览代码

new opcode 'PREPVARARG'
(avoids test for vararg function in all function calls)

Roberto Ierusalimschy 7 年之前
父节点
当前提交
318a9a5859
共有 7 个文件被更改,包括 50 次插入29 次删除
  1. 5 14
      ldo.c
  2. 3 1
      lopcodes.c
  3. 2 0
      lopcodes.h
  4. 16 6
      lparser.c
  5. 3 2
      ltm.c
  6. 2 2
      ltm.h
  7. 19 4
      lvm.c

+ 5 - 14
ldo.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ldo.c,v 2.189 2018/01/29 16:21:35 roberto Exp roberto $
+** $Id: ldo.c,v 2.190 2018/02/06 19:16:56 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -297,15 +297,11 @@ void luaD_hook (lua_State *L, int event, int line) {
 /*
 /*
 ** Executes a call hook for Lua functions. This function is called
 ** Executes a call hook for Lua functions. This function is called
 ** whenever 'hookmask' is not zero, so it checks whether call hooks are
 ** whenever 'hookmask' is not zero, so it checks whether call hooks are
-** active. Also, this function can be called when resuming a function,
-** so it checks whether the function is in its first instruction.
+** active.
 */
 */
 void luaD_hookcall (lua_State *L, CallInfo *ci) {
 void luaD_hookcall (lua_State *L, CallInfo *ci) {
-  Proto *p = clLvalue(s2v(ci->func))->p;
   int hook = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL : LUA_HOOKCALL;
   int hook = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL : LUA_HOOKCALL;
-  ci->u.l.trap = 1;  /* there may be other hooks */
-  if (!(L->hookmask & LUA_MASKCALL) ||  /* some other hook? */
-      ci->u.l.savedpc != p->code)  /* not 1st instruction? */
+  if (!(L->hookmask & LUA_MASKCALL))  /* some other hook? */
     return;  /* don't call hook */
     return;  /* don't call hook */
   L->top = ci->top;  /* prepare top */
   L->top = ci->top;  /* prepare top */
   ci->u.l.savedpc++;  /* hooks assume 'pc' is already incremented */
   ci->u.l.savedpc++;  /* hooks assume 'pc' is already incremented */
@@ -417,7 +413,7 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
   int i;
   int i;
   for (i = 0; i < narg1; i++)  /* move down function and arguments */
   for (i = 0; i < narg1; i++)  /* move down function and arguments */
     setobjs2s(L, ci->func + i, func + i);
     setobjs2s(L, ci->func + i, func + i);
-  checkstackp(L, fsize, func);
+  luaD_checkstackaux(L, fsize, (void)0, luaC_checkGC(L));
   func = ci->func;  /* moved-down function */
   func = ci->func;  /* moved-down function */
   for (; narg1 <= nfixparams; narg1++)
   for (; narg1 <= nfixparams; narg1++)
     setnilvalue(s2v(func + narg1));  /* complete missing arguments */
     setnilvalue(s2v(func + narg1));  /* complete missing arguments */
@@ -425,10 +421,7 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
   lua_assert(ci->top <= L->stack_last);
   lua_assert(ci->top <= L->stack_last);
   ci->u.l.savedpc = p->code;  /* starting point */
   ci->u.l.savedpc = p->code;  /* starting point */
   ci->callstatus |= CIST_TAIL;
   ci->callstatus |= CIST_TAIL;
-  if (p->is_vararg) {
-    L->top = func + narg1;  /* set top */
-    luaT_adjustvarargs(L, nfixparams, narg1 - 1);
-  }
+  L->top = func + narg1;  /* set top */
 }
 }
 
 
 
 
@@ -481,8 +474,6 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
       lua_assert(ci->top <= L->stack_last);
       lua_assert(ci->top <= L->stack_last);
       ci->u.l.savedpc = p->code;  /* starting point */
       ci->u.l.savedpc = p->code;  /* starting point */
       ci->callstatus = 0;
       ci->callstatus = 0;
-      if (p->is_vararg)
-        luaT_adjustvarargs(L, nfixparams, narg);  /* may invoke GC */
       luaV_execute(L, ci);  /* run the function */
       luaV_execute(L, ci);  /* run the function */
       break;
       break;
     }
     }

+ 3 - 1
lopcodes.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lopcodes.c,v 1.74 2017/12/18 17:49:31 roberto Exp $
+** $Id: lopcodes.c,v 1.75 2017/12/22 14:16:46 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -91,6 +91,7 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
   "SETLIST",
   "SETLIST",
   "CLOSURE",
   "CLOSURE",
   "VARARG",
   "VARARG",
+  "PREPVARARG",
   "EXTRAARG",
   "EXTRAARG",
   NULL
   NULL
 };
 };
@@ -171,6 +172,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
  ,opmode(0, 1, 0, 0, iABC)		/* OP_SETLIST */
  ,opmode(0, 1, 0, 0, iABC)		/* OP_SETLIST */
  ,opmode(0, 0, 0, 1, iABx)		/* OP_CLOSURE */
  ,opmode(0, 0, 0, 1, iABx)		/* OP_CLOSURE */
  ,opmode(1, 0, 0, 1, iABC)		/* OP_VARARG */
  ,opmode(1, 0, 0, 1, iABC)		/* OP_VARARG */
+ ,opmode(0, 0, 0, 1, iABC)		/* OP_PREPVARARG */
  ,opmode(0, 0, 0, 0, iAx)		/* OP_EXTRAARG */
  ,opmode(0, 0, 0, 0, iAx)		/* OP_EXTRAARG */
 };
 };
 
 

+ 2 - 0
lopcodes.h

@@ -288,6 +288,8 @@ OP_CLOSURE,/*	A Bx	R(A) := closure(KPROTO[Bx])			*/
 
 
 OP_VARARG,/*	A B C	R(A), R(A+1), ..., R(A+C-2) = vararg(B)		*/
 OP_VARARG,/*	A B C	R(A), R(A+1), ..., R(A+C-2) = vararg(B)		*/
 
 
+OP_PREPVARARG,/*A 	(adjust vararg parameters)			*/
+
 OP_EXTRAARG/*	Ax	extra (larger) argument for previous opcode	*/
 OP_EXTRAARG/*	Ax	extra (larger) argument for previous opcode	*/
 } OpCode;
 } OpCode;
 
 

+ 16 - 6
lparser.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lparser.c,v 2.174 2017/12/18 17:49:31 roberto Exp roberto $
+** $Id: lparser.c,v 2.175 2017/12/22 14:16:46 roberto Exp roberto $
 ** Lua Parser
 ** Lua Parser
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -759,12 +759,18 @@ static void constructor (LexState *ls, expdesc *t) {
 /* }====================================================================== */
 /* }====================================================================== */
 
 
 
 
+static void setvararg (FuncState *fs, int nparams) {
+  fs->f->is_vararg = 1;
+  luaK_codeABC(fs, OP_PREPVARARG, nparams, 0, 0);
+}
+
 
 
 static void parlist (LexState *ls) {
 static void parlist (LexState *ls) {
   /* parlist -> [ param { ',' param } ] */
   /* parlist -> [ param { ',' param } ] */
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
   Proto *f = fs->f;
   Proto *f = fs->f;
   int nparams = 0;
   int nparams = 0;
+  int isvararg = 0;
   if (ls->t.token != ')') {  /* is 'parlist' not empty? */
   if (ls->t.token != ')') {  /* is 'parlist' not empty? */
     do {
     do {
       switch (ls->t.token) {
       switch (ls->t.token) {
@@ -779,17 +785,21 @@ static void parlist (LexState *ls) {
             new_localvar(ls, str_checkname(ls));
             new_localvar(ls, str_checkname(ls));
           else
           else
             new_localvarliteral(ls, "_ARG");
             new_localvarliteral(ls, "_ARG");
-          f->is_vararg = 1;  /* declared vararg */
           nparams++;
           nparams++;
+          isvararg = 1;
           break;
           break;
         }
         }
         default: luaX_syntaxerror(ls, "<name> or '...' expected");
         default: luaX_syntaxerror(ls, "<name> or '...' expected");
       }
       }
-    } while (!f->is_vararg && testnext(ls, ','));
+    } while (!isvararg && testnext(ls, ','));
   }
   }
   adjustlocalvars(ls, nparams);
   adjustlocalvars(ls, nparams);
-  f->numparams = cast_byte(fs->nactvar) - f->is_vararg;
-  luaK_reserveregs(fs, fs->nactvar);  /* reserve register for parameters */
+  f->numparams = cast_byte(fs->nactvar);
+  if (isvararg) {
+    f->numparams--;  /* exclude vararg parameter */
+    setvararg(fs, f->numparams);  /* declared vararg */
+  }
+  luaK_reserveregs(fs, fs->nactvar);  /* reserve registers for parameters */
 }
 }
 
 
 
 
@@ -1692,7 +1702,7 @@ static void mainfunc (LexState *ls, FuncState *fs) {
   BlockCnt bl;
   BlockCnt bl;
   expdesc v;
   expdesc v;
   open_func(ls, fs, &bl);
   open_func(ls, fs, &bl);
-  fs->f->is_vararg = 1;  /* main function is always declared vararg */
+  setvararg(fs, 0);  /* main function is always declared vararg */
   fs->f->numparams = 0;
   fs->f->numparams = 0;
   new_localvarliteral(ls, "_ARG");
   new_localvarliteral(ls, "_ARG");
   adjustlocalvars(ls, 1);
   adjustlocalvars(ls, 1);

+ 3 - 2
ltm.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ltm.c,v 2.57 2018/01/28 12:08:04 roberto Exp roberto $
+** $Id: ltm.c,v 2.58 2018/01/28 13:39:52 roberto Exp roberto $
 ** Tag methods
 ** Tag methods
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -216,10 +216,11 @@ int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
 }
 }
 
 
 
 
-void luaT_adjustvarargs (lua_State *L, int nfixparams, int actual) {
+void luaT_adjustvarargs (lua_State *L, int nfixparams, StkId base) {
   int i;
   int i;
   Table *vtab;
   Table *vtab;
   TValue nname;
   TValue nname;
+  int actual = cast_int(L->top - base);  /* number of arguments */
   int nextra = actual - nfixparams;  /* number of extra arguments */
   int nextra = actual - nfixparams;  /* number of extra arguments */
   vtab = luaH_new(L);  /* create vararg table */
   vtab = luaH_new(L);  /* create vararg table */
   sethvalue2s(L, L->top, vtab);  /* anchor it for resizing */
   sethvalue2s(L, L->top, vtab);  /* anchor it for resizing */

+ 2 - 2
ltm.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ltm.h,v 2.28 2017/12/13 18:32:09 roberto Exp roberto $
+** $Id: ltm.h,v 2.29 2018/01/28 13:39:52 roberto Exp roberto $
 ** Tag methods
 ** Tag methods
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -77,7 +77,7 @@ LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1,
 LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
 LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
                                  int inv, TMS event);
                                  int inv, TMS event);
 
 
-LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, int actual);
+LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, StkId base);
 LUAI_FUNC void luaT_getvarargs (lua_State *L, TValue *t, StkId where,
 LUAI_FUNC void luaT_getvarargs (lua_State *L, TValue *t, StkId where,
                                 int wanted);
                                 int wanted);
 
 

+ 19 - 4
lvm.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lvm.c,v 2.336 2018/01/29 16:21:35 roberto Exp roberto $
+** $Id: lvm.c,v 2.337 2018/02/06 19:16:56 roberto Exp roberto $
 ** Lua virtual machine
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -835,12 +835,17 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
   int trap;
   int trap;
  tailcall:
  tailcall:
   trap = L->hookmask;
   trap = L->hookmask;
-  if (trap)
-    luaD_hookcall(L, ci);
   cl = clLvalue(s2v(ci->func));
   cl = clLvalue(s2v(ci->func));
   k = cl->p->k;
   k = cl->p->k;
-  base = ci->func + 1;
   pc = ci->u.l.savedpc;
   pc = ci->u.l.savedpc;
+  if (trap) {
+    if (cl->p->is_vararg)
+      trap = 0;  /* hooks will start with PREPVARARG instruction */
+    else if (pc == cl->p->code)  /* first instruction (not resuming)? */
+      luaD_hookcall(L, ci);
+    ci->u.l.trap = 1;  /* there may be other hooks */
+  }
+  base = ci->func + 1;
   /* main loop of interpreter */
   /* main loop of interpreter */
   for (;;) {
   for (;;) {
     int cond;  /* flag for conditional jumps */
     int cond;  /* flag for conditional jumps */
@@ -1701,6 +1706,16 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
         Protect(luaT_getvarargs(L, vtab, ra, n));
         Protect(luaT_getvarargs(L, vtab, ra, n));
         vmbreak;
         vmbreak;
       }
       }
+      vmcase(OP_PREPVARARG) {
+        luaT_adjustvarargs(L, GETARG_A(i), base);
+        updatetrap(ci);
+        if (trap) {
+          luaD_hookcall(L, ci);
+          L->oldpc = pc + 1;  /* next opcode will be seen as a new line */
+        }
+        updatebase(ci);
+        vmbreak;
+      }
       vmcase(OP_EXTRAARG) {
       vmcase(OP_EXTRAARG) {
         lua_assert(0);
         lua_assert(0);
         vmbreak;
         vmbreak;