Fixed initialization of global variables
When calling 'luaK_storevar', the 'expdesc' for the variable must be created before the one for the expression, to satisfy the assumptions for register allocation. So, in a statement like 'global a = exp', where 'a' is actually '_ENV.a', this variable must be handled before the initializing expression 'exp'.
This commit is contained in:
2
lcode.c
2
lcode.c
@@ -1242,7 +1242,7 @@ static void codenot (FuncState *fs, expdesc *e) {
|
|||||||
** Check whether expression 'e' is a short literal string
|
** Check whether expression 'e' is a short literal string
|
||||||
*/
|
*/
|
||||||
static int isKstr (FuncState *fs, expdesc *e) {
|
static int isKstr (FuncState *fs, expdesc *e) {
|
||||||
return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_B &&
|
return (e->k == VK && !hasjumps(e) && e->u.info <= MAXINDEXRK &&
|
||||||
ttisshrstring(&fs->f->k[e->u.info]));
|
ttisshrstring(&fs->f->k[e->u.info]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
41
lparser.c
41
lparser.c
@@ -1875,6 +1875,33 @@ static lu_byte getglobalattribute (LexState *ls, lu_byte df) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Recursively traverse list of globals to be initalized. When
|
||||||
|
** going, generate table description for the global. In the end,
|
||||||
|
** after all indices have been generated, read list of initializing
|
||||||
|
** expressions. When returning, generate the assignment of the value on
|
||||||
|
** the stack to the corresponding table description. 'n' is the variable
|
||||||
|
** being handled, range [0, nvars - 1].
|
||||||
|
*/
|
||||||
|
static void initglobal (LexState *ls, int nvars, int firstidx, int n) {
|
||||||
|
if (n == nvars) { /* traversed all variables? */
|
||||||
|
expdesc e;
|
||||||
|
int nexps = explist(ls, &e); /* read list of expressions */
|
||||||
|
adjust_assign(ls, nvars, nexps, &e);
|
||||||
|
}
|
||||||
|
else { /* handle variable 'n' */
|
||||||
|
FuncState *fs = ls->fs;
|
||||||
|
expdesc var;
|
||||||
|
TString *varname = getlocalvardesc(fs, firstidx + n)->vd.name;
|
||||||
|
buildglobal(ls, varname, &var); /* create global variable in 'var' */
|
||||||
|
enterlevel(ls); /* control recursion depth */
|
||||||
|
initglobal(ls, nvars, firstidx, n + 1);
|
||||||
|
leavelevel(ls);
|
||||||
|
storevartop(fs, &var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void globalnames (LexState *ls, lu_byte defkind) {
|
static void globalnames (LexState *ls, lu_byte defkind) {
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
int nvars = 0;
|
int nvars = 0;
|
||||||
@@ -1885,18 +1912,8 @@ static void globalnames (LexState *ls, lu_byte defkind) {
|
|||||||
lastidx = new_varkind(ls, vname, kind);
|
lastidx = new_varkind(ls, vname, kind);
|
||||||
nvars++;
|
nvars++;
|
||||||
} while (testnext(ls, ','));
|
} while (testnext(ls, ','));
|
||||||
if (testnext(ls, '=')) { /* initialization? */
|
if (testnext(ls, '=')) /* initialization? */
|
||||||
expdesc e;
|
initglobal(ls, nvars, lastidx - nvars + 1, 0);
|
||||||
int i;
|
|
||||||
int nexps = explist(ls, &e); /* read list of expressions */
|
|
||||||
adjust_assign(ls, nvars, nexps, &e);
|
|
||||||
for (i = 0; i < nvars; i++) { /* for each variable */
|
|
||||||
expdesc var;
|
|
||||||
TString *varname = getlocalvardesc(fs, lastidx - i)->vd.name;
|
|
||||||
buildglobal(ls, varname, &var); /* create global variable in 'var' */
|
|
||||||
storevartop(fs, &var);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fs->nactvar = cast_short(fs->nactvar + nvars); /* activate declaration */
|
fs->nactvar = cast_short(fs->nactvar + nvars); /* activate declaration */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -432,5 +432,27 @@ do print "testing initialization in global declarations"
|
|||||||
_ENV.a, _ENV.b, _ENV.c, _ENV.d = nil -- erase these globals
|
_ENV.a, _ENV.b, _ENV.c, _ENV.d = nil -- erase these globals
|
||||||
end
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
global table, string
|
||||||
|
-- global initialization when names don't fit in K
|
||||||
|
|
||||||
|
-- to fill constant table
|
||||||
|
local code = {}
|
||||||
|
for i = 1, 300 do code[i] = "'" .. i .. "'" end
|
||||||
|
code = table.concat(code, ",")
|
||||||
|
code = string.format([[
|
||||||
|
return function (_ENV)
|
||||||
|
local dummy = {%s} -- fill initial positions in constant table,
|
||||||
|
-- so that initialization must use registers for global names
|
||||||
|
global a, b, c = 10, 20, 30
|
||||||
|
end]], code)
|
||||||
|
|
||||||
|
local fun = assert(load(code))()
|
||||||
|
|
||||||
|
local env = {}
|
||||||
|
fun(env)
|
||||||
|
assert(env.a == 10 and env.b == 20 and env.c == 30)
|
||||||
|
end
|
||||||
|
|
||||||
print'OK'
|
print'OK'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user