gc tag methods for udata are called in (reverse) tag order
This commit is contained in:
147
lgc.c
147
lgc.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lgc.c,v 1.50 2000/05/11 18:57:19 roberto Exp roberto $
|
** $Id: lgc.c,v 1.51 2000/05/24 13:54:49 roberto Exp roberto $
|
||||||
** Garbage Collector
|
** Garbage Collector
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -20,16 +20,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void luaD_gcTM (lua_State *L, const TObject *o) {
|
|
||||||
const TObject *im = luaT_getimbyObj(L, o, IM_GC);
|
|
||||||
if (ttype(im) != TAG_NIL) {
|
|
||||||
luaD_checkstack(L, 2);
|
|
||||||
*(L->top++) = *im;
|
|
||||||
*(L->top++) = *o;
|
|
||||||
luaD_call(L, L->top-2, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int markobject (lua_State *L, TObject *o);
|
static int markobject (lua_State *L, TObject *o);
|
||||||
|
|
||||||
@@ -78,9 +68,9 @@ static void tablemark (lua_State *L, Hash *h) {
|
|||||||
|
|
||||||
|
|
||||||
static void travstack (lua_State *L) {
|
static void travstack (lua_State *L) {
|
||||||
int i;
|
StkId o;
|
||||||
for (i = (L->top-1)-L->stack; i>=0; i--)
|
for (o=L->stack; o<L->top; o++)
|
||||||
markobject(L, L->stack+i);
|
markobject(L, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -161,54 +151,101 @@ static void collecttable (lua_State *L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
static void checktab (lua_State *L, stringtable *tb) {
|
||||||
** collect all elements with `marked' < `limit'.
|
|
||||||
** with limit=1, that means all unmarked elements;
|
|
||||||
** with limit=MAX_INT, that means all elements.
|
|
||||||
*/
|
|
||||||
static void collectstringtab (lua_State *L, int limit, stringtable *tb) {
|
|
||||||
int i;
|
|
||||||
TObject o; /* to call userdata `gc' tag method */
|
|
||||||
ttype(&o) = TAG_USERDATA;
|
|
||||||
for (i=0; i<tb->size; i++) { /* for each list */
|
|
||||||
TString **p = &tb->hash[i];
|
|
||||||
TString *next;
|
|
||||||
while ((next = *p) != NULL) {
|
|
||||||
if (next->marked >= limit) {
|
|
||||||
if (next->marked < FIXMARK) /* does not change FIXMARKs */
|
|
||||||
next->marked = 0;
|
|
||||||
p = &next->nexthash;
|
|
||||||
}
|
|
||||||
else { /* collect */
|
|
||||||
if (tb == &L->strt) /* is string? */
|
|
||||||
L->nblocks -= gcsizestring(L, next->u.s.len);
|
|
||||||
else {
|
|
||||||
tsvalue(&o) = next;
|
|
||||||
luaD_gcTM(L, &o);
|
|
||||||
L->nblocks -= gcsizeudata;
|
|
||||||
}
|
|
||||||
*p = next->nexthash;
|
|
||||||
tb->nuse--;
|
|
||||||
luaM_free(L, next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tb->nuse < (lint32)(tb->size/4) && tb->size > 10)
|
if (tb->nuse < (lint32)(tb->size/4) && tb->size > 10)
|
||||||
luaS_resize(L, tb, tb->size/2); /* table is too big */
|
luaS_resize(L, tb, tb->size/2); /* table is too big */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void collectstring (lua_State *L, int limit) {
|
/*
|
||||||
collectstringtab(L, limit, &L->strt);
|
** collect all elements with `marked' <= `limit'.
|
||||||
collectstringtab(L, limit, &L->udt);
|
** with limit=0, that means all unmarked elements;
|
||||||
|
** with limit=MAX_INT, that means all elements.
|
||||||
|
*/
|
||||||
|
static void collectstringtab (lua_State *L, int limit) {
|
||||||
|
int i;
|
||||||
|
for (i=0; i<L->strt.size; i++) { /* for each list */
|
||||||
|
TString **p = &L->strt.hash[i];
|
||||||
|
TString *next;
|
||||||
|
while ((next = *p) != NULL) {
|
||||||
|
if (next->marked > limit) { /* preserve? */
|
||||||
|
if (next->marked < FIXMARK) /* does not change FIXMARKs */
|
||||||
|
next->marked = 0;
|
||||||
|
p = &next->nexthash;
|
||||||
|
}
|
||||||
|
else { /* collect */
|
||||||
|
*p = next->nexthash;
|
||||||
|
L->strt.nuse--;
|
||||||
|
L->nblocks -= gcsizestring(L, next->u.s.len);
|
||||||
|
luaM_free(L, next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checktab(L, &L->strt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void collectudatatab (lua_State *L, int all) {
|
||||||
|
int i;
|
||||||
|
for (i=0; i<L->udt.size; i++) { /* for each list */
|
||||||
|
TString **p = &L->udt.hash[i];
|
||||||
|
TString *next;
|
||||||
|
while ((next = *p) != NULL) {
|
||||||
|
LUA_ASSERT(L, next->marked <= 1, "udata cannot be fixed");
|
||||||
|
if (next->marked > all) { /* preserve? */
|
||||||
|
next->marked = 0;
|
||||||
|
p = &next->nexthash;
|
||||||
|
}
|
||||||
|
else { /* collect */
|
||||||
|
int tag = next->u.d.tag;
|
||||||
|
if (tag > L->last_tag) tag = TAG_USERDATA;
|
||||||
|
*p = next->nexthash;
|
||||||
|
next->nexthash = L->IMtable[tag].collected; /* chain udata */
|
||||||
|
L->IMtable[tag].collected = next;
|
||||||
|
L->nblocks -= gcsizeudata;
|
||||||
|
L->udt.nuse--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checktab(L, &L->udt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void callgcTM (lua_State *L, const TObject *o) {
|
||||||
|
const TObject *im = luaT_getimbyObj(L, o, IM_GC);
|
||||||
|
if (ttype(im) != TAG_NIL) {
|
||||||
|
luaD_checkstack(L, 2);
|
||||||
|
*(L->top) = *im;
|
||||||
|
*(L->top+1) = *o;
|
||||||
|
L->top += 2;
|
||||||
|
luaD_call(L, L->top-2, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void callgcTMudata (lua_State *L) {
|
||||||
|
int tag;
|
||||||
|
TObject o;
|
||||||
|
ttype(&o) = TAG_USERDATA;
|
||||||
|
for (tag=L->last_tag; tag>=0; tag--) {
|
||||||
|
TString *udata = L->IMtable[tag].collected;
|
||||||
|
L->IMtable[tag].collected = NULL;
|
||||||
|
while (udata) {
|
||||||
|
TString *next = udata->nexthash;
|
||||||
|
tsvalue(&o) = udata;
|
||||||
|
callgcTM(L, &o);
|
||||||
|
luaM_free(L, udata);
|
||||||
|
udata = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void markall (lua_State *L) {
|
static void markall (lua_State *L) {
|
||||||
travstack(L); /* mark stack objects */
|
|
||||||
tablemark(L, L->gt); /* mark global variable values and names */
|
|
||||||
travlock(L); /* mark locked objects */
|
|
||||||
luaT_travtagmethods(L, markobject); /* mark tag methods */
|
luaT_travtagmethods(L, markobject); /* mark tag methods */
|
||||||
|
travstack(L); /* mark stack objects */
|
||||||
|
tablemark(L, L->gt); /* mark global variables */
|
||||||
|
travlock(L); /* mark locked objects */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -216,8 +253,10 @@ void luaC_collect (lua_State *L, int all) {
|
|||||||
int oldah = L->allowhooks;
|
int oldah = L->allowhooks;
|
||||||
L->allowhooks = 0; /* stop debug hooks during GC */
|
L->allowhooks = 0; /* stop debug hooks during GC */
|
||||||
L->GCthreshold *= 4; /* to avoid GC during GC */
|
L->GCthreshold *= 4; /* to avoid GC during GC */
|
||||||
|
collectudatatab(L, all);
|
||||||
|
callgcTMudata(L);
|
||||||
|
collectstringtab(L, all?MAX_INT:0);
|
||||||
collecttable(L);
|
collecttable(L);
|
||||||
collectstring(L, all?MAX_INT:1);
|
|
||||||
collectproto(L);
|
collectproto(L);
|
||||||
collectclosure(L);
|
collectclosure(L);
|
||||||
L->allowhooks = oldah; /* restore hooks */
|
L->allowhooks = oldah; /* restore hooks */
|
||||||
@@ -235,7 +274,7 @@ long lua_collectgarbage (lua_State *L, long limit) {
|
|||||||
L->Mbuffsize /= 2; /* still larger than Mbuffnext*2 */
|
L->Mbuffsize /= 2; /* still larger than Mbuffnext*2 */
|
||||||
luaM_reallocvector(L, L->Mbuffer, L->Mbuffsize, char);
|
luaM_reallocvector(L, L->Mbuffer, L->Mbuffsize, char);
|
||||||
}
|
}
|
||||||
luaD_gcTM(L, &luaO_nilobject);
|
callgcTM(L, &luaO_nilobject);
|
||||||
return recovered;
|
return recovered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
ltm.c
3
ltm.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltm.c,v 1.39 2000/03/30 16:41:51 roberto Exp roberto $
|
** $Id: ltm.c,v 1.40 2000/05/24 13:54:49 roberto Exp roberto $
|
||||||
** Tag methods
|
** Tag methods
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -61,6 +61,7 @@ static void init_entry (lua_State *L, int tag) {
|
|||||||
int i;
|
int i;
|
||||||
for (i=0; i<IM_N; i++)
|
for (i=0; i<IM_N; i++)
|
||||||
ttype(luaT_getim(L, tag, i)) = TAG_NIL;
|
ttype(luaT_getim(L, tag, i)) = TAG_NIL;
|
||||||
|
L->IMtable[tag].collected = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
3
ltm.h
3
ltm.h
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltm.h,v 1.11 2000/03/20 19:14:54 roberto Exp roberto $
|
** $Id: ltm.h,v 1.12 2000/03/30 16:41:51 roberto Exp roberto $
|
||||||
** Tag methods
|
** Tag methods
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -37,6 +37,7 @@ typedef enum {
|
|||||||
|
|
||||||
struct IM {
|
struct IM {
|
||||||
TObject int_method[IM_N];
|
TObject int_method[IM_N];
|
||||||
|
TString *collected; /* list of G. collected udata with this tag */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user