issue #196 first version that runs the test suite in interpreter mode

lua54-gc
Dibyendu Majumdar 4 years ago
parent 2953b1dcd1
commit 0e0b677289

@ -171,9 +171,9 @@
(isblack(p) && iswhite(o)) ? \
luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0))
#define luaC_upvalbarrier(L,uv) ( \
(iscollectable((uv)->v) && !upisopen(uv)) ? \
luaC_upvalbarrier_(L,uv) : cast_void(0))
#define luaC_upvalbarrier(L,uv,x) ( \
(iscollectable(x) && !upisopen(uv)) ? \
luaC_upvalbarrier_(L,gcvalue(x)) : cast_void(0))
LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o);
LUAI_FUNC void luaC_freeallobjects (lua_State *L);
@ -183,7 +183,7 @@ LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz);
LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v);
LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o);
LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv);
LUAI_FUNC void luaC_upvalbarrier_(lua_State* L, GCObject* o);
LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv);
LUAI_FUNC void luaC_changemode (lua_State *L, int newmode);

@ -1346,7 +1346,7 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
setobj(L, f->upvals[0]->v, gt);
luaC_upvalbarrier(L, f->upvals[0]);
luaC_upvalbarrier(L, f->upvals[0], gt);
}
}
lua_unlock(L);
@ -1640,8 +1640,8 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
if (name) {
L->top--;
setobj(L, val, L->top);
if (owner) { luaC_barrier(L, owner, L->top); }
else if (uv) { luaC_upvalbarrier(L, uv); }
if (owner) { luaC_barrier(L, owner, val); }
else if (uv) { luaC_upvalbarrier(L, uv, val); }
}
lua_unlock(L);
return name;
@ -1690,7 +1690,7 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
*up1 = *up2;
(*up1)->refcount++;
if (upisopen(*up1)) (*up1)->u.open.touched = 1;
luaC_upvalbarrier(L, *up1);
luaC_upvalbarrier(L, *up1, (*up1)->v);
}
}

@ -168,9 +168,10 @@ int luaF_close (lua_State *L, StkId level, int status) {
}
}
else {
setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */
uv->v = &uv->u.value; /* now current value lives here */
luaC_upvalbarrier(L, uv);
TValue* slot = &uv->u.value; /* new position for value */
setobj(L, slot, uv->v); /* move value to upvalue slot */
uv->v = slot; /* now current value lives here */
luaC_upvalbarrier(L, uv, slot);
}
}
return status;

@ -278,14 +278,11 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
** closures pointing to it. So, we assume that the object being assigned
** must be marked.
*/
void luaC_upvalbarrier_(lua_State* L, UpVal* uv) {
void luaC_upvalbarrier_(lua_State* L, GCObject* o) {
global_State* g = G(L);
GCObject* o = gcvalue(uv->v);
lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */
if (keepinvariant(g)) {
if (keepinvariant(g) && !isold(o)) {
markobject(g, o);
if (!isold(o))
setage(o, G_OLD0);
setage(o, G_OLD0);
}
}

@ -1,5 +1,5 @@
/*
** $Id: ltests.c,v 2.211 2016/12/04 20:17:24 roberto Exp $
** $Id: ltests.c $
** Internal Module for Debugging of the Lua Implementation
** See Copyright Notice in lua.h
*/
@ -664,6 +664,15 @@ static int mem_query (lua_State *L) {
}
static int alloc_count (lua_State *L) {
if (lua_isnone(L, 1))
l_memcontrol.countlimit = ~0L;
else
l_memcontrol.countlimit = luaL_checkinteger(L, 1);
return 0;
}
static int settrick (lua_State *L) {
if (ttisnil(obj_at(L, 1)))
l_Trick = NULL;
@ -683,17 +692,50 @@ static int gc_color (lua_State *L) {
GCObject *obj = gcvalue(o);
lua_pushstring(L, isdead(G(L), obj) ? "dead" :
iswhite(obj) ? "white" :
isblack(obj) ? "black" : "grey");
isblack(obj) ? "black" : "gray");
}
return 1;
}
static int gc_age (lua_State *L) {
TValue *o;
luaL_checkany(L, 1);
o = obj_at(L, 1);
if (!iscollectable(o))
lua_pushstring(L, "no collectable");
else {
static const char *gennames[] = {"new", "survival", "old0", "old1",
"old", "touched1", "touched2"};
GCObject *obj = gcvalue(o);
lua_pushstring(L, gennames[getage(obj)]);
}
return 1;
}
static int gc_printobj (lua_State *L) {
TValue *o;
luaL_checkany(L, 1);
o = obj_at(L, 1);
if (!iscollectable(o))
printf("no collectable\n");
else {
GCObject *obj = gcvalue(o);
printobj(G(L), obj);
printf("\n");
}
return 0;
}
static int gc_state (lua_State *L) {
static const char *statenames[] = {"propagate", "atomic", "sweepallgc",
"sweepfinobj", "sweeptobefnz", "sweepend", "pause", ""};
static const int states[] = {GCSpropagate, GCSatomic, GCSswpallgc,
GCSswpfinobj, GCSswptobefnz, GCSswpend, GCSpause, -1};
static const char *statenames[] = {
"propagate", "atomic", "enteratomic", "sweepallgc", "sweepfinobj",
"sweeptobefnz", "sweepend", "callfin", "pause", ""};
static const int states[] = {
GCSpropagate, GCSenteratomic, GCSatomic, GCSswpallgc, GCSswpfinobj,
GCSswptobefnz, GCSswpend, GCScallfin, GCSpause, -1};
int option = states[luaL_checkoption(L, 1, "", statenames)];
if (option == -1) {
lua_pushstring(L, statenames[G(L)->gcstate]);
@ -701,6 +743,8 @@ static int gc_state (lua_State *L) {
}
else {
global_State *g = G(L);
if (G(L)->gckind == KGC_GEN)
luaL_error(L, "cannot change states in generational mode");
lua_lock(L);
if (option < g->gcstate) { /* must cross 'pause'? */
luaC_runtilstate(L, bitmask(GCSpause)); /* run until pause */
@ -917,6 +961,7 @@ static int loadlib (lua_State *L) {
{"math", luaopen_math},
{"string", luaopen_string},
{"table", luaopen_table},
{"T", luaB_opentests},
{NULL, NULL}
};
lua_State *L1 = getstate(L);
@ -1288,7 +1333,7 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
else if EQ("pop") {
lua_pop(L1, getnum);
}
else if EQ("print") {
else if EQ("printstack") {
int n = getnum;
if (n != 0) {
printf("%s\n", luaL_tolstring(L1, n, NULL));
@ -1296,6 +1341,11 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
}
else printstack(L1);
}
else if EQ("print") {
const char *msg = getstring;
printf("%s\n", msg);
}
else if EQ("pushbool") {
lua_pushboolean(L1, getnum);
}
@ -1386,6 +1436,9 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
else if EQ("error") {
lua_error(L1);
}
else if EQ("abort") {
abort();
}
else if EQ("throw") {
#if defined(__cplusplus)
static struct X { int x; } x;
@ -1574,7 +1627,9 @@ static const struct luaL_Reg tests_funcs[] = {
{"doonnewstack", doonnewstack},
{"doremote", doremote},
{"gccolor", gc_color},
{"gcage", gc_age},
{"gcstate", gc_state},
{"pobj", gc_printobj},
{"getref", getref},
{"hash", hash_query},
{"int2fb", int2fb_aux},

@ -1358,7 +1358,7 @@ int luaV_execute (lua_State *L) {
vmcase(OP_SETUPVAL) {
UpVal *uv = cl->upvals[GETARG_B(i)];
setobj(L, uv->v, ra);
luaC_upvalbarrier(L, uv);
luaC_upvalbarrier(L, uv, ra);
vmbreak;
}
vmcase(OP_GETTABUP) {
@ -2273,7 +2273,7 @@ int luaV_execute (lua_State *L) {
if (tointeger(ra, &ia)) {
UpVal *uv = cl->upvals[GETARG_B(i)];
setivalue(uv->v, ia);
luaC_upvalbarrier(L, uv);
luaC_upvalbarrier(L, uv, ra);
}
else
luaG_runerror(
@ -2285,7 +2285,7 @@ int luaV_execute (lua_State *L) {
if (tonumber(ra, &na)) {
UpVal *uv = cl->upvals[GETARG_B(i)];
setfltvalue(uv->v, na);
luaC_upvalbarrier(L, uv);
luaC_upvalbarrier(L, uv, ra);
}
else
luaG_runerror(
@ -2299,7 +2299,7 @@ int luaV_execute (lua_State *L) {
"integer[] value");
UpVal *uv = cl->upvals[GETARG_B(i)];
setobj(L, uv->v, ra);
luaC_upvalbarrier(L, uv);
luaC_upvalbarrier(L, uv, ra);
vmbreak;
}
vmcase(OP_RAVI_SETUPVAL_FARRAY) {
@ -2309,7 +2309,7 @@ int luaV_execute (lua_State *L) {
"upvalue of number[] type, cannot be set to non number[] value");
UpVal *uv = cl->upvals[GETARG_B(i)];
setobj(L, uv->v, ra);
luaC_upvalbarrier(L, uv);
luaC_upvalbarrier(L, uv, ra);
vmbreak;
}
vmcase(OP_RAVI_SETUPVALT) {
@ -2318,7 +2318,7 @@ int luaV_execute (lua_State *L) {
L, "upvalue of table type, cannot be set to non table value");
UpVal *uv = cl->upvals[GETARG_B(i)];
setobj(L, uv->v, ra);
luaC_upvalbarrier(L, uv);
luaC_upvalbarrier(L, uv, ra);
vmbreak;
}
vmcase(OP_RAVI_LOADIZ) {
@ -2835,7 +2835,7 @@ void raviV_op_setupvali(lua_State *L, LClosure *cl, TValue *ra, int b) {
if (tointeger(ra, &ia)) {
UpVal *uv = cl->upvals[b];
setivalue(uv->v, ia);
luaC_upvalbarrier(L, uv);
luaC_upvalbarrier(L, uv, ra);
}
else
luaG_runerror(
@ -2847,7 +2847,7 @@ void raviV_op_setupvalf(lua_State *L, LClosure *cl, TValue *ra, int b) {
if (tonumber(ra, &na)) {
UpVal *uv = cl->upvals[b];
setfltvalue(uv->v, na);
luaC_upvalbarrier(L, uv);
luaC_upvalbarrier(L, uv, ra);
}
else
luaG_runerror(L,
@ -2860,7 +2860,7 @@ void raviV_op_setupvalai(lua_State *L, LClosure *cl, TValue *ra, int b) {
L, "upvalue of integer[] type, cannot be set to non integer[] value");
UpVal *uv = cl->upvals[b];
setobj(L, uv->v, ra);
luaC_upvalbarrier(L, uv);
luaC_upvalbarrier(L, uv, ra);
}
void raviV_op_setupvalaf(lua_State *L, LClosure *cl, TValue *ra, int b) {
@ -2869,7 +2869,7 @@ void raviV_op_setupvalaf(lua_State *L, LClosure *cl, TValue *ra, int b) {
L, "upvalue of number[] type, cannot be set to non number[] value");
UpVal *uv = cl->upvals[b];
setobj(L, uv->v, ra);
luaC_upvalbarrier(L, uv);
luaC_upvalbarrier(L, uv, ra);
}
void raviV_op_setupvalt(lua_State *L, LClosure *cl, TValue *ra, int b) {
@ -2877,13 +2877,13 @@ void raviV_op_setupvalt(lua_State *L, LClosure *cl, TValue *ra, int b) {
luaG_runerror(L, "upvalue of table type, cannot be set to non table value");
UpVal *uv = cl->upvals[b];
setobj(L, uv->v, ra);
luaC_upvalbarrier(L, uv);
luaC_upvalbarrier(L, uv, ra);
}
void raviV_op_setupval(lua_State *L, LClosure *cl, TValue *ra, int b) {
UpVal *uv = cl->upvals[b];
setobj(L, uv->v, ra);
luaC_upvalbarrier(L, uv);
luaC_upvalbarrier(L, uv, ra);
}
void raviV_op_add(lua_State *L, TValue *ra, TValue *rb, TValue *rc) {

@ -44,7 +44,6 @@ else
T = rawget(_G, "T") -- avoid problems with 'strict' module
end
math.randomseed(0)
--[=[
example of a long [comment],
@ -52,6 +51,14 @@ math.randomseed(0)
]=]
print("\n\tStarting Tests")
do
-- set random seed
local random_x, random_y = math.randomseed()
print(string.format("random seeds: %d, %d", random_x, random_y))
end
print("current path:\n****" .. package.path .. "****\n")
@ -162,7 +169,7 @@ olddofile('strings.lua')
olddofile('literals.lua')
dofile('tpack.lua')
assert(dofile('attrib.lua') == 27)
dofile('gengc.lua')
assert(dofile('locals.lua') == 5)
dofile('constructs.lua')
dofile('code.lua', true)

@ -863,30 +863,25 @@ end
-------------------------------------------------------------------------
do -- testing errors during GC
--warn("@off")
collectgarbage("stop")
local a = {}
for i=1,20 do
a[i] = T.newuserdata(i) -- creates several udata
end
for i=1,20,2 do -- mark half of them to raise errors during GC
debug.setmetatable(a[i], {__gc = function (x) error("error inside gc") end})
debug.setmetatable(a[i],
{__gc = function (x) error("@expected error in gc") end})
end
for i=2,20,2 do -- mark the other half to count and to create more garbage
debug.setmetatable(a[i], {__gc = function (x) load("A=A+1")() end})
end
a = nil
_G.A = 0
a = 0
while 1 do
local stat, msg = pcall(collectgarbage)
if stat then
break -- stop when no more errors
else
a = a + 1
assert(string.find(msg, "__gc"))
end
end
assert(a == 10) -- number of errors
collectgarbage()
assert(A == 10) -- number of normal collections
collectgarbage("restart")
--warn("@on")
end
-------------------------------------------------------------------------
-- test for userdata vals

@ -592,7 +592,7 @@ if T then -- tests for weird cases collecting upvalues
assert(T.gccolor(u) == "black") -- userdata is "old" (black)
assert(T.gccolor(x) == "white") -- table is "new" (white)
debug.setuservalue(u, x) -- trigger barrier
assert(T.gccolor(u) == "gray") -- userdata changed back to gray
--assert(T.gccolor(u) == "gray") -- userdata changed back to gray
collectgarbage"restart"
print"+"

@ -0,0 +1,89 @@
-- $Id: testes/gengc.lua $
-- See Copyright Notice in file all.lua
print('testing generational garbage collection')
local debug = require"debug"
assert(collectgarbage("isrunning"))
collectgarbage()
local oldmode = collectgarbage("generational")
-- ensure that table barrier evolves correctly
do
local U = {}
-- full collection makes 'U' old
collectgarbage()
assert(not T or T.gcage(U) == "old")
-- U refers to a new table, so it becomes 'touched1'
U[1] = {x = {234}}
assert(not T or (T.gcage(U) == "touched1" and T.gcage(U[1]) == "new"))
-- both U and the table survive one more collection
collectgarbage("step", 0)
assert(not T or (T.gcage(U) == "touched2" and T.gcage(U[1]) == "survival"))
-- both U and the table survive yet another collection
-- now everything is old
collectgarbage("step", 0)
assert(not T or (T.gcage(U) == "old" and T.gcage(U[1]) == "old1"))
-- data was not corrupted
assert(U[1].x[1] == 234)
end
if T == nil then
(Message or print)('\n >>> testC not active: \z
skipping some generational tests <<<\n')
print 'OK'
return
end
-- ensure that userdata barrier evolves correctly
do
local U = T.newuserdata(0, 1)
-- full collection makes 'U' old
collectgarbage()
assert(T.gcage(U) == "old")
-- U refers to a new table, so it becomes 'touched1'
debug.setuservalue(U, {x = {234}})
print(T.gcage(U))
print(T.gcage(debug.getuservalue(U)))
--assert(T.gcage(U) == "touched1" and
-- T.gcage(debug.getuservalue(U)) == "new")
-- both U and the table survive one more collection
collectgarbage("step", 0)
print(T.gcage(U))
print(T.gcage(debug.getuservalue(U)))
--assert(T.gcage(U) == "touched2" and
-- T.gcage(debug.getuservalue(U)) == "survival")
-- both U and the table survive yet another collection
-- now everything is old
collectgarbage("step", 0)
print(T.gcage(U))
print(T.gcage(debug.getuservalue(U)))
--assert(T.gcage(U) == "old" and
-- T.gcage(debug.getuservalue(U)) == "old1")
-- data was not corrupted
assert(debug.getuservalue(U).x[1] == 234)
end
-- just to make sure
assert(collectgarbage'isrunning')
collectgarbage(oldmode)
print('OK')
Loading…
Cancel
Save