From 50a82ec1b9adafa108756077b018925131f131e8 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 30 May 2000 15:54:49 -0300 Subject: gc tag methods for udata are called in (reverse) tag order --- lgc.c | 127 +++++++++++++++++++++++++++++++++++++++++++----------------------- ltm.c | 3 +- ltm.h | 3 +- 3 files changed, 87 insertions(+), 46 deletions(-) diff --git a/lgc.c b/lgc.c index cc984992..a9dfc412 100644 --- a/lgc.c +++ b/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 ** 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); @@ -78,9 +68,9 @@ static void tablemark (lua_State *L, Hash *h) { static void travstack (lua_State *L) { - int i; - for (i = (L->top-1)-L->stack; i>=0; i--) - markobject(L, L->stack+i); + StkId o; + for (o=L->stack; otop; o++) + markobject(L, o); } @@ -161,54 +151,101 @@ static void collecttable (lua_State *L) { } +static void checktab (lua_State *L, stringtable *tb) { + if (tb->nuse < (lint32)(tb->size/4) && tb->size > 10) + luaS_resize(L, tb, tb->size/2); /* table is too big */ +} + + /* -** collect all elements with `marked' < `limit'. -** with limit=1, that means all unmarked elements; +** collect all elements with `marked' <= `limit'. +** with limit=0, that means all unmarked elements; ** with limit=MAX_INT, that means all elements. */ -static void collectstringtab (lua_State *L, int limit, stringtable *tb) { +static void collectstringtab (lua_State *L, int limit) { int i; - TObject o; /* to call userdata `gc' tag method */ - ttype(&o) = TAG_USERDATA; - for (i=0; isize; i++) { /* for each list */ - TString **p = &tb->hash[i]; + for (i=0; istrt.size; i++) { /* for each list */ + TString **p = &L->strt.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; - } + if (next->marked > limit) { /* preserve? */ + if (next->marked < FIXMARK) /* does not change FIXMARKs */ + next->marked = 0; + p = &next->nexthash; + } + else { /* collect */ *p = next->nexthash; - tb->nuse--; + L->strt.nuse--; + L->nblocks -= gcsizestring(L, next->u.s.len); luaM_free(L, next); } } } - if (tb->nuse < (lint32)(tb->size/4) && tb->size > 10) - luaS_resize(L, tb, tb->size/2); /* table is too big */ + checktab(L, &L->strt); } -static void collectstring (lua_State *L, int limit) { - collectstringtab(L, limit, &L->strt); - collectstringtab(L, limit, &L->udt); +static void collectudatatab (lua_State *L, int all) { + int i; + for (i=0; iudt.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) { + luaT_travtagmethods(L, markobject); /* mark tag methods */ travstack(L); /* mark stack objects */ - tablemark(L, L->gt); /* mark global variable values and names */ + tablemark(L, L->gt); /* mark global variables */ travlock(L); /* mark locked objects */ - luaT_travtagmethods(L, markobject); /* mark tag methods */ } @@ -216,8 +253,10 @@ void luaC_collect (lua_State *L, int all) { int oldah = L->allowhooks; L->allowhooks = 0; /* stop debug hooks during GC */ L->GCthreshold *= 4; /* to avoid GC during GC */ + collectudatatab(L, all); + callgcTMudata(L); + collectstringtab(L, all?MAX_INT:0); collecttable(L); - collectstring(L, all?MAX_INT:1); collectproto(L); collectclosure(L); 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 */ luaM_reallocvector(L, L->Mbuffer, L->Mbuffsize, char); } - luaD_gcTM(L, &luaO_nilobject); + callgcTM(L, &luaO_nilobject); return recovered; } diff --git a/ltm.c b/ltm.c index 410d23c0..a173879e 100644 --- a/ltm.c +++ b/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 ** See Copyright Notice in lua.h */ @@ -61,6 +61,7 @@ static void init_entry (lua_State *L, int tag) { int i; for (i=0; iIMtable[tag].collected = NULL; } diff --git a/ltm.h b/ltm.h index be3e51e3..48acd59f 100644 --- a/ltm.h +++ b/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 ** See Copyright Notice in lua.h */ @@ -37,6 +37,7 @@ typedef enum { struct IM { TObject int_method[IM_N]; + TString *collected; /* list of G. collected udata with this tag */ }; -- cgit v1.2.3-55-g6feb