mirror of https://github.com/rusefi/lua.git
new opcodes for table access with constant keys (strings and integers)
This commit is contained in:
parent
173e41b2eb
commit
502a1d1108
76
lcode.c
76
lcode.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lcode.c,v 2.116 2017/04/25 20:01:14 roberto Exp roberto $
|
** $Id: lcode.c,v 2.117 2017/04/26 17:46:52 roberto Exp roberto $
|
||||||
** Code generator for Lua
|
** Code generator for Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -580,18 +580,26 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
|
||||||
e->k = VRELOCABLE;
|
e->k = VRELOCABLE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case VINDEXUP: {
|
||||||
|
e->u.info = luaK_codeABC(fs, OP_GETTABUP, 0, e->u.ind.t, e->u.ind.idx);
|
||||||
|
e->k = VRELOCABLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VINDEXI: {
|
||||||
|
freereg(fs, e->u.ind.t);
|
||||||
|
e->u.info = luaK_codeABC(fs, OP_GETI, 0, e->u.ind.t, e->u.ind.idx);
|
||||||
|
e->k = VRELOCABLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VINDEXSTR: {
|
||||||
|
freereg(fs, e->u.ind.t);
|
||||||
|
e->u.info = luaK_codeABC(fs, OP_GETFIELD, 0, e->u.ind.t, e->u.ind.idx);
|
||||||
|
e->k = VRELOCABLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case VINDEXED: {
|
case VINDEXED: {
|
||||||
OpCode op;
|
freeregs(fs, e->u.ind.t, e->u.ind.idx);
|
||||||
if (e->u.ind.vt == VLOCAL) { /* is 't' in a register? */
|
e->u.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.ind.t, e->u.ind.idx);
|
||||||
freeregs(fs, e->u.ind.t, e->u.ind.idx);
|
|
||||||
op = OP_GETTABLE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
lua_assert(e->u.ind.vt == VUPVAL);
|
|
||||||
freereg(fs, e->u.ind.idx);
|
|
||||||
op = OP_GETTABUP; /* 't' is in an upvalue */
|
|
||||||
}
|
|
||||||
e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx);
|
|
||||||
e->k = VRELOCABLE;
|
e->k = VRELOCABLE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -807,10 +815,24 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
|
||||||
luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0);
|
luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VINDEXED: {
|
case VINDEXUP: {
|
||||||
OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP;
|
|
||||||
int e = luaK_exp2RK(fs, ex);
|
int e = luaK_exp2RK(fs, ex);
|
||||||
luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e);
|
luaK_codeABC(fs, OP_SETTABUP, var->u.ind.t, var->u.ind.idx, e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VINDEXI: {
|
||||||
|
int e = luaK_exp2RK(fs, ex);
|
||||||
|
luaK_codeABC(fs, OP_SETI, var->u.ind.t, var->u.ind.idx, e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VINDEXSTR: {
|
||||||
|
int e = luaK_exp2RK(fs, ex);
|
||||||
|
luaK_codeABC(fs, OP_SETFIELD, var->u.ind.t, var->u.ind.idx, e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case VINDEXED: {
|
||||||
|
int e = luaK_exp2RK(fs, ex);
|
||||||
|
luaK_codeABC(fs, OP_SETTABLE, var->u.ind.t, var->u.ind.idx, e);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: lua_assert(0); /* invalid var kind to store */
|
default: lua_assert(0); /* invalid var kind to store */
|
||||||
|
@ -959,7 +981,8 @@ static void codenot (FuncState *fs, expdesc *e) {
|
||||||
** Check whether expression 'e' is a literal string
|
** Check whether expression 'e' is a literal string
|
||||||
*/
|
*/
|
||||||
static int isKstr (FuncState *fs, expdesc *e) {
|
static int isKstr (FuncState *fs, expdesc *e) {
|
||||||
return (e->k == VK && ttisstring(&fs->f->k[e->u.info]));
|
return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_C &&
|
||||||
|
ttisstring(&fs->f->k[e->u.info]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -976,15 +999,30 @@ static int isKint (expdesc *e) {
|
||||||
/*
|
/*
|
||||||
** Create expression 't[k]'. 't' must have its final result already in a
|
** Create expression 't[k]'. 't' must have its final result already in a
|
||||||
** register or upvalue. Upvalues can only be indexed by literal strings.
|
** register or upvalue. Upvalues can only be indexed by literal strings.
|
||||||
|
** Keys can be literal strings in the constant table or arbitrary
|
||||||
|
** values in registers.
|
||||||
*/
|
*/
|
||||||
void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
|
void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
|
||||||
lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL));
|
lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL));
|
||||||
if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non string? */
|
if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non string? */
|
||||||
luaK_exp2anyreg(fs, t); /* put it in a register */
|
luaK_exp2anyreg(fs, t); /* put it in a register */
|
||||||
t->u.ind.t = t->u.info; /* register or upvalue index */
|
t->u.ind.t = t->u.info; /* register or upvalue index */
|
||||||
t->u.ind.idx = luaK_exp2RK(fs, k); /* R/K index for key */
|
if (t->k == VUPVAL) {
|
||||||
t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL : VLOCAL;
|
t->u.ind.idx = k->u.info; /* literal string */
|
||||||
t->k = VINDEXED;
|
t->k = VINDEXUP;
|
||||||
|
}
|
||||||
|
else if (isKstr(fs, k)) {
|
||||||
|
t->u.ind.idx = k->u.info; /* literal string */
|
||||||
|
t->k = VINDEXSTR;
|
||||||
|
}
|
||||||
|
else if (isKint(k)) {
|
||||||
|
t->u.ind.idx = k->u.ival; /* integer constant */
|
||||||
|
t->k = VINDEXI;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
t->u.ind.idx = luaK_exp2anyreg(fs, k); /* register */
|
||||||
|
t->k = VINDEXED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
92
ldebug.c
92
ldebug.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: ldebug.c,v 2.121 2016/10/19 12:32:10 roberto Exp roberto $
|
** $Id: ldebug.c,v 2.122 2017/04/26 17:46:52 roberto Exp roberto $
|
||||||
** Debug Interface
|
** Debug Interface
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -350,28 +350,36 @@ static const char *getobjname (Proto *p, int lastpc, int reg,
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** find a "name" for the RK value 'c'
|
** Find a "name" for the constant 'c'.
|
||||||
*/
|
*/
|
||||||
static void kname (Proto *p, int pc, int c, const char **name) {
|
static void kname (Proto *p, int c, const char **name) {
|
||||||
if (ISK(c)) { /* is 'c' a constant? */
|
TValue *kvalue = &p->k[INDEXK(c)];
|
||||||
TValue *kvalue = &p->k[INDEXK(c)];
|
*name = (ttisstring(kvalue)) ? svalue(kvalue) : "?";
|
||||||
if (ttisstring(kvalue)) { /* literal constant? */
|
|
||||||
*name = svalue(kvalue); /* it is its own name */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* else no reasonable name found */
|
|
||||||
}
|
|
||||||
else { /* 'c' is a register */
|
|
||||||
const char *what = getobjname(p, pc, c, name); /* search for 'c' */
|
|
||||||
if (what && *what == 'c') { /* found a constant name? */
|
|
||||||
return; /* 'name' already filled */
|
|
||||||
}
|
|
||||||
/* else no reasonable name found */
|
|
||||||
}
|
|
||||||
*name = "?"; /* no reasonable name found */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Find a "name" for the register 'c'.
|
||||||
|
*/
|
||||||
|
static void rname (Proto *p, int pc, int c, const char **name) {
|
||||||
|
const char *what = getobjname(p, pc, c, name); /* search for 'c' */
|
||||||
|
if (!(what && *what == 'c')) /* did not find a constant name? */
|
||||||
|
*name = "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Find a "name" for the R/K index 'c'.
|
||||||
|
*/
|
||||||
|
static void rkname (Proto *p, int pc, int c, const char **name) {
|
||||||
|
if (ISK(c)) /* is 'c' a constant? */
|
||||||
|
kname(p, INDEXK(c), name);
|
||||||
|
else /* 'c' is a register */
|
||||||
|
rname(p, pc, c, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int filterpc (int pc, int jmptarget) {
|
static int filterpc (int pc, int jmptarget) {
|
||||||
if (pc < jmptarget) /* is code conditional (inside a jump)? */
|
if (pc < jmptarget) /* is code conditional (inside a jump)? */
|
||||||
return -1; /* cannot know who sets that register */
|
return -1; /* cannot know who sets that register */
|
||||||
|
@ -428,8 +436,22 @@ static int findsetreg (Proto *p, int lastpc, int reg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *getobjname (Proto *p, int lastpc, int reg,
|
/*
|
||||||
const char **name) {
|
** Check whether table being indexed by instruction 'i' is the
|
||||||
|
** environment '_ENV'
|
||||||
|
*/
|
||||||
|
static const char *gxf (Proto *p, int pc, Instruction i, int isup) {
|
||||||
|
int t = GETARG_B(i); /* table index */
|
||||||
|
const char *name; /* name of indexed variable */
|
||||||
|
if (isup) /* is an upvalue? */
|
||||||
|
name = upvalname(p, t);
|
||||||
|
else
|
||||||
|
getobjname(p, pc, t, &name);
|
||||||
|
return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *getobjname (Proto *p, int lastpc, int reg, const char **name) {
|
||||||
int pc;
|
int pc;
|
||||||
*name = luaF_getlocalname(p, reg + 1, lastpc);
|
*name = luaF_getlocalname(p, reg + 1, lastpc);
|
||||||
if (*name) /* is a local? */
|
if (*name) /* is a local? */
|
||||||
|
@ -446,15 +468,24 @@ static const char *getobjname (Proto *p, int lastpc, int reg,
|
||||||
return getobjname(p, pc, b, name); /* get name for 'b' */
|
return getobjname(p, pc, b, name); /* get name for 'b' */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_GETTABUP:
|
case OP_GETTABUP: {
|
||||||
|
int k = GETARG_C(i); /* key index */
|
||||||
|
kname(p, k, name);
|
||||||
|
return gxf(p, pc, i, 1);
|
||||||
|
}
|
||||||
case OP_GETTABLE: {
|
case OP_GETTABLE: {
|
||||||
int k = GETARG_C(i); /* key index */
|
int k = GETARG_C(i); /* key index */
|
||||||
int t = GETARG_B(i); /* table index */
|
rname(p, pc, k, name);
|
||||||
const char *vn = (op == OP_GETTABLE) /* name of indexed variable */
|
return gxf(p, pc, i, 0);
|
||||||
? luaF_getlocalname(p, t + 1, pc)
|
}
|
||||||
: upvalname(p, t);
|
case OP_GETI: {
|
||||||
kname(p, pc, k, name);
|
*name = "integer index";
|
||||||
return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field";
|
return "field";
|
||||||
|
}
|
||||||
|
case OP_GETFIELD: {
|
||||||
|
int k = GETARG_C(i); /* key index */
|
||||||
|
kname(p, k, name);
|
||||||
|
return gxf(p, pc, i, 0);
|
||||||
}
|
}
|
||||||
case OP_GETUPVAL: {
|
case OP_GETUPVAL: {
|
||||||
*name = upvalname(p, GETARG_B(i));
|
*name = upvalname(p, GETARG_B(i));
|
||||||
|
@ -472,7 +503,7 @@ static const char *getobjname (Proto *p, int lastpc, int reg,
|
||||||
}
|
}
|
||||||
case OP_SELF: {
|
case OP_SELF: {
|
||||||
int k = GETARG_C(i); /* key index */
|
int k = GETARG_C(i); /* key index */
|
||||||
kname(p, pc, k, name);
|
rkname(p, pc, k, name);
|
||||||
return "method";
|
return "method";
|
||||||
}
|
}
|
||||||
default: break; /* go through to return NULL */
|
default: break; /* go through to return NULL */
|
||||||
|
@ -508,9 +539,10 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
|
||||||
}
|
}
|
||||||
/* other instructions can do calls through metamethods */
|
/* other instructions can do calls through metamethods */
|
||||||
case OP_SELF: case OP_GETTABUP: case OP_GETTABLE:
|
case OP_SELF: case OP_GETTABUP: case OP_GETTABLE:
|
||||||
|
case OP_GETI: case OP_GETFIELD:
|
||||||
tm = TM_INDEX;
|
tm = TM_INDEX;
|
||||||
break;
|
break;
|
||||||
case OP_SETTABUP: case OP_SETTABLE:
|
case OP_SETTABUP: case OP_SETTABLE: case OP_SETI: case OP_SETFIELD:
|
||||||
tm = TM_NEWINDEX;
|
tm = TM_NEWINDEX;
|
||||||
break;
|
break;
|
||||||
case OP_ADDI:
|
case OP_ADDI:
|
||||||
|
|
20
lopcodes.c
20
lopcodes.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lopcodes.c,v 1.56 2017/04/20 19:53:55 roberto Exp roberto $
|
** $Id: lopcodes.c,v 1.57 2017/04/26 17:46:52 roberto Exp roberto $
|
||||||
** Opcodes for Lua virtual machine
|
** Opcodes for Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -25,11 +25,15 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
|
||||||
"LOADBOOL",
|
"LOADBOOL",
|
||||||
"LOADNIL",
|
"LOADNIL",
|
||||||
"GETUPVAL",
|
"GETUPVAL",
|
||||||
|
"SETUPVAL",
|
||||||
"GETTABUP",
|
"GETTABUP",
|
||||||
"GETTABLE",
|
"GETTABLE",
|
||||||
|
"GETI",
|
||||||
|
"GETFIELD",
|
||||||
"SETTABUP",
|
"SETTABUP",
|
||||||
"SETUPVAL",
|
|
||||||
"SETTABLE",
|
"SETTABLE",
|
||||||
|
"SETI",
|
||||||
|
"SETFIELD",
|
||||||
"NEWTABLE",
|
"NEWTABLE",
|
||||||
"SELF",
|
"SELF",
|
||||||
"ADDI",
|
"ADDI",
|
||||||
|
@ -82,11 +86,15 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
||||||
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
|
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */
|
||||||
,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */
|
,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */
|
||||||
,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
|
,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */
|
||||||
,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */
|
|
||||||
,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */
|
|
||||||
,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */
|
|
||||||
,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
|
,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
|
||||||
,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */
|
,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */
|
||||||
|
,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_GETTABLE */
|
||||||
|
,opmode(0, 1, OpArgR, OpArgU, iABC) /* OP_GETI */
|
||||||
|
,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETFIELD */
|
||||||
|
,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */
|
||||||
|
,opmode(0, 0, OpArgR, OpArgK, iABC) /* OP_SETTABLE */
|
||||||
|
,opmode(0, 0, OpArgU, OpArgK, iABC) /* OP_SETI */
|
||||||
|
,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETFIELD */
|
||||||
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */
|
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */
|
||||||
,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */
|
,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */
|
||||||
,opmode(0, 1, OpArgR, OpArgU, iABC) /* OP_ADDI */
|
,opmode(0, 1, OpArgR, OpArgU, iABC) /* OP_ADDI */
|
||||||
|
|
22
lopcodes.h
22
lopcodes.h
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lopcodes.h,v 1.151 2017/04/24 20:26:39 roberto Exp roberto $
|
** $Id: lopcodes.h,v 1.152 2017/04/26 17:46:52 roberto Exp roberto $
|
||||||
** Opcodes for Lua virtual machine
|
** Opcodes for Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -178,17 +178,21 @@ OP_LOADKX,/* A R(A) := Kst(extra arg) */
|
||||||
OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
|
OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
|
||||||
OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */
|
OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */
|
||||||
OP_GETUPVAL,/* A B R(A) := UpValue[B] */
|
OP_GETUPVAL,/* A B R(A) := UpValue[B] */
|
||||||
|
|
||||||
OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */
|
|
||||||
OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
|
|
||||||
|
|
||||||
OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */
|
|
||||||
OP_SETUPVAL,/* A B UpValue[B] := R(A) */
|
OP_SETUPVAL,/* A B UpValue[B] := R(A) */
|
||||||
OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
|
|
||||||
|
OP_GETTABUP,/* A B C R(A) := UpValue[B][K(C):string] */
|
||||||
|
OP_GETTABLE,/* A B C R(A) := R(B)[R(C)] */
|
||||||
|
OP_GETI,/* A B C R(A) := R(B)[C] */
|
||||||
|
OP_GETFIELD,/* A B C R(A) := R(B)[Kst(C):string] */
|
||||||
|
|
||||||
|
OP_SETTABUP,/* A B C UpValue[A][K(B):string] := RK(C) */
|
||||||
|
OP_SETTABLE,/* A B C R(A)[R(B)] := RK(C) */
|
||||||
|
OP_SETI,/* A B C R(A)[B] := RK(C) */
|
||||||
|
OP_SETFIELD,/* A B C R(A)[K(B):string] := RK(C) */
|
||||||
|
|
||||||
OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
|
OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
|
||||||
|
|
||||||
OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
|
OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C):string] */
|
||||||
|
|
||||||
OP_ADDI,/* A B C R(A) := R(B) + C */
|
OP_ADDI,/* A B C R(A) := R(B) + C */
|
||||||
OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
|
OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
|
||||||
|
@ -259,8 +263,6 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
|
||||||
|
|
||||||
(*) In OP_LOADKX, the next 'instruction' is always EXTRAARG.
|
(*) In OP_LOADKX, the next 'instruction' is always EXTRAARG.
|
||||||
|
|
||||||
(*) In OP_GETTABUP, OP_SETTABUP, and OP_SELF, the index must be a string.
|
|
||||||
|
|
||||||
(*) For comparisons, A specifies what condition the test should accept
|
(*) For comparisons, A specifies what condition the test should accept
|
||||||
(true or false).
|
(true or false).
|
||||||
|
|
||||||
|
|
40
lparser.c
40
lparser.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lparser.c,v 2.155 2016/08/01 19:51:24 roberto Exp roberto $
|
** $Id: lparser.c,v 2.156 2017/04/20 19:53:55 roberto Exp roberto $
|
||||||
** Lua Parser
|
** Lua Parser
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -647,8 +647,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) {
|
||||||
/* recfield -> (NAME | '['exp1']') = exp1 */
|
/* recfield -> (NAME | '['exp1']') = exp1 */
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
int reg = ls->fs->freereg;
|
int reg = ls->fs->freereg;
|
||||||
expdesc key, val;
|
expdesc tab, key, val;
|
||||||
int rkkey;
|
|
||||||
if (ls->t.token == TK_NAME) {
|
if (ls->t.token == TK_NAME) {
|
||||||
checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
|
checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
|
||||||
checkname(ls, &key);
|
checkname(ls, &key);
|
||||||
|
@ -657,9 +656,10 @@ static void recfield (LexState *ls, struct ConsControl *cc) {
|
||||||
yindex(ls, &key);
|
yindex(ls, &key);
|
||||||
cc->nh++;
|
cc->nh++;
|
||||||
checknext(ls, '=');
|
checknext(ls, '=');
|
||||||
rkkey = luaK_exp2RK(fs, &key);
|
tab = *cc->t;
|
||||||
|
luaK_indexed(fs, &tab, &key);
|
||||||
expr(ls, &val);
|
expr(ls, &val);
|
||||||
luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val));
|
luaK_storevar(fs, &tab, &val);
|
||||||
fs->freereg = reg; /* free registers */
|
fs->freereg = reg; /* free registers */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1121,17 +1121,25 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
|
||||||
int extra = fs->freereg; /* eventual position to save local variable */
|
int extra = fs->freereg; /* eventual position to save local variable */
|
||||||
int conflict = 0;
|
int conflict = 0;
|
||||||
for (; lh; lh = lh->prev) { /* check all previous assignments */
|
for (; lh; lh = lh->prev) { /* check all previous assignments */
|
||||||
if (lh->v.k == VINDEXED) { /* assigning to a table? */
|
if (vkisindexed(lh->v.k)) { /* assignment to table field? */
|
||||||
/* table is the upvalue/local being assigned now? */
|
if (lh->v.k == VINDEXUP) { /* is table an upvalue? */
|
||||||
if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) {
|
if (v->k == VUPVAL && lh->v.u.ind.t == v->u.info) {
|
||||||
conflict = 1;
|
conflict = 1; /* table is the upvalue being assigned now */
|
||||||
lh->v.u.ind.vt = VLOCAL;
|
lh->v.k = VINDEXSTR;
|
||||||
lh->v.u.ind.t = extra; /* previous assignment will use safe copy */
|
lh->v.u.ind.t = extra; /* assignment will use safe copy */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* index is the local being assigned? (index cannot be upvalue) */
|
else { /* table is a register */
|
||||||
if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) {
|
if (v->k == VLOCAL && lh->v.u.ind.t == v->u.info) {
|
||||||
conflict = 1;
|
conflict = 1; /* table is the local being assigned now */
|
||||||
lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */
|
lh->v.u.ind.t = extra; /* assignment will use safe copy */
|
||||||
|
}
|
||||||
|
/* is index the local being assigned? */
|
||||||
|
if (lh->v.k == VINDEXED && 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 */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1151,7 +1159,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
|
||||||
struct LHS_assign nv;
|
struct LHS_assign nv;
|
||||||
nv.prev = lh;
|
nv.prev = lh;
|
||||||
suffixedexp(ls, &nv.v);
|
suffixedexp(ls, &nv.v);
|
||||||
if (nv.v.k != VINDEXED)
|
if (!vkisindexed(nv.v.k))
|
||||||
check_conflict(ls, lh, &nv.v);
|
check_conflict(ls, lh, &nv.v);
|
||||||
checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS,
|
checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS,
|
||||||
"C levels");
|
"C levels");
|
||||||
|
|
24
lparser.h
24
lparser.h
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lparser.h,v 1.75 2015/12/17 15:44:50 roberto Exp roberto $
|
** $Id: lparser.h,v 1.76 2015/12/30 18:16:13 roberto Exp roberto $
|
||||||
** Lua Parser
|
** Lua Parser
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -36,9 +36,17 @@ typedef enum {
|
||||||
VLOCAL, /* local variable; info = local register */
|
VLOCAL, /* local variable; info = local register */
|
||||||
VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
|
VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */
|
||||||
VINDEXED, /* indexed variable;
|
VINDEXED, /* indexed variable;
|
||||||
ind.vt = whether 't' is register or upvalue;
|
ind.t = table register;
|
||||||
ind.t = table register or upvalue;
|
ind.idx = key's R index */
|
||||||
ind.idx = key's R/K index */
|
VINDEXUP, /* indexed upvalue;
|
||||||
|
ind.t = table upvalue;
|
||||||
|
ind.idx = key's K index */
|
||||||
|
VINDEXI, /* indexed variable with constant integer;
|
||||||
|
ind.t = table register;
|
||||||
|
ind.idx = key's value */
|
||||||
|
VINDEXSTR, /* indexed variable with literal string;
|
||||||
|
ind.t = table register;
|
||||||
|
ind.idx = key's K index */
|
||||||
VJMP, /* expression is a test/comparison;
|
VJMP, /* expression is a test/comparison;
|
||||||
info = pc of corresponding jump instruction */
|
info = pc of corresponding jump instruction */
|
||||||
VRELOCABLE, /* expression can put result in any register;
|
VRELOCABLE, /* expression can put result in any register;
|
||||||
|
@ -48,7 +56,8 @@ typedef enum {
|
||||||
} expkind;
|
} expkind;
|
||||||
|
|
||||||
|
|
||||||
#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED)
|
#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXSTR)
|
||||||
|
#define vkisindexed(k) (VINDEXED <= (k) && (k) <= VINDEXSTR)
|
||||||
#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL)
|
#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL)
|
||||||
|
|
||||||
typedef struct expdesc {
|
typedef struct expdesc {
|
||||||
|
@ -57,10 +66,9 @@ typedef struct expdesc {
|
||||||
lua_Integer ival; /* for VKINT */
|
lua_Integer ival; /* for VKINT */
|
||||||
lua_Number nval; /* for VKFLT */
|
lua_Number nval; /* for VKFLT */
|
||||||
int info; /* for generic use */
|
int info; /* for generic use */
|
||||||
struct { /* for indexed variables (VINDEXED) */
|
struct { /* for indexed variables */
|
||||||
short idx; /* index (R/K) */
|
short idx; /* index (R or "long" K) */
|
||||||
lu_byte t; /* table (register or upvalue) */
|
lu_byte t; /* table (register or upvalue) */
|
||||||
lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
|
|
||||||
} ind;
|
} ind;
|
||||||
} u;
|
} u;
|
||||||
int t; /* patch list of 'exit when true' */
|
int t; /* patch list of 'exit when true' */
|
||||||
|
|
76
lvm.c
76
lvm.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lvm.c,v 2.272 2017/04/24 20:26:39 roberto Exp roberto $
|
** $Id: lvm.c,v 2.273 2017/04/26 17:46:52 roberto Exp roberto $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -658,11 +658,13 @@ void luaV_finishOp (lua_State *L) {
|
||||||
Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */
|
Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */
|
||||||
OpCode op = GET_OPCODE(inst);
|
OpCode op = GET_OPCODE(inst);
|
||||||
switch (op) { /* finish its execution */
|
switch (op) { /* finish its execution */
|
||||||
case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV:
|
case OP_ADDI: case OP_ADD: case OP_SUB:
|
||||||
|
case OP_MUL: case OP_DIV: case OP_IDIV:
|
||||||
case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR:
|
case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR:
|
||||||
case OP_MOD: case OP_POW:
|
case OP_MOD: case OP_POW:
|
||||||
case OP_UNM: case OP_BNOT: case OP_LEN:
|
case OP_UNM: case OP_BNOT: case OP_LEN:
|
||||||
case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: {
|
case OP_GETTABUP: case OP_GETTABLE: case OP_GETI:
|
||||||
|
case OP_GETFIELD: case OP_SELF: {
|
||||||
setobjs2s(L, base + GETARG_A(inst), --L->top);
|
setobjs2s(L, base + GETARG_A(inst), --L->top);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -704,6 +706,7 @@ void luaV_finishOp (lua_State *L) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE:
|
case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE:
|
||||||
|
case OP_SETI: case OP_SETFIELD:
|
||||||
break;
|
break;
|
||||||
default: lua_assert(0);
|
default: lua_assert(0);
|
||||||
}
|
}
|
||||||
|
@ -726,7 +729,9 @@ void luaV_finishOp (lua_State *L) {
|
||||||
|
|
||||||
#define RA(i) (base+GETARG_A(i))
|
#define RA(i) (base+GETARG_A(i))
|
||||||
#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_Br(i))
|
#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_Br(i))
|
||||||
|
#define KB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_B(i))
|
||||||
#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
|
#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
|
||||||
|
#define KC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, k+GETARG_C(i))
|
||||||
#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
|
#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
|
||||||
(GETARG_Bk(i)) ? k+GETARG_Br(i) : base+GETARG_Br(i))
|
(GETARG_Bk(i)) ? k+GETARG_Br(i) : base+GETARG_Br(i))
|
||||||
#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
|
#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
|
||||||
|
@ -837,10 +842,16 @@ void luaV_execute (lua_State *L) {
|
||||||
setobj2s(L, ra, cl->upvals[b]->v);
|
setobj2s(L, ra, cl->upvals[b]->v);
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
|
vmcase(OP_SETUPVAL) {
|
||||||
|
UpVal *uv = cl->upvals[GETARG_B(i)];
|
||||||
|
setobj(L, uv->v, ra);
|
||||||
|
luaC_barrier(L, uv, ra);
|
||||||
|
vmbreak;
|
||||||
|
}
|
||||||
vmcase(OP_GETTABUP) {
|
vmcase(OP_GETTABUP) {
|
||||||
const TValue *slot;
|
const TValue *slot;
|
||||||
TValue *upval = cl->upvals[GETARG_B(i)]->v;
|
TValue *upval = cl->upvals[GETARG_B(i)]->v;
|
||||||
TValue *rc = RKC(i);
|
TValue *rc = KC(i);
|
||||||
TString *key = tsvalue(rc); /* key must be a string */
|
TString *key = tsvalue(rc); /* key must be a string */
|
||||||
if (luaV_fastget(L, upval, key, slot, luaH_getstr)) {
|
if (luaV_fastget(L, upval, key, slot, luaH_getstr)) {
|
||||||
setobj2s(L, ra, slot);
|
setobj2s(L, ra, slot);
|
||||||
|
@ -850,32 +861,71 @@ void luaV_execute (lua_State *L) {
|
||||||
}
|
}
|
||||||
vmcase(OP_GETTABLE) {
|
vmcase(OP_GETTABLE) {
|
||||||
StkId rb = RB(i);
|
StkId rb = RB(i);
|
||||||
TValue *rc = RKC(i);
|
TValue *rc = RC(i);
|
||||||
gettableProtected(L, rb, rc, ra);
|
gettableProtected(L, rb, rc, ra);
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
|
vmcase(OP_GETI) {
|
||||||
|
const TValue *slot;
|
||||||
|
StkId rb = RB(i);
|
||||||
|
int c = GETARG_C(i);
|
||||||
|
if (luaV_fastget(L, rb, c, slot, luaH_getint)) {
|
||||||
|
setobj2s(L, ra, slot);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TValue key;
|
||||||
|
setivalue(&key, c);
|
||||||
|
Protect(luaV_finishget(L, rb, &key, ra, slot));
|
||||||
|
}
|
||||||
|
vmbreak;
|
||||||
|
}
|
||||||
|
vmcase(OP_GETFIELD) {
|
||||||
|
const TValue *slot;
|
||||||
|
StkId rb = RB(i);
|
||||||
|
TValue *rc = KC(i);
|
||||||
|
TString *key = tsvalue(rc); /* key must be a string */
|
||||||
|
if (luaV_fastget(L, rb, key, slot, luaH_getstr)) {
|
||||||
|
setobj2s(L, ra, slot);
|
||||||
|
}
|
||||||
|
else Protect(luaV_finishget(L, rb, rc, ra, slot));
|
||||||
|
vmbreak;
|
||||||
|
}
|
||||||
vmcase(OP_SETTABUP) {
|
vmcase(OP_SETTABUP) {
|
||||||
const TValue *slot;
|
const TValue *slot;
|
||||||
TValue *upval = cl->upvals[GETARG_A(i)]->v;
|
TValue *upval = cl->upvals[GETARG_A(i)]->v;
|
||||||
TValue *rb = RKB(i);
|
TValue *rb = KB(i);
|
||||||
TValue *rc = RKC(i);
|
TValue *rc = RKC(i);
|
||||||
TString *key = tsvalue(rb); /* key must be a string */
|
TString *key = tsvalue(rb); /* key must be a string */
|
||||||
if (!luaV_fastset(L, upval, key, slot, luaH_getstr, rc))
|
if (!luaV_fastset(L, upval, key, slot, luaH_getstr, rc))
|
||||||
Protect(luaV_finishset(L, upval, rb, rc, slot));
|
Protect(luaV_finishset(L, upval, rb, rc, slot));
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
vmcase(OP_SETUPVAL) {
|
|
||||||
UpVal *uv = cl->upvals[GETARG_B(i)];
|
|
||||||
setobj(L, uv->v, ra);
|
|
||||||
luaC_barrier(L, uv, ra);
|
|
||||||
vmbreak;
|
|
||||||
}
|
|
||||||
vmcase(OP_SETTABLE) {
|
vmcase(OP_SETTABLE) {
|
||||||
TValue *rb = RKB(i);
|
TValue *rb = RB(i);
|
||||||
TValue *rc = RKC(i);
|
TValue *rc = RKC(i);
|
||||||
settableProtected(L, ra, rb, rc);
|
settableProtected(L, ra, rb, rc);
|
||||||
vmbreak;
|
vmbreak;
|
||||||
}
|
}
|
||||||
|
vmcase(OP_SETI) {
|
||||||
|
const TValue *slot;
|
||||||
|
int c = GETARG_B(i);
|
||||||
|
TValue *rc = RKC(i);
|
||||||
|
if (!luaV_fastset(L, ra, c, slot, luaH_getint, rc)) {
|
||||||
|
TValue key;
|
||||||
|
setivalue(&key, c);
|
||||||
|
Protect(luaV_finishset(L, ra, &key, rc, slot));
|
||||||
|
}
|
||||||
|
vmbreak;
|
||||||
|
}
|
||||||
|
vmcase(OP_SETFIELD) {
|
||||||
|
const TValue *slot;
|
||||||
|
TValue *rb = KB(i);
|
||||||
|
TValue *rc = RKC(i);
|
||||||
|
TString *key = tsvalue(rb); /* key must be a string */
|
||||||
|
if (!luaV_fastset(L, ra, key, slot, luaH_getstr, rc))
|
||||||
|
Protect(luaV_finishset(L, ra, rb, rc, slot));
|
||||||
|
vmbreak;
|
||||||
|
}
|
||||||
vmcase(OP_NEWTABLE) {
|
vmcase(OP_NEWTABLE) {
|
||||||
int b = GETARG_B(i);
|
int b = GETARG_B(i);
|
||||||
int c = GETARG_C(i);
|
int c = GETARG_C(i);
|
||||||
|
|
Loading…
Reference in New Issue