Skip to content

Commit d4eff00

Browse files
committed
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'.
1 parent fca9744 commit d4eff00

3 files changed

Lines changed: 52 additions & 13 deletions

File tree

lcode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1242,7 +1242,7 @@ static void codenot (FuncState *fs, expdesc *e) {
12421242
** Check whether expression 'e' is a short literal string
12431243
*/
12441244
static int isKstr (FuncState *fs, expdesc *e) {
1245-
return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_B &&
1245+
return (e->k == VK && !hasjumps(e) && e->u.info <= MAXINDEXRK &&
12461246
ttisshrstring(&fs->f->k[e->u.info]));
12471247
}
12481248

lparser.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1875,6 +1875,33 @@ static lu_byte getglobalattribute (LexState *ls, lu_byte df) {
18751875
}
18761876

18771877

1878+
/*
1879+
** Recursively traverse list of globals to be initalized. When
1880+
** going, generate table description for the global. In the end,
1881+
** after all indices have been generated, read list of initializing
1882+
** expressions. When returning, generate the assignment of the value on
1883+
** the stack to the corresponding table description. 'n' is the variable
1884+
** being handled, range [0, nvars - 1].
1885+
*/
1886+
static void initglobal (LexState *ls, int nvars, int firstidx, int n) {
1887+
if (n == nvars) { /* traversed all variables? */
1888+
expdesc e;
1889+
int nexps = explist(ls, &e); /* read list of expressions */
1890+
adjust_assign(ls, nvars, nexps, &e);
1891+
}
1892+
else { /* handle variable 'n' */
1893+
FuncState *fs = ls->fs;
1894+
expdesc var;
1895+
TString *varname = getlocalvardesc(fs, firstidx + n)->vd.name;
1896+
buildglobal(ls, varname, &var); /* create global variable in 'var' */
1897+
enterlevel(ls); /* control recursion depth */
1898+
initglobal(ls, nvars, firstidx, n + 1);
1899+
leavelevel(ls);
1900+
storevartop(fs, &var);
1901+
}
1902+
}
1903+
1904+
18781905
static void globalnames (LexState *ls, lu_byte defkind) {
18791906
FuncState *fs = ls->fs;
18801907
int nvars = 0;
@@ -1885,18 +1912,8 @@ static void globalnames (LexState *ls, lu_byte defkind) {
18851912
lastidx = new_varkind(ls, vname, kind);
18861913
nvars++;
18871914
} while (testnext(ls, ','));
1888-
if (testnext(ls, '=')) { /* initialization? */
1889-
expdesc e;
1890-
int i;
1891-
int nexps = explist(ls, &e); /* read list of expressions */
1892-
adjust_assign(ls, nvars, nexps, &e);
1893-
for (i = 0; i < nvars; i++) { /* for each variable */
1894-
expdesc var;
1895-
TString *varname = getlocalvardesc(fs, lastidx - i)->vd.name;
1896-
buildglobal(ls, varname, &var); /* create global variable in 'var' */
1897-
storevartop(fs, &var);
1898-
}
1899-
}
1915+
if (testnext(ls, '=')) /* initialization? */
1916+
initglobal(ls, nvars, lastidx - nvars + 1, 0);
19001917
fs->nactvar = cast_short(fs->nactvar + nvars); /* activate declaration */
19011918
}
19021919

testes/goto.lua

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,5 +432,27 @@ do print "testing initialization in global declarations"
432432
_ENV.a, _ENV.b, _ENV.c, _ENV.d = nil -- erase these globals
433433
end
434434

435+
do
436+
global table, string
437+
-- global initialization when names don't fit in K
438+
439+
-- to fill constant table
440+
local code = {}
441+
for i = 1, 300 do code[i] = "'" .. i .. "'" end
442+
code = table.concat(code, ",")
443+
code = string.format([[
444+
return function (_ENV)
445+
local dummy = {%s} -- fill initial positions in constant table,
446+
-- so that initialization must use registers for global names
447+
global a, b, c = 10, 20, 30
448+
end]], code)
449+
450+
local fun = assert(load(code))()
451+
452+
local env = {}
453+
fun(env)
454+
assert(env.a == 10 and env.b == 20 and env.c == 30)
455+
end
456+
435457
print'OK'
436458

0 commit comments

Comments
 (0)