diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-04-28 17:57:45 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-04-28 17:57:45 -0300 |
commit | 502a1d1108d4e3b97e012d2ed9a496fd003b08db (patch) | |
tree | 0d1daa63ebe8af89a35ec5ecbc48f7e055eb0374 | |
parent | 173e41b2ebed59a716d299470de25e50aee3b921 (diff) | |
download | lua-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.c | 74 | ||||
-rw-r--r-- | ldebug.c | 92 | ||||
-rw-r--r-- | lopcodes.c | 18 | ||||
-rw-r--r-- | lopcodes.h | 20 | ||||
-rw-r--r-- | lparser.c | 40 | ||||
-rw-r--r-- | lparser.h | 24 | ||||
-rw-r--r-- | lvm.c | 76 |
7 files changed, 245 insertions, 99 deletions
@@ -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 | */ |
961 | static int isKstr (FuncState *fs, expdesc *e) { | 983 | static 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 | */ |
980 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | 1005 | void 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 | ||
@@ -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 | */ |
355 | static void kname (Proto *p, int pc, int c, const char **name) { | 355 | static 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 */ | 364 | static 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 | */ | ||
374 | static 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 | |||
375 | static int filterpc (int pc, int jmptarget) { | 383 | static 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 | ||
431 | static 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 | */ | ||
443 | static 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: |
@@ -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 */ |
@@ -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) */ | |||
178 | OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */ | 178 | OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */ |
179 | OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */ | 179 | OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */ |
180 | OP_GETUPVAL,/* A B R(A) := UpValue[B] */ | 180 | OP_GETUPVAL,/* A B R(A) := UpValue[B] */ |
181 | OP_SETUPVAL,/* A B UpValue[B] := R(A) */ | ||
181 | 182 | ||
182 | OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */ | 183 | OP_GETTABUP,/* A B C R(A) := UpValue[B][K(C):string] */ |
183 | OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */ | 184 | OP_GETTABLE,/* A B C R(A) := R(B)[R(C)] */ |
185 | OP_GETI,/* A B C R(A) := R(B)[C] */ | ||
186 | OP_GETFIELD,/* A B C R(A) := R(B)[Kst(C):string] */ | ||
184 | 187 | ||
185 | OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */ | 188 | OP_SETTABUP,/* A B C UpValue[A][K(B):string] := RK(C) */ |
186 | OP_SETUPVAL,/* A B UpValue[B] := R(A) */ | 189 | OP_SETTABLE,/* A B C R(A)[R(B)] := RK(C) */ |
187 | OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */ | 190 | OP_SETI,/* A B C R(A)[B] := RK(C) */ |
191 | OP_SETFIELD,/* A B C R(A)[K(B):string] := RK(C) */ | ||
188 | 192 | ||
189 | OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */ | 193 | OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */ |
190 | 194 | ||
191 | OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */ | 195 | OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C):string] */ |
192 | 196 | ||
193 | OP_ADDI,/* A B C R(A) := R(B) + C */ | 197 | OP_ADDI,/* A B C R(A) := R(B) + C */ |
194 | OP_ADD,/* A B C R(A) := RK(B) + RK(C) */ | 198 | OP_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 | ||
@@ -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"); |
@@ -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 | ||
54 | typedef struct expdesc { | 63 | typedef 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' */ |
@@ -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); |