浏览代码

new way to distinguish between indexing tables in registers and
tables in upvalues (+ fixed small bug when checking conflicts in
multiple assignments)

Roberto Ierusalimschy 15 年之前
父节点
当前提交
81dd13f4c6
共有 3 个文件被更改,包括 41 次插入46 次删除
  1. 12 16
      lcode.c
  2. 16 20
      lparser.c
  3. 13 10
      lparser.h

+ 12 - 16
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 2.47 2010/06/30 14:11:17 roberto Exp roberto $
+** $Id: lcode.c,v 2.48 2010/07/02 20:42:40 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -373,15 +373,13 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
       break;
     }
     case VINDEXED: {
+      OpCode op = OP_GETTABUP;  /* assume 't' is in an upvalue */
       freereg(fs, e->u.ind.idx);
-      freereg(fs, e->u.ind.t);
-      e->u.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.ind.t, e->u.ind.idx);
-      e->k = VRELOCABLE;
-      break;
-    }
-    case VINDEXEDUP: {
-      freereg(fs, e->u.ind.idx);
-      e->u.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.ind.t, e->u.ind.idx);
+      if (e->u.ind.vt == VLOCAL) {  /* 't' is in a register? */
+        freereg(fs, e->u.ind.t);
+        op = OP_GETTABLE;
+      }
+      e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx);
       e->k = VRELOCABLE;
       break;
     }
@@ -551,13 +549,9 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
       break;
     }
     case VINDEXED: {
+      OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP;
       int e = luaK_exp2RK(fs, ex);
-      luaK_codeABC(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, e);
-      break;
-    }
-    case VINDEXEDUP: {
-      int e = luaK_exp2RK(fs, ex);
-      luaK_codeABC(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, e);
+      luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e);
       break;
     }
     default: {
@@ -705,7 +699,9 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
   lua_assert(!hasjumps(t));
   t->u.ind.t = t->u.info;
   t->u.ind.idx = luaK_exp2RK(fs, k);
-  t->k = (t->k == VUPVAL) ? VINDEXEDUP : VINDEXED;
+  t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL
+                                 : check_exp(vkisinreg(t->k), VLOCAL);
+  t->k = VINDEXED;
 }
 
 

+ 16 - 20
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 2.88 2010/06/21 16:30:12 roberto Exp roberto $
+** $Id: lparser.c,v 2.89 2010/07/02 20:42:40 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -969,26 +969,25 @@ 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,
-                            expkind ix, OpCode op) {
+static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
   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 == ix) {
-      if (lh->v.u.ind.t == v->u.info) {  /* conflict? */
-        conflict = 1;
-        lh->v.k = VINDEXED;
-        lh->v.u.ind.t = extra;  /* previous assignment will use safe copy */
-      }
-      if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) {  /* conflict? */
-        conflict = 1;
-        lua_assert(lh->v.k == VINDEXED);
-        lh->v.u.ind.idx = extra;  /* previous assignment will use safe copy */
-      }
+    /* conflict in table 't'? */
+    if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) {
+      conflict = 1;
+      lh->v.u.ind.vt = VLOCAL;
+      lh->v.u.ind.t = extra;  /* previous assignment will use safe copy */
+    }
+    /* conflict in index 'idx'? */
+    if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) {
+      conflict = 1;
+      lh->v.u.ind.idx = extra;  /* previous assignment will use safe copy */
     }
   }
   if (conflict) {
+    OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
     luaK_codeABC(fs, op, fs->freereg, v->u.info, 0);  /* make copy */
     luaK_reserveregs(fs, 1);
   }
@@ -997,16 +996,13 @@ 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 <= VINDEXEDUP,
-                      "syntax error");
+  check_condition(ls, vkisvar(lh->v.k), "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, VINDEXED, OP_MOVE);
-    else if (nv.v.k == VUPVAL)
-      check_conflict(ls, lh, &nv.v, VINDEXEDUP, OP_GETUPVAL);
+    if (nv.v.k != VINDEXED)
+      check_conflict(ls, lh, &nv.v);
     checklimit(ls->fs, nvars, LUAI_MAXCCALLS - G(ls->L)->nCcalls,
                     "variable names");
     assignment(ls, &nv, nvars+1);

+ 13 - 10
lparser.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.h,v 1.63 2010/03/12 19:14:06 roberto Exp roberto $
+** $Id: lparser.h,v 1.64 2010/07/02 20:42:40 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -23,27 +23,30 @@ typedef enum {
   VFALSE,
   VK,		/* info = index of constant in `k' */
   VKNUM,	/* nval = numerical value */
+  VNONRELOC,	/* info = result register */
   VLOCAL,	/* info = local register */
   VUPVAL,       /* info = index of upvalue in 'upvalues' */
-  VINDEXED,	/* t = table register; idx = index R/K */
-  VINDEXEDUP,	/* t = table upvalue; idx = index R/K */
+  VINDEXED,	/* t = table register/upvalue; idx = index R/K */
   VJMP,		/* info = instruction pc */
   VRELOCABLE,	/* info = instruction pc */
-  VNONRELOC,	/* info = result register */
   VCALL,	/* info = instruction pc */
   VVARARG	/* info = instruction pc */
 } expkind;
 
 
+#define vkisvar(k)	(VLOCAL <= (k) && (k) <= VINDEXED)
+#define vkisinreg(k)	((k) == VNONRELOC || (k) == VLOCAL)
+
 typedef struct expdesc {
   expkind k;
   union {
-    struct {
-      short idx;
-      lu_byte t;
-    } ind;  /* for indexed variables */
-    int info;
-    lua_Number nval;
+    struct {  /* for indexed variables (VINDEXED) */
+      short idx;  /* index (R/K) */
+      lu_byte t;  /* table (register or upvalue) */
+      lu_byte vt;  /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
+    } ind;
+    int info;  /* for generic use */
+    lua_Number nval;  /* for VKNUM */
   } u;
   int t;  /* patch list of `exit when true' */
   int f;  /* patch list of `exit when false' */