瀏覽代碼

new instructions to optimize indexing on upvalues

Roberto Ierusalimschy 15 年之前
父節點
當前提交
0fe2576a39
共有 8 個文件被更改,包括 89 次插入31 次删除
  1. 20 2
      lcode.c
  2. 2 1
      lcode.h
  3. 26 9
      ldebug.c
  4. 5 1
      lopcodes.c
  5. 3 1
      lopcodes.h
  6. 14 9
      lparser.c
  7. 6 5
      lparser.h
  8. 13 3
      lvm.c

+ 20 - 2
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 2.42 2009/09/23 20:33:05 roberto Exp roberto $
+** $Id: lcode.c,v 2.43 2010/01/11 17:38:30 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -384,6 +384,12 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
       e->k = VRELOCABLE;
       break;
     }
+    case VINDEXEDUP: {
+      freereg(fs, e->u.s.aux);
+      e->u.s.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.s.info, e->u.s.aux);
+      e->k = VRELOCABLE;
+      break;
+    }
     case VVARARG:
     case VCALL: {
       luaK_setoneret(fs, e);
@@ -493,6 +499,12 @@ int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
 }
 
 
+void luaK_exp2anyregup (FuncState *fs, expdesc *e) {
+  if (e->k != VUPVAL || hasjumps(e))
+    luaK_exp2anyreg(fs, e);
+}
+
+
 void luaK_exp2val (FuncState *fs, expdesc *e) {
   if (hasjumps(e))
     luaK_exp2anyreg(fs, e);
@@ -553,6 +565,11 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
       luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);
       break;
     }
+    case VINDEXEDUP: {
+      int e = luaK_exp2RK(fs, ex);
+      luaK_codeABC(fs, OP_SETTABUP, var->u.s.info, var->u.s.aux, e);
+      break;
+    }
     default: {
       lua_assert(0);  /* invalid var kind to store */
       break;
@@ -695,8 +712,9 @@ static void codenot (FuncState *fs, expdesc *e) {
 
 
 void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
+  lua_assert(!hasjumps(t));
   t->u.s.aux = luaK_exp2RK(fs, k);
-  t->k = VINDEXED;
+  t->k = (t->k == VUPVAL) ? VINDEXEDUP : VINDEXED;
 }
 
 

+ 2 - 1
lcode.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.h,v 1.51 2009/06/18 16:35:05 roberto Exp roberto $
+** $Id: lcode.h,v 1.52 2009/09/23 20:33:05 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -57,6 +57,7 @@ LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);
 LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r);
 LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
 LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
+LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e);
 LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);
 LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);
 LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);

+ 26 - 9
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.62 2010/01/11 17:37:59 roberto Exp roberto $
+** $Id: ldebug.c,v 2.63 2010/01/13 16:18:25 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -270,12 +270,10 @@ static const char *kname (Proto *p, int c) {
 
 static const char *getobjname (lua_State *L, CallInfo *ci, int reg,
                                const char **name) {
-  Proto *p;
-  int lastpc, pc;
+  Proto *p = ci_func(ci)->l.p;
   const char *what = NULL;
-  lua_assert(isLua(ci));
-  p = ci_func(ci)->l.p;
-  lastpc = currentpc(ci);
+  int lastpc = currentpc(ci);
+  int pc;
   *name = luaF_getlocalname(p, reg + 1, lastpc);
   if (*name)  /* is a local? */
     return "local";
@@ -305,6 +303,7 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int reg,
         }
         break;
       }
+      case OP_GETTABUP:
       case OP_GETTABLE: {
         if (reg == a) {
           int k = GETARG_C(i);  /* key index */
@@ -378,6 +377,7 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
       return getobjname(L, ci, GETARG_A(i), name);
     case OP_GETGLOBAL:
     case OP_SELF:
+    case OP_GETTABUP:
     case OP_GETTABLE: tm = TM_INDEX; break;
     case OP_SETGLOBAL:
     case OP_SETTABLE: tm = TM_NEWINDEX; break;
@@ -413,13 +413,30 @@ static int isinstack (CallInfo *ci, const TValue *o) {
 }
 
 
+static const char *getupvalname (CallInfo *ci, const TValue *o,
+                               const char **name) {
+  LClosure *c = &ci_func(ci)->l;
+  int i;
+  for (i = 0; i < c->nupvalues; i++) {
+    if (c->upvals[i]->v == o) {
+      *name = getstr(c->p->upvalues[i].name);
+      return "upvalue";
+    }
+  }
+  return NULL;
+}
+
+
 void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
   CallInfo *ci = L->ci;
   const char *name = NULL;
   const char *t = typename(ttype(o));
-  const char *kind = (isLua(ci) && isinstack(ci, o)) ?
-                         getobjname(L, ci, cast_int(o - ci->u.l.base), &name) :
-                         NULL;
+  const char *kind = NULL;
+  if (isLua(ci)) {
+    kind = getupvalname(ci, o, &name);  /* check whether 'o' is an upvalue */
+    if (!kind && isinstack(ci, o))  /* no? try a register */ 
+      kind = getobjname(L, ci, cast_int(o - ci->u.l.base), &name);
+  }
   if (kind)
     luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)",
                 op, kind, name, t);

+ 5 - 1
lopcodes.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.c,v 1.40 2008/10/30 15:39:30 roberto Exp roberto $
+** $Id: lopcodes.c,v 1.41 2009/11/19 19:06:52 roberto Exp roberto $
 ** See Copyright Notice in lua.h
 */
 
@@ -20,8 +20,10 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
   "LOADNIL",
   "GETUPVAL",
   "GETGLOBAL",
+  "GETTABUP",
   "GETTABLE",
   "SETGLOBAL",
+  "SETTABUP",
   "SETUPVAL",
   "SETTABLE",
   "NEWTABLE",
@@ -68,8 +70,10 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
  ,opmode(0, 1, OpArgR, OpArgN, iABC)		/* OP_LOADNIL */
  ,opmode(0, 1, OpArgU, OpArgN, iABC)		/* OP_GETUPVAL */
  ,opmode(0, 1, OpArgK, OpArgN, iABx)		/* OP_GETGLOBAL */
+ ,opmode(0, 1, OpArgU, OpArgK, iABC)		/* OP_GETTABUP */
  ,opmode(0, 1, OpArgR, OpArgK, iABC)		/* OP_GETTABLE */
  ,opmode(0, 0, OpArgK, OpArgN, iABx)		/* OP_SETGLOBAL */
+ ,opmode(0, 0, OpArgK, OpArgK, iABC)		/* OP_SETTABUP */
  ,opmode(0, 0, OpArgU, OpArgN, iABC)		/* OP_SETUPVAL */
  ,opmode(0, 0, OpArgK, OpArgK, iABC)		/* OP_SETTABLE */
  ,opmode(0, 1, OpArgU, OpArgU, iABC)		/* OP_NEWTABLE */

+ 3 - 1
lopcodes.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.132 2009/10/28 12:20:07 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.133 2009/11/19 19:06:52 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -172,9 +172,11 @@ OP_LOADNIL,/*	A B	R(A) := ... := R(B) := nil			*/
 OP_GETUPVAL,/*	A B	R(A) := UpValue[B]				*/
 
 OP_GETGLOBAL,/*	A Bx	R(A) := Gbl[Kst(Bx - 1)]			*/
+OP_GETTABUP,/*	A B C	R(A) := UpValue[B][RK(C)]			*/
 OP_GETTABLE,/*	A B C	R(A) := R(B)[RK(C)]				*/
 
 OP_SETGLOBAL,/*	A Bx	Gbl[Kst(Bx - 1)] := R(A)			*/
+OP_SETTABUP,/*	A B C	UpValue[A][RK(B)] := RK(C)			*/
 OP_SETUPVAL,/*	A B	UpValue[B] := R(A)				*/
 OP_SETTABLE,/*	A B C	R(A)[RK(B)] := RK(C)				*/
 

+ 14 - 9
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 2.74 2010/01/05 18:46:58 roberto Exp roberto $
+** $Id: lparser.c,v 2.75 2010/01/06 11:48:02 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -452,7 +452,7 @@ static void fieldsel (LexState *ls, expdesc *v) {
   /* fieldsel -> ['.' | ':'] NAME */
   FuncState *fs = ls->fs;
   expdesc key;
-  luaK_exp2anyreg(fs, v);
+  luaK_exp2anyregup(fs, v);
   luaX_next(ls);  /* skip the dot or colon */
   checkname(ls, &key);
   luaK_indexed(fs, v, &key);
@@ -747,7 +747,7 @@ static void primaryexp (LexState *ls, expdesc *v) {
       }
       case '[': {  /* `[' exp1 `]' */
         expdesc key;
-        luaK_exp2anyreg(fs, v);
+        luaK_exp2anyregup(fs, v);
         yindex(ls, &key);
         luaK_indexed(fs, v, &key);
         break;
@@ -951,24 +951,27 @@ struct LHS_assign {
 ** local value in a safe place and use this safe copy in the previous
 ** assignment.
 */
-static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
+static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v,
+                            expkind ix, OpCode op) {
   FuncState *fs = ls->fs;
   int extra = fs->freereg;  /* eventual position to save local variable */
   int conflict = 0;
   for (; lh; lh = lh->prev) {
-    if (lh->v.k == VINDEXED) {
+    if (lh->v.k == ix) {
       if (lh->v.u.s.info == v->u.s.info) {  /* conflict? */
         conflict = 1;
+        lh->v.k = VINDEXED;
         lh->v.u.s.info = extra;  /* previous assignment will use safe copy */
       }
-      if (lh->v.u.s.aux == v->u.s.info) {  /* conflict? */
+      if (v->k == VLOCAL && lh->v.u.s.aux == v->u.s.info) {  /* conflict? */
         conflict = 1;
+        lua_assert(lh->v.k == VINDEXED);
         lh->v.u.s.aux = extra;  /* previous assignment will use safe copy */
       }
     }
   }
   if (conflict) {
-    luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0);  /* make copy */
+    luaK_codeABC(fs, op, fs->freereg, v->u.s.info, 0);  /* make copy */
     luaK_reserveregs(fs, 1);
   }
 }
@@ -976,14 +979,16 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
 
 static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
   expdesc e;
-  check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,
+  check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXEDUP,
                       "syntax error");
   if (testnext(ls, ',')) {  /* assignment -> `,' primaryexp assignment */
     struct LHS_assign nv;
     nv.prev = lh;
     primaryexp(ls, &nv.v);
     if (nv.v.k == VLOCAL)
-      check_conflict(ls, lh, &nv.v);
+      check_conflict(ls, lh, &nv.v, VINDEXED, OP_MOVE);
+    else if (nv.v.k == VUPVAL)
+      check_conflict(ls, lh, &nv.v, VINDEXEDUP, OP_GETUPVAL);
     checklimit(ls->fs, nvars, LUAI_MAXCCALLS - G(ls->L)->nCcalls,
                     "variable names");
     assignment(ls, &nv, nvars+1);

+ 6 - 5
lparser.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.h,v 1.60 2009/09/30 15:38:37 roberto Exp roberto $
+** $Id: lparser.h,v 1.61 2009/10/11 20:02:19 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -23,10 +23,11 @@ typedef enum {
   VFALSE,
   VK,		/* info = index of constant in `k' */
   VKNUM,	/* nval = numerical value */
-  VLOCAL,	/* info = local register; aux = read only */
-  VUPVAL,       /* info = index of upvalue in 'upvalues'; aux = read only */
-  VGLOBAL,	/* info = index of table; aux = index of global name in `k' */
-  VINDEXED,	/* info = table register; aux = index register (or `k') */
+  VLOCAL,	/* info = local register */
+  VUPVAL,       /* info = index of upvalue in 'upvalues' */
+  VGLOBAL,	/* info =  index of global name in 'k' */
+  VINDEXED,	/* info = table R/K; aux = index R/K */
+  VINDEXEDUP,	/* info = table upvalue; aux = R/K */
   VJMP,		/* info = instruction pc */
   VRELOCABLE,	/* info = instruction pc */
   VNONRELOC,	/* info = result register */

+ 13 - 3
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.102 2009/12/17 16:20:01 roberto Exp roberto $
+** $Id: lvm.c,v 2.103 2010/01/15 16:23:58 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -362,7 +362,7 @@ void luaV_finishOp (lua_State *L) {
   switch (op) {  /* finish its execution */
     case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:
     case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN:
-    case OP_GETGLOBAL: case OP_GETTABLE: case OP_SELF: {
+    case OP_GETGLOBAL: case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: {
       setobjs2s(L, base + GETARG_A(inst), --L->top);
       break;
     }
@@ -403,7 +403,7 @@ void luaV_finishOp (lua_State *L) {
         L->top = ci->top;  /* adjust results */
       break;
     }
-    case OP_TAILCALL: case OP_SETGLOBAL: case OP_SETTABLE:
+    case OP_TAILCALL: case OP_SETGLOBAL: case OP_SETTABUP:  case OP_SETTABLE:
       break;
     default: lua_assert(0);
   }
@@ -504,6 +504,11 @@ void luaV_execute (lua_State *L) {
         Protect(luaV_gettable(L, &g, rb, ra));
         continue;
       }
+      case OP_GETTABUP: {
+        int b = GETARG_B(i);
+        Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));
+        continue;
+      }
       case OP_GETTABLE: {
         Protect(luaV_gettable(L, RB(i), RKC(i), ra));
         continue;
@@ -516,6 +521,11 @@ void luaV_execute (lua_State *L) {
         Protect(luaV_settable(L, &g, rb, ra));
         continue;
       }
+      case OP_SETTABUP: {
+        int a = GETARG_A(i);
+        Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i)));
+        continue;
+      }
       case OP_SETUPVAL: {
         UpVal *uv = cl->upvals[GETARG_B(i)];
         setobj(L, uv->v, ra);