aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2010-07-07 13:27:29 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2010-07-07 13:27:29 -0300
commit81dd13f4c6a70f08d83f7b7360e4e15cf79dd573 (patch)
treeb379d2c248dd57e71f9461db581c6d0cfa0f24f8
parent6a02bbe1e2f8ad1b98a077bd2aac44e776fd107c (diff)
downloadlua-81dd13f4c6a70f08d83f7b7360e4e15cf79dd573.tar.gz
lua-81dd13f4c6a70f08d83f7b7360e4e15cf79dd573.tar.bz2
lua-81dd13f4c6a70f08d83f7b7360e4e15cf79dd573.zip
new way to distinguish between indexing tables in registers and
tables in upvalues (+ fixed small bug when checking conflicts in multiple assignments)
-rw-r--r--lcode.c28
-rw-r--r--lparser.c36
-rw-r--r--lparser.h23
3 files changed, 41 insertions, 46 deletions
diff --git a/lcode.c b/lcode.c
index 084354fd..ec255a0f 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 2.47 2010/06/30 14:11:17 roberto Exp roberto $ 2** $Id: lcode.c,v 2.48 2010/07/02 20:42:40 roberto Exp roberto $
3** Code generator for Lua 3** Code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -373,15 +373,13 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
373 break; 373 break;
374 } 374 }
375 case VINDEXED: { 375 case VINDEXED: {
376 OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */
376 freereg(fs, e->u.ind.idx); 377 freereg(fs, e->u.ind.idx);
377 freereg(fs, e->u.ind.t); 378 if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */
378 e->u.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.ind.t, e->u.ind.idx); 379 freereg(fs, e->u.ind.t);
379 e->k = VRELOCABLE; 380 op = OP_GETTABLE;
380 break; 381 }
381 } 382 e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx);
382 case VINDEXEDUP: {
383 freereg(fs, e->u.ind.idx);
384 e->u.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.ind.t, e->u.ind.idx);
385 e->k = VRELOCABLE; 383 e->k = VRELOCABLE;
386 break; 384 break;
387 } 385 }
@@ -551,13 +549,9 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
551 break; 549 break;
552 } 550 }
553 case VINDEXED: { 551 case VINDEXED: {
552 OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP;
554 int e = luaK_exp2RK(fs, ex); 553 int e = luaK_exp2RK(fs, ex);
555 luaK_codeABC(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, e); 554 luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e);
556 break;
557 }
558 case VINDEXEDUP: {
559 int e = luaK_exp2RK(fs, ex);
560 luaK_codeABC(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, e);
561 break; 555 break;
562 } 556 }
563 default: { 557 default: {
@@ -705,7 +699,9 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
705 lua_assert(!hasjumps(t)); 699 lua_assert(!hasjumps(t));
706 t->u.ind.t = t->u.info; 700 t->u.ind.t = t->u.info;
707 t->u.ind.idx = luaK_exp2RK(fs, k); 701 t->u.ind.idx = luaK_exp2RK(fs, k);
708 t->k = (t->k == VUPVAL) ? VINDEXEDUP : VINDEXED; 702 t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL
703 : check_exp(vkisinreg(t->k), VLOCAL);
704 t->k = VINDEXED;
709} 705}
710 706
711 707
diff --git a/lparser.c b/lparser.c
index c0bf6316..49fe8d8c 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 2.88 2010/06/21 16:30:12 roberto Exp roberto $ 2** $Id: lparser.c,v 2.89 2010/07/02 20:42:40 roberto Exp roberto $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -969,26 +969,25 @@ struct LHS_assign {
969** local value in a safe place and use this safe copy in the previous 969** local value in a safe place and use this safe copy in the previous
970** assignment. 970** assignment.
971*/ 971*/
972static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v, 972static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
973 expkind ix, OpCode op) {
974 FuncState *fs = ls->fs; 973 FuncState *fs = ls->fs;
975 int extra = fs->freereg; /* eventual position to save local variable */ 974 int extra = fs->freereg; /* eventual position to save local variable */
976 int conflict = 0; 975 int conflict = 0;
977 for (; lh; lh = lh->prev) { 976 for (; lh; lh = lh->prev) {
978 if (lh->v.k == ix) { 977 /* conflict in table 't'? */
979 if (lh->v.u.ind.t == v->u.info) { /* conflict? */ 978 if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) {
980 conflict = 1; 979 conflict = 1;
981 lh->v.k = VINDEXED; 980 lh->v.u.ind.vt = VLOCAL;
982 lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ 981 lh->v.u.ind.t = extra; /* previous assignment will use safe copy */
983 } 982 }
984 if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { /* conflict? */ 983 /* conflict in index 'idx'? */
985 conflict = 1; 984 if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) {
986 lua_assert(lh->v.k == VINDEXED); 985 conflict = 1;
987 lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ 986 lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */
988 }
989 } 987 }
990 } 988 }
991 if (conflict) { 989 if (conflict) {
990 OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
992 luaK_codeABC(fs, op, fs->freereg, v->u.info, 0); /* make copy */ 991 luaK_codeABC(fs, op, fs->freereg, v->u.info, 0); /* make copy */
993 luaK_reserveregs(fs, 1); 992 luaK_reserveregs(fs, 1);
994 } 993 }
@@ -997,16 +996,13 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v,
997 996
998static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { 997static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
999 expdesc e; 998 expdesc e;
1000 check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXEDUP, 999 check_condition(ls, vkisvar(lh->v.k), "syntax error");
1001 "syntax error");
1002 if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ 1000 if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */
1003 struct LHS_assign nv; 1001 struct LHS_assign nv;
1004 nv.prev = lh; 1002 nv.prev = lh;
1005 primaryexp(ls, &nv.v); 1003 primaryexp(ls, &nv.v);
1006 if (nv.v.k == VLOCAL) 1004 if (nv.v.k != VINDEXED)
1007 check_conflict(ls, lh, &nv.v, VINDEXED, OP_MOVE); 1005 check_conflict(ls, lh, &nv.v);
1008 else if (nv.v.k == VUPVAL)
1009 check_conflict(ls, lh, &nv.v, VINDEXEDUP, OP_GETUPVAL);
1010 checklimit(ls->fs, nvars, LUAI_MAXCCALLS - G(ls->L)->nCcalls, 1006 checklimit(ls->fs, nvars, LUAI_MAXCCALLS - G(ls->L)->nCcalls,
1011 "variable names"); 1007 "variable names");
1012 assignment(ls, &nv, nvars+1); 1008 assignment(ls, &nv, nvars+1);
diff --git a/lparser.h b/lparser.h
index bef7bbc4..945a14a5 100644
--- a/lparser.h
+++ b/lparser.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.h,v 1.63 2010/03/12 19:14:06 roberto Exp roberto $ 2** $Id: lparser.h,v 1.64 2010/07/02 20:42:40 roberto Exp roberto $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -23,27 +23,30 @@ typedef enum {
23 VFALSE, 23 VFALSE,
24 VK, /* info = index of constant in `k' */ 24 VK, /* info = index of constant in `k' */
25 VKNUM, /* nval = numerical value */ 25 VKNUM, /* nval = numerical value */
26 VNONRELOC, /* info = result register */
26 VLOCAL, /* info = local register */ 27 VLOCAL, /* info = local register */
27 VUPVAL, /* info = index of upvalue in 'upvalues' */ 28 VUPVAL, /* info = index of upvalue in 'upvalues' */
28 VINDEXED, /* t = table register; idx = index R/K */ 29 VINDEXED, /* t = table register/upvalue; idx = index R/K */
29 VINDEXEDUP, /* t = table upvalue; idx = index R/K */
30 VJMP, /* info = instruction pc */ 30 VJMP, /* info = instruction pc */
31 VRELOCABLE, /* info = instruction pc */ 31 VRELOCABLE, /* info = instruction pc */
32 VNONRELOC, /* info = result register */
33 VCALL, /* info = instruction pc */ 32 VCALL, /* info = instruction pc */
34 VVARARG /* info = instruction pc */ 33 VVARARG /* info = instruction pc */
35} expkind; 34} expkind;
36 35
37 36
37#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED)
38#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL)
39
38typedef struct expdesc { 40typedef struct expdesc {
39 expkind k; 41 expkind k;
40 union { 42 union {
41 struct { 43 struct { /* for indexed variables (VINDEXED) */
42 short idx; 44 short idx; /* index (R/K) */
43 lu_byte t; 45 lu_byte t; /* table (register or upvalue) */
44 } ind; /* for indexed variables */ 46 lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
45 int info; 47 } ind;
46 lua_Number nval; 48 int info; /* for generic use */
49 lua_Number nval; /* for VKNUM */
47 } u; 50 } u;
48 int t; /* patch list of `exit when true' */ 51 int t; /* patch list of `exit when true' */
49 int f; /* patch list of `exit when false' */ 52 int f; /* patch list of `exit when false' */