summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-04-28 17:57:45 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-04-28 17:57:45 -0300
commit502a1d1108d4e3b97e012d2ed9a496fd003b08db (patch)
tree0d1daa63ebe8af89a35ec5ecbc48f7e055eb0374
parent173e41b2ebed59a716d299470de25e50aee3b921 (diff)
downloadlua-502a1d1108d4e3b97e012d2ed9a496fd003b08db.tar.gz
lua-502a1d1108d4e3b97e012d2ed9a496fd003b08db.tar.bz2
lua-502a1d1108d4e3b97e012d2ed9a496fd003b08db.zip
new opcodes for table access with constant keys (strings and integers)
-rw-r--r--lcode.c74
-rw-r--r--ldebug.c92
-rw-r--r--lopcodes.c18
-rw-r--r--lopcodes.h20
-rw-r--r--lparser.c40
-rw-r--r--lparser.h24
-rw-r--r--lvm.c76
7 files changed, 245 insertions, 99 deletions
diff --git a/lcode.c b/lcode.c
index ccf7b1ae..a154c339 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 2.116 2017/04/25 20:01:14 roberto Exp roberto $ 2** $Id: lcode.c,v 2.117 2017/04/26 17:46:52 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*/
@@ -580,18 +580,26 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
580 e->k = VRELOCABLE; 580 e->k = VRELOCABLE;
581 break; 581 break;
582 } 582 }
583 case VINDEXUP: {
584 e->u.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.ind.t, e->u.ind.idx);
585 e->k = VRELOCABLE;
586 break;
587 }
588 case VINDEXI: {
589 freereg(fs, e->u.ind.t);
590 e->u.info = luaK_codeABC(fs, OP_GETI, 0, e->u.ind.t, e->u.ind.idx);
591 e->k = VRELOCABLE;
592 break;
593 }
594 case VINDEXSTR: {
595 freereg(fs, e->u.ind.t);
596 e->u.info = luaK_codeABC(fs, OP_GETFIELD, 0, e->u.ind.t, e->u.ind.idx);
597 e->k = VRELOCABLE;
598 break;
599 }
583 case VINDEXED: { 600 case VINDEXED: {
584 OpCode op; 601 freeregs(fs, e->u.ind.t, e->u.ind.idx);
585 if (e->u.ind.vt == VLOCAL) { /* is 't' in a register? */ 602 e->u.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.ind.t, e->u.ind.idx);
586 freeregs(fs, e->u.ind.t, e->u.ind.idx);
587 op = OP_GETTABLE;
588 }
589 else {
590 lua_assert(e->u.ind.vt == VUPVAL);
591 freereg(fs, e->u.ind.idx);
592 op = OP_GETTABUP; /* 't' is in an upvalue */
593 }
594 e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx);
595 e->k = VRELOCABLE; 603 e->k = VRELOCABLE;
596 break; 604 break;
597 } 605 }
@@ -807,10 +815,24 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
807 luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); 815 luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0);
808 break; 816 break;
809 } 817 }
818 case VINDEXUP: {
819 int e = luaK_exp2RK(fs, ex);
820 luaK_codeABC(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, e);
821 break;
822 }
823 case VINDEXI: {
824 int e = luaK_exp2RK(fs, ex);
825 luaK_codeABC(fs, OP_SETI, var->u.ind.t, var->u.ind.idx, e);
826 break;
827 }
828 case VINDEXSTR: {
829 int e = luaK_exp2RK(fs, ex);
830 luaK_codeABC(fs, OP_SETFIELD, var->u.ind.t, var->u.ind.idx, e);
831 break;
832 }
810 case VINDEXED: { 833 case VINDEXED: {
811 OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP;
812 int e = luaK_exp2RK(fs, ex); 834 int e = luaK_exp2RK(fs, ex);
813 luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); 835 luaK_codeABC(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, e);
814 break; 836 break;
815 } 837 }
816 default: lua_assert(0); /* invalid var kind to store */ 838 default: lua_assert(0); /* invalid var kind to store */
@@ -959,7 +981,8 @@ static void codenot (FuncState *fs, expdesc *e) {
959** Check whether expression 'e' is a literal string 981** Check whether expression 'e' is a literal string
960*/ 982*/
961static int isKstr (FuncState *fs, expdesc *e) { 983static int isKstr (FuncState *fs, expdesc *e) {
962 return (e->k == VK && ttisstring(&fs->f->k[e->u.info])); 984 return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_C &&
985 ttisstring(&fs->f->k[e->u.info]));
963} 986}
964 987
965 988
@@ -976,15 +999,30 @@ static int isKint (expdesc *e) {
976/* 999/*
977** Create expression 't[k]'. 't' must have its final result already in a 1000** Create expression 't[k]'. 't' must have its final result already in a
978** register or upvalue. Upvalues can only be indexed by literal strings. 1001** register or upvalue. Upvalues can only be indexed by literal strings.
1002** Keys can be literal strings in the constant table or arbitrary
1003** values in registers.
979*/ 1004*/
980void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { 1005void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
981 lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL)); 1006 lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL));
982 if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non string? */ 1007 if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non string? */
983 luaK_exp2anyreg(fs, t); /* put it in a register */ 1008 luaK_exp2anyreg(fs, t); /* put it in a register */
984 t->u.ind.t = t->u.info; /* register or upvalue index */ 1009 t->u.ind.t = t->u.info; /* register or upvalue index */
985 t->u.ind.idx = luaK_exp2RK(fs, k); /* R/K index for key */ 1010 if (t->k == VUPVAL) {
986 t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL : VLOCAL; 1011 t->u.ind.idx = k->u.info; /* literal string */
987 t->k = VINDEXED; 1012 t->k = VINDEXUP;
1013 }
1014 else if (isKstr(fs, k)) {
1015 t->u.ind.idx = k->u.info; /* literal string */
1016 t->k = VINDEXSTR;
1017 }
1018 else if (isKint(k)) {
1019 t->u.ind.idx = k->u.ival; /* integer constant */
1020 t->k = VINDEXI;
1021 }
1022 else {
1023 t->u.ind.idx = luaK_exp2anyreg(fs, k); /* register */
1024 t->k = VINDEXED;
1025 }
988} 1026}
989 1027
990 1028
diff --git a/ldebug.c b/ldebug.c
index 4f35d211..8a36e2f8 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldebug.c,v 2.121 2016/10/19 12:32:10 roberto Exp roberto $ 2** $Id: ldebug.c,v 2.122 2017/04/26 17:46:52 roberto Exp roberto $
3** Debug Interface 3** Debug Interface
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -350,28 +350,36 @@ static const char *getobjname (Proto *p, int lastpc, int reg,
350 350
351 351
352/* 352/*
353** find a "name" for the RK value 'c' 353** Find a "name" for the constant 'c'.
354*/ 354*/
355static void kname (Proto *p, int pc, int c, const char **name) { 355static void kname (Proto *p, int c, const char **name) {
356 if (ISK(c)) { /* is 'c' a constant? */ 356 TValue *kvalue = &p->k[INDEXK(c)];
357 TValue *kvalue = &p->k[INDEXK(c)]; 357 *name = (ttisstring(kvalue)) ? svalue(kvalue) : "?";
358 if (ttisstring(kvalue)) { /* literal constant? */ 358}
359 *name = svalue(kvalue); /* it is its own name */ 359
360 return; 360
361 } 361/*
362 /* else no reasonable name found */ 362** Find a "name" for the register 'c'.
363 } 363*/
364 else { /* 'c' is a register */ 364static void rname (Proto *p, int pc, int c, const char **name) {
365 const char *what = getobjname(p, pc, c, name); /* search for 'c' */ 365 const char *what = getobjname(p, pc, c, name); /* search for 'c' */
366 if (what && *what == 'c') { /* found a constant name? */ 366 if (!(what && *what == 'c')) /* did not find a constant name? */
367 return; /* 'name' already filled */ 367 *name = "?";
368 } 368}
369 /* else no reasonable name found */ 369
370 } 370
371 *name = "?"; /* no reasonable name found */ 371/*
372** Find a "name" for the R/K index 'c'.
373*/
374static void rkname (Proto *p, int pc, int c, const char **name) {
375 if (ISK(c)) /* is 'c' a constant? */
376 kname(p, INDEXK(c), name);
377 else /* 'c' is a register */
378 rname(p, pc, c, name);
372} 379}
373 380
374 381
382
375static int filterpc (int pc, int jmptarget) { 383static int filterpc (int pc, int jmptarget) {
376 if (pc < jmptarget) /* is code conditional (inside a jump)? */ 384 if (pc < jmptarget) /* is code conditional (inside a jump)? */
377 return -1; /* cannot know who sets that register */ 385 return -1; /* cannot know who sets that register */
@@ -428,8 +436,22 @@ static int findsetreg (Proto *p, int lastpc, int reg) {
428} 436}
429 437
430 438
431static const char *getobjname (Proto *p, int lastpc, int reg, 439/*
432 const char **name) { 440** Check whether table being indexed by instruction 'i' is the
441** environment '_ENV'
442*/
443static const char *gxf (Proto *p, int pc, Instruction i, int isup) {
444 int t = GETARG_B(i); /* table index */
445 const char *name; /* name of indexed variable */
446 if (isup) /* is an upvalue? */
447 name = upvalname(p, t);
448 else
449 getobjname(p, pc, t, &name);
450 return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field";
451}
452
453
454 const char *getobjname (Proto *p, int lastpc, int reg, const char **name) {
433 int pc; 455 int pc;
434 *name = luaF_getlocalname(p, reg + 1, lastpc); 456 *name = luaF_getlocalname(p, reg + 1, lastpc);
435 if (*name) /* is a local? */ 457 if (*name) /* is a local? */
@@ -446,15 +468,24 @@ static const char *getobjname (Proto *p, int lastpc, int reg,
446 return getobjname(p, pc, b, name); /* get name for 'b' */ 468 return getobjname(p, pc, b, name); /* get name for 'b' */
447 break; 469 break;
448 } 470 }
449 case OP_GETTABUP: 471 case OP_GETTABUP: {
472 int k = GETARG_C(i); /* key index */
473 kname(p, k, name);
474 return gxf(p, pc, i, 1);
475 }
450 case OP_GETTABLE: { 476 case OP_GETTABLE: {
451 int k = GETARG_C(i); /* key index */ 477 int k = GETARG_C(i); /* key index */
452 int t = GETARG_B(i); /* table index */ 478 rname(p, pc, k, name);
453 const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ 479 return gxf(p, pc, i, 0);
454 ? luaF_getlocalname(p, t + 1, pc) 480 }
455 : upvalname(p, t); 481 case OP_GETI: {
456 kname(p, pc, k, name); 482 *name = "integer index";
457 return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; 483 return "field";
484 }
485 case OP_GETFIELD: {
486 int k = GETARG_C(i); /* key index */
487 kname(p, k, name);
488 return gxf(p, pc, i, 0);
458 } 489 }
459 case OP_GETUPVAL: { 490 case OP_GETUPVAL: {
460 *name = upvalname(p, GETARG_B(i)); 491 *name = upvalname(p, GETARG_B(i));
@@ -472,7 +503,7 @@ static const char *getobjname (Proto *p, int lastpc, int reg,
472 } 503 }
473 case OP_SELF: { 504 case OP_SELF: {
474 int k = GETARG_C(i); /* key index */ 505 int k = GETARG_C(i); /* key index */
475 kname(p, pc, k, name); 506 rkname(p, pc, k, name);
476 return "method"; 507 return "method";
477 } 508 }
478 default: break; /* go through to return NULL */ 509 default: break; /* go through to return NULL */
@@ -508,9 +539,10 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
508 } 539 }
509 /* other instructions can do calls through metamethods */ 540 /* other instructions can do calls through metamethods */
510 case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: 541 case OP_SELF: case OP_GETTABUP: case OP_GETTABLE:
542 case OP_GETI: case OP_GETFIELD:
511 tm = TM_INDEX; 543 tm = TM_INDEX;
512 break; 544 break;
513 case OP_SETTABUP: case OP_SETTABLE: 545 case OP_SETTABUP: case OP_SETTABLE: case OP_SETI: case OP_SETFIELD:
514 tm = TM_NEWINDEX; 546 tm = TM_NEWINDEX;
515 break; 547 break;
516 case OP_ADDI: 548 case OP_ADDI:
diff --git a/lopcodes.c b/lopcodes.c
index f66f209a..1ffc52c9 100644
--- a/lopcodes.c
+++ b/lopcodes.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lopcodes.c,v 1.56 2017/04/20 19:53:55 roberto Exp roberto $ 2** $Id: lopcodes.c,v 1.57 2017/04/26 17:46:52 roberto Exp roberto $
3** Opcodes for Lua virtual machine 3** Opcodes for Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -25,11 +25,15 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
25 "LOADBOOL", 25 "LOADBOOL",
26 "LOADNIL", 26 "LOADNIL",
27 "GETUPVAL", 27 "GETUPVAL",
28 "SETUPVAL",
28 "GETTABUP", 29 "GETTABUP",
29 "GETTABLE", 30 "GETTABLE",
31 "GETI",
32 "GETFIELD",
30 "SETTABUP", 33 "SETTABUP",
31 "SETUPVAL",
32 "SETTABLE", 34 "SETTABLE",
35 "SETI",
36 "SETFIELD",
33 "NEWTABLE", 37 "NEWTABLE",
34 "SELF", 38 "SELF",
35 "ADDI", 39 "ADDI",
@@ -82,11 +86,15 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
82 ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ 86 ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
83 ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ 87 ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */
84 ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ 88 ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
89 ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
85 ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ 90 ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */
86 ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ 91 ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_GETTABLE */
92 ,opmode(0, 1, OpArgR, OpArgU, iABC) /* OP_GETI */
93 ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETFIELD */
87 ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ 94 ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */
88 ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ 95 ,opmode(0, 0, OpArgR, OpArgK, iABC) /* OP_SETTABLE */
89 ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ 96 ,opmode(0, 0, OpArgU, OpArgK, iABC) /* OP_SETI */
97 ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETFIELD */
90 ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ 98 ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */
91 ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ 99 ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */
92 ,opmode(0, 1, OpArgR, OpArgU, iABC) /* OP_ADDI */ 100 ,opmode(0, 1, OpArgR, OpArgU, iABC) /* OP_ADDI */
diff --git a/lopcodes.h b/lopcodes.h
index c359581d..6c9df6f3 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lopcodes.h,v 1.151 2017/04/24 20:26:39 roberto Exp roberto $ 2** $Id: lopcodes.h,v 1.152 2017/04/26 17:46:52 roberto Exp roberto $
3** Opcodes for Lua virtual machine 3** Opcodes for Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -178,17 +178,21 @@ OP_LOADKX,/* A R(A) := Kst(extra arg) */
178OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */ 178OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
179OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */ 179OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */
180OP_GETUPVAL,/* A B R(A) := UpValue[B] */ 180OP_GETUPVAL,/* A B R(A) := UpValue[B] */
181OP_SETUPVAL,/* A B UpValue[B] := R(A) */
181 182
182OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */ 183OP_GETTABUP,/* A B C R(A) := UpValue[B][K(C):string] */
183OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */ 184OP_GETTABLE,/* A B C R(A) := R(B)[R(C)] */
185OP_GETI,/* A B C R(A) := R(B)[C] */
186OP_GETFIELD,/* A B C R(A) := R(B)[Kst(C):string] */
184 187
185OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */ 188OP_SETTABUP,/* A B C UpValue[A][K(B):string] := RK(C) */
186OP_SETUPVAL,/* A B UpValue[B] := R(A) */ 189OP_SETTABLE,/* A B C R(A)[R(B)] := RK(C) */
187OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */ 190OP_SETI,/* A B C R(A)[B] := RK(C) */
191OP_SETFIELD,/* A B C R(A)[K(B):string] := RK(C) */
188 192
189OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */ 193OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
190 194
191OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */ 195OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C):string] */
192 196
193OP_ADDI,/* A B C R(A) := R(B) + C */ 197OP_ADDI,/* A B C R(A) := R(B) + C */
194OP_ADD,/* A B C R(A) := RK(B) + RK(C) */ 198OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
@@ -259,8 +263,6 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
259 263
260 (*) In OP_LOADKX, the next 'instruction' is always EXTRAARG. 264 (*) In OP_LOADKX, the next 'instruction' is always EXTRAARG.
261 265
262 (*) In OP_GETTABUP, OP_SETTABUP, and OP_SELF, the index must be a string.
263
264 (*) For comparisons, A specifies what condition the test should accept 266 (*) For comparisons, A specifies what condition the test should accept
265 (true or false). 267 (true or false).
266 268
diff --git a/lparser.c b/lparser.c
index 25134f11..f78f64bd 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 2.155 2016/08/01 19:51:24 roberto Exp roberto $ 2** $Id: lparser.c,v 2.156 2017/04/20 19:53:55 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*/
@@ -647,8 +647,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) {
647 /* recfield -> (NAME | '['exp1']') = exp1 */ 647 /* recfield -> (NAME | '['exp1']') = exp1 */
648 FuncState *fs = ls->fs; 648 FuncState *fs = ls->fs;
649 int reg = ls->fs->freereg; 649 int reg = ls->fs->freereg;
650 expdesc key, val; 650 expdesc tab, key, val;
651 int rkkey;
652 if (ls->t.token == TK_NAME) { 651 if (ls->t.token == TK_NAME) {
653 checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); 652 checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
654 checkname(ls, &key); 653 checkname(ls, &key);
@@ -657,9 +656,10 @@ static void recfield (LexState *ls, struct ConsControl *cc) {
657 yindex(ls, &key); 656 yindex(ls, &key);
658 cc->nh++; 657 cc->nh++;
659 checknext(ls, '='); 658 checknext(ls, '=');
660 rkkey = luaK_exp2RK(fs, &key); 659 tab = *cc->t;
660 luaK_indexed(fs, &tab, &key);
661 expr(ls, &val); 661 expr(ls, &val);
662 luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val)); 662 luaK_storevar(fs, &tab, &val);
663 fs->freereg = reg; /* free registers */ 663 fs->freereg = reg; /* free registers */
664} 664}
665 665
@@ -1121,17 +1121,25 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
1121 int extra = fs->freereg; /* eventual position to save local variable */ 1121 int extra = fs->freereg; /* eventual position to save local variable */
1122 int conflict = 0; 1122 int conflict = 0;
1123 for (; lh; lh = lh->prev) { /* check all previous assignments */ 1123 for (; lh; lh = lh->prev) { /* check all previous assignments */
1124 if (lh->v.k == VINDEXED) { /* assigning to a table? */ 1124 if (vkisindexed(lh->v.k)) { /* assignment to table field? */
1125 /* table is the upvalue/local being assigned now? */ 1125 if (lh->v.k == VINDEXUP) { /* is table an upvalue? */
1126 if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { 1126 if (v->k == VUPVAL && lh->v.u.ind.t == v->u.info) {
1127 conflict = 1; 1127 conflict = 1; /* table is the upvalue being assigned now */
1128 lh->v.u.ind.vt = VLOCAL; 1128 lh->v.k = VINDEXSTR;
1129 lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ 1129 lh->v.u.ind.t = extra; /* assignment will use safe copy */
1130 }
1130 } 1131 }
1131 /* index is the local being assigned? (index cannot be upvalue) */ 1132 else { /* table is a register */
1132 if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { 1133 if (v->k == VLOCAL && lh->v.u.ind.t == v->u.info) {
1133 conflict = 1; 1134 conflict = 1; /* table is the local being assigned now */
1134 lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ 1135 lh->v.u.ind.t = extra; /* assignment will use safe copy */
1136 }
1137 /* is index the local being assigned? */
1138 if (lh->v.k == VINDEXED && v->k == VLOCAL &&
1139 lh->v.u.ind.idx == v->u.info) {
1140 conflict = 1;
1141 lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */
1142 }
1135 } 1143 }
1136 } 1144 }
1137 } 1145 }
@@ -1151,7 +1159,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
1151 struct LHS_assign nv; 1159 struct LHS_assign nv;
1152 nv.prev = lh; 1160 nv.prev = lh;
1153 suffixedexp(ls, &nv.v); 1161 suffixedexp(ls, &nv.v);
1154 if (nv.v.k != VINDEXED) 1162 if (!vkisindexed(nv.v.k))
1155 check_conflict(ls, lh, &nv.v); 1163 check_conflict(ls, lh, &nv.v);
1156 checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, 1164 checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS,
1157 "C levels"); 1165 "C levels");
diff --git a/lparser.h b/lparser.h
index 13e613ac..16124181 100644
--- a/lparser.h
+++ b/lparser.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.h,v 1.75 2015/12/17 15:44:50 roberto Exp roberto $ 2** $Id: lparser.h,v 1.76 2015/12/30 18:16:13 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*/
@@ -36,9 +36,17 @@ typedef enum {
36 VLOCAL, /* local variable; info = local register */ 36 VLOCAL, /* local variable; info = local register */
37 VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ 37 VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
38 VINDEXED, /* indexed variable; 38 VINDEXED, /* indexed variable;
39 ind.vt = whether 't' is register or upvalue; 39 ind.t = table register;
40 ind.t = table register or upvalue; 40 ind.idx = key's R index */
41 ind.idx = key's R/K index */ 41 VINDEXUP, /* indexed upvalue;
42 ind.t = table upvalue;
43 ind.idx = key's K index */
44 VINDEXI, /* indexed variable with constant integer;
45 ind.t = table register;
46 ind.idx = key's value */
47 VINDEXSTR, /* indexed variable with literal string;
48 ind.t = table register;
49 ind.idx = key's K index */
42 VJMP, /* expression is a test/comparison; 50 VJMP, /* expression is a test/comparison;
43 info = pc of corresponding jump instruction */ 51 info = pc of corresponding jump instruction */
44 VRELOCABLE, /* expression can put result in any register; 52 VRELOCABLE, /* expression can put result in any register;
@@ -48,7 +56,8 @@ typedef enum {
48} expkind; 56} expkind;
49 57
50 58
51#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) 59#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXSTR)
60#define vkisindexed(k) (VINDEXED <= (k) && (k) <= VINDEXSTR)
52#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) 61#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL)
53 62
54typedef struct expdesc { 63typedef struct expdesc {
@@ -57,10 +66,9 @@ typedef struct expdesc {
57 lua_Integer ival; /* for VKINT */ 66 lua_Integer ival; /* for VKINT */
58 lua_Number nval; /* for VKFLT */ 67 lua_Number nval; /* for VKFLT */
59 int info; /* for generic use */ 68 int info; /* for generic use */
60 struct { /* for indexed variables (VINDEXED) */ 69 struct { /* for indexed variables */
61 short idx; /* index (R/K) */ 70 short idx; /* index (R or "long" K) */
62 lu_byte t; /* table (register or upvalue) */ 71 lu_byte t; /* table (register or upvalue) */
63 lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
64 } ind; 72 } ind;
65 } u; 73 } u;
66 int t; /* patch list of 'exit when true' */ 74 int t; /* patch list of 'exit when true' */
diff --git a/lvm.c b/lvm.c
index 52a6ca35..9fa9daf5 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.272 2017/04/24 20:26:39 roberto Exp roberto $ 2** $Id: lvm.c,v 2.273 2017/04/26 17:46:52 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -658,11 +658,13 @@ void luaV_finishOp (lua_State *L) {
658 Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ 658 Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */
659 OpCode op = GET_OPCODE(inst); 659 OpCode op = GET_OPCODE(inst);
660 switch (op) { /* finish its execution */ 660 switch (op) { /* finish its execution */
661 case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV: 661 case OP_ADDI: case OP_ADD: case OP_SUB:
662 case OP_MUL: case OP_DIV: case OP_IDIV:
662 case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: 663 case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR:
663 case OP_MOD: case OP_POW: 664 case OP_MOD: case OP_POW:
664 case OP_UNM: case OP_BNOT: case OP_LEN: 665 case OP_UNM: case OP_BNOT: case OP_LEN:
665 case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { 666 case OP_GETTABUP: case OP_GETTABLE: case OP_GETI:
667 case OP_GETFIELD: case OP_SELF: {
666 setobjs2s(L, base + GETARG_A(inst), --L->top); 668 setobjs2s(L, base + GETARG_A(inst), --L->top);
667 break; 669 break;
668 } 670 }
@@ -704,6 +706,7 @@ void luaV_finishOp (lua_State *L) {
704 break; 706 break;
705 } 707 }
706 case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: 708 case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE:
709 case OP_SETI: case OP_SETFIELD:
707 break; 710 break;
708 default: lua_assert(0); 711 default: lua_assert(0);
709 } 712 }
@@ -726,7 +729,9 @@ void luaV_finishOp (lua_State *L) {
726 729
727#define RA(i) (base+GETARG_A(i)) 730#define RA(i) (base+GETARG_A(i))
728#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_Br(i)) 731#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_Br(i))
732#define KB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_B(i))
729#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) 733#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
734#define KC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, k+GETARG_C(i))
730#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ 735#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
731 (GETARG_Bk(i)) ? k+GETARG_Br(i) : base+GETARG_Br(i)) 736 (GETARG_Bk(i)) ? k+GETARG_Br(i) : base+GETARG_Br(i))
732#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ 737#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
@@ -837,10 +842,16 @@ void luaV_execute (lua_State *L) {
837 setobj2s(L, ra, cl->upvals[b]->v); 842 setobj2s(L, ra, cl->upvals[b]->v);
838 vmbreak; 843 vmbreak;
839 } 844 }
845 vmcase(OP_SETUPVAL) {
846 UpVal *uv = cl->upvals[GETARG_B(i)];
847 setobj(L, uv->v, ra);
848 luaC_barrier(L, uv, ra);
849 vmbreak;
850 }
840 vmcase(OP_GETTABUP) { 851 vmcase(OP_GETTABUP) {
841 const TValue *slot; 852 const TValue *slot;
842 TValue *upval = cl->upvals[GETARG_B(i)]->v; 853 TValue *upval = cl->upvals[GETARG_B(i)]->v;
843 TValue *rc = RKC(i); 854 TValue *rc = KC(i);
844 TString *key = tsvalue(rc); /* key must be a string */ 855 TString *key = tsvalue(rc); /* key must be a string */
845 if (luaV_fastget(L, upval, key, slot, luaH_getstr)) { 856 if (luaV_fastget(L, upval, key, slot, luaH_getstr)) {
846 setobj2s(L, ra, slot); 857 setobj2s(L, ra, slot);
@@ -850,32 +861,71 @@ void luaV_execute (lua_State *L) {
850 } 861 }
851 vmcase(OP_GETTABLE) { 862 vmcase(OP_GETTABLE) {
852 StkId rb = RB(i); 863 StkId rb = RB(i);
853 TValue *rc = RKC(i); 864 TValue *rc = RC(i);
854 gettableProtected(L, rb, rc, ra); 865 gettableProtected(L, rb, rc, ra);
855 vmbreak; 866 vmbreak;
856 } 867 }
868 vmcase(OP_GETI) {
869 const TValue *slot;
870 StkId rb = RB(i);
871 int c = GETARG_C(i);
872 if (luaV_fastget(L, rb, c, slot, luaH_getint)) {
873 setobj2s(L, ra, slot);
874 }
875 else {
876 TValue key;
877 setivalue(&key, c);
878 Protect(luaV_finishget(L, rb, &key, ra, slot));
879 }
880 vmbreak;
881 }
882 vmcase(OP_GETFIELD) {
883 const TValue *slot;
884 StkId rb = RB(i);
885 TValue *rc = KC(i);
886 TString *key = tsvalue(rc); /* key must be a string */
887 if (luaV_fastget(L, rb, key, slot, luaH_getstr)) {
888 setobj2s(L, ra, slot);
889 }
890 else Protect(luaV_finishget(L, rb, rc, ra, slot));
891 vmbreak;
892 }
857 vmcase(OP_SETTABUP) { 893 vmcase(OP_SETTABUP) {
858 const TValue *slot; 894 const TValue *slot;
859 TValue *upval = cl->upvals[GETARG_A(i)]->v; 895 TValue *upval = cl->upvals[GETARG_A(i)]->v;
860 TValue *rb = RKB(i); 896 TValue *rb = KB(i);
861 TValue *rc = RKC(i); 897 TValue *rc = RKC(i);
862 TString *key = tsvalue(rb); /* key must be a string */ 898 TString *key = tsvalue(rb); /* key must be a string */
863 if (!luaV_fastset(L, upval, key, slot, luaH_getstr, rc)) 899 if (!luaV_fastset(L, upval, key, slot, luaH_getstr, rc))
864 Protect(luaV_finishset(L, upval, rb, rc, slot)); 900 Protect(luaV_finishset(L, upval, rb, rc, slot));
865 vmbreak; 901 vmbreak;
866 } 902 }
867 vmcase(OP_SETUPVAL) {
868 UpVal *uv = cl->upvals[GETARG_B(i)];
869 setobj(L, uv->v, ra);
870 luaC_barrier(L, uv, ra);
871 vmbreak;
872 }
873 vmcase(OP_SETTABLE) { 903 vmcase(OP_SETTABLE) {
874 TValue *rb = RKB(i); 904 TValue *rb = RB(i);
875 TValue *rc = RKC(i); 905 TValue *rc = RKC(i);
876 settableProtected(L, ra, rb, rc); 906 settableProtected(L, ra, rb, rc);
877 vmbreak; 907 vmbreak;
878 } 908 }
909 vmcase(OP_SETI) {
910 const TValue *slot;
911 int c = GETARG_B(i);
912 TValue *rc = RKC(i);
913 if (!luaV_fastset(L, ra, c, slot, luaH_getint, rc)) {
914 TValue key;
915 setivalue(&key, c);
916 Protect(luaV_finishset(L, ra, &key, rc, slot));
917 }
918 vmbreak;
919 }
920 vmcase(OP_SETFIELD) {
921 const TValue *slot;
922 TValue *rb = KB(i);
923 TValue *rc = RKC(i);
924 TString *key = tsvalue(rb); /* key must be a string */
925 if (!luaV_fastset(L, ra, key, slot, luaH_getstr, rc))
926 Protect(luaV_finishset(L, ra, rb, rc, slot));
927 vmbreak;
928 }
879 vmcase(OP_NEWTABLE) { 929 vmcase(OP_NEWTABLE) {
880 int b = GETARG_B(i); 930 int b = GETARG_B(i);
881 int c = GETARG_C(i); 931 int c = GETARG_C(i);