aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-12-05 18:15:18 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-12-05 18:15:18 -0200
commit592a309177edc52847b1196969ad6d49ba21f4fb (patch)
tree06add977885c012ee22cc4f105785c435b6af353 /lgc.c
parent413fc7334bf8ceaea71417d73edef15c99d3a793 (diff)
downloadlua-592a309177edc52847b1196969ad6d49ba21f4fb.tar.gz
lua-592a309177edc52847b1196969ad6d49ba21f4fb.tar.bz2
lua-592a309177edc52847b1196969ad6d49ba21f4fb.zip
tag system replaced by event tables
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c121
1 files changed, 61 insertions, 60 deletions
diff --git a/lgc.c b/lgc.c
index 5ea01c77..3aa9f98d 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.116 2001/11/06 21:41:53 roberto Exp $ 2** $Id: lgc.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -30,6 +30,15 @@ typedef struct GCState {
30#define strmark(s) {if ((s)->tsv.marked == 0) (s)->tsv.marked = 1;} 30#define strmark(s) {if ((s)->tsv.marked == 0) (s)->tsv.marked = 1;}
31 31
32 32
33/* mark tricks for userdata */
34#define isudmarked(u) (u->uv.len & 1)
35#define markud(u) (u->uv.len |= 1)
36#define unmarkud(u) (u->uv.len--)
37
38
39/* mark tricks for upvalues (assume that open upvalues are always marked) */
40#define isupvalmarked(uv) ((uv)->v != &(uv)->value)
41
33 42
34static void markobject (GCState *st, TObject *o); 43static void markobject (GCState *st, TObject *o);
35 44
@@ -66,9 +75,9 @@ static void markclosure (GCState *st, Closure *cl) {
66 protomark(cl->l.p); 75 protomark(cl->l.p);
67 for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ 76 for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
68 UpVal *u = cl->l.upvals[i]; 77 UpVal *u = cl->l.upvals[i];
69 if (!u->mark) { 78 if (!isupvalmarked(u)) {
70 u->mark = 1; 79 markobject(st, &u->value);
71 markobject(st, u->v); 80 u->v = NULL; /* mark it! */
72 } 81 }
73 } 82 }
74 } 83 }
@@ -90,8 +99,8 @@ static void markobject (GCState *st, TObject *o) {
90 strmark(tsvalue(o)); 99 strmark(tsvalue(o));
91 break; 100 break;
92 case LUA_TUSERDATA: 101 case LUA_TUSERDATA:
93 if (!ismarkedudata(uvalue(o))) 102 if (!isudmarked(uvalue(o)))
94 switchudatamark(uvalue(o)); 103 markud(uvalue(o));
95 break; 104 break;
96 case LUA_TFUNCTION: 105 case LUA_TFUNCTION:
97 markclosure(st, clvalue(o)); 106 markclosure(st, clvalue(o));
@@ -112,7 +121,6 @@ static void markstacks (lua_State *L, GCState *st) {
112 lua_State *L1 = L; 121 lua_State *L1 = L;
113 do { /* for each thread */ 122 do { /* for each thread */
114 StkId o, lim; 123 StkId o, lim;
115 markobject(st, &L1->gt); /* mark table of globals */
116 for (o=L1->stack; o<L1->top; o++) 124 for (o=L1->stack; o<L1->top; o++)
117 markobject(st, o); 125 markobject(st, o);
118 lim = (L1->stack_last - L1->ci->base > MAXSTACK) ? L1->ci->base+MAXSTACK 126 lim = (L1->stack_last - L1->ci->base > MAXSTACK) ? L1->ci->base+MAXSTACK
@@ -124,17 +132,10 @@ static void markstacks (lua_State *L, GCState *st) {
124} 132}
125 133
126 134
127static void marktagmethods (global_State *G, GCState *st) { 135static void markudet (lua_State *L, GCState *st) {
128 int t; 136 Udata *u;
129 for (t=0; t<G->ntag; t++) { 137 for (u = G(L)->rootudata; u; u = u->uv.next)
130 struct TM *tm = &G->TMtable[t]; 138 marktable(st, u->uv.eventtable);
131 int e;
132 if (tm->name) strmark(tm->name);
133 for (e=0; e<TM_N; e++) {
134 Closure *cl = tm->method[e];
135 if (cl) markclosure(st, cl);
136 }
137 }
138} 139}
139 140
140 141
@@ -152,6 +153,7 @@ static void traversetable (GCState *st, Table *h) {
152 h->mark = st->toclear; /* put in the appropriate list */ 153 h->mark = st->toclear; /* put in the appropriate list */
153 st->toclear = h; 154 st->toclear = h;
154 } 155 }
156 marktable(st, h->eventtable);
155 if (!(mode & LUA_WEAK_VALUE)) { 157 if (!(mode & LUA_WEAK_VALUE)) {
156 i = sizearray(h); 158 i = sizearray(h);
157 while (i--) 159 while (i--)
@@ -172,11 +174,9 @@ static void traversetable (GCState *st, Table *h) {
172 174
173 175
174static void markall (lua_State *L, GCState *st) { 176static void markall (lua_State *L, GCState *st) {
175 marktagmethods(G(L), st); /* mark tag methods */
176 markstacks(L, st); /* mark all stacks */ 177 markstacks(L, st); /* mark all stacks */
177 marktable(st, G(L)->type2tag); 178 markudet(L, st); /* mark userdata's event tables */
178 markobject(st, &G(L)->registry); 179 while (st->tmark) { /* traverse marked tables */
179 while (st->tmark) { /* mark tables */
180 Table *h = st->tmark; /* get first table from list */ 180 Table *h = st->tmark; /* get first table from list */
181 st->tmark = h->mark; /* remove it from list */ 181 st->tmark = h->mark; /* remove it from list */
182 traversetable(st, h); 182 traversetable(st, h);
@@ -189,7 +189,7 @@ static int hasmark (const TObject *o) {
189 case LUA_TSTRING: 189 case LUA_TSTRING:
190 return tsvalue(o)->tsv.marked; 190 return tsvalue(o)->tsv.marked;
191 case LUA_TUSERDATA: 191 case LUA_TUSERDATA:
192 return ismarkedudata(uvalue(o)); 192 return isudmarked(uvalue(o));
193 case LUA_TTABLE: 193 case LUA_TTABLE:
194 return ismarked(hvalue(o)); 194 return ismarked(hvalue(o));
195 case LUA_TFUNCTION: 195 case LUA_TFUNCTION:
@@ -261,8 +261,9 @@ static void collectupval (lua_State *L) {
261 UpVal **v = &G(L)->rootupval; 261 UpVal **v = &G(L)->rootupval;
262 UpVal *curr; 262 UpVal *curr;
263 while ((curr = *v) != NULL) { 263 while ((curr = *v) != NULL) {
264 if (curr->mark) { 264 if (isupvalmarked(curr)) {
265 curr->mark = 0; 265 lua_assert(curr->v == NULL);
266 curr->v = &curr->value; /* unmark */
266 v = &curr->next; /* next */ 267 v = &curr->next; /* next */
267 } 268 }
268 else { 269 else {
@@ -289,26 +290,27 @@ static void collecttable (lua_State *L) {
289} 290}
290 291
291 292
292static void collectudata (lua_State *L, int keep) { 293static Udata *collectudata (lua_State *L, int keep) {
293 Udata **p = &G(L)->rootudata; 294 Udata **p = &G(L)->rootudata;
294 Udata *curr; 295 Udata *curr;
296 Udata *collected = NULL;
295 while ((curr = *p) != NULL) { 297 while ((curr = *p) != NULL) {
296 if (ismarkedudata(curr)) { 298 if (isudmarked(curr)) {
297 switchudatamark(curr); /* unmark */ 299 unmarkud(curr);
298 p = &curr->uv.next; 300 p = &curr->uv.next;
299 } 301 }
300 else { /* collect */ 302 else { /* collect */
301 int tag = curr->uv.tag; 303 const TObject *tm = fasttm(L, curr->uv.eventtable, TM_GC);
302 *p = curr->uv.next; 304 *p = curr->uv.next;
303 if (keep || /* must keep all of them (to close state)? */ 305 if (keep || tm != NULL) {
304 luaT_gettm(G(L), tag, TM_GC)) { /* or is there a GC tag method? */ 306 curr->uv.next = collected;
305 curr->uv.next = G(L)->TMtable[tag].collected; /* chain udata ... */ 307 collected = curr;
306 G(L)->TMtable[tag].collected = curr; /* ... to call its TM later */
307 } 308 }
308 else /* no tag method; delete udata */ 309 else /* no gc action; delete udata */
309 luaM_free(L, curr, sizeudata(curr->uv.len)); 310 luaM_free(L, curr, sizeudata(curr->uv.len));
310 } 311 }
311 } 312 }
313 return collected;
312} 314}
313 315
314 316
@@ -347,14 +349,14 @@ static void checkMbuffer (lua_State *L) {
347} 349}
348 350
349 351
350static void callgcTM (lua_State *L, const TObject *obj) { 352static void callgcTM (lua_State *L, Udata *udata) {
351 Closure *tm = luaT_gettmbyObj(G(L), obj, TM_GC); 353 const TObject *tm = fasttm(L, udata->uv.eventtable, TM_GC);
352 if (tm != NULL) { 354 if (tm != NULL && ttype(tm) == LUA_TFUNCTION) {
353 int oldah = L->allowhooks; 355 int oldah = L->allowhooks;
354 StkId top = L->top; 356 StkId top = L->top;
355 L->allowhooks = 0; /* stop debug hooks during GC tag methods */ 357 L->allowhooks = 0; /* stop debug hooks during GC tag methods */
356 setclvalue(top, tm); 358 setobj(top, tm);
357 setobj(top+1, obj); 359 setuvalue(top+1, udata);
358 L->top += 2; 360 L->top += 2;
359 luaD_call(L, top); 361 luaD_call(L, top);
360 L->top = top; /* restore top */ 362 L->top = top; /* restore top */
@@ -363,53 +365,52 @@ static void callgcTM (lua_State *L, const TObject *obj) {
363} 365}
364 366
365 367
366static void callgcTMudata (lua_State *L) { 368static void callgcTMudata (lua_State *L, Udata *c) {
367 int tag;
368 luaD_checkstack(L, 3); 369 luaD_checkstack(L, 3);
369 for (tag=G(L)->ntag-1; tag>=0; tag--) { /* for each tag (in reverse order) */ 370 L->top++; /* reserve space to keep udata while runs its gc method */
370 Udata *udata; 371 while (c != NULL) {
371 while ((udata = G(L)->TMtable[tag].collected) != NULL) { 372 Udata *udata = c;
372 G(L)->TMtable[tag].collected = udata->uv.next; /* remove it from list */ 373 c = udata->uv.next; /* remove udata from list */
373 udata->uv.next = G(L)->rootudata; /* resurect it */ 374 udata->uv.next = G(L)->rootudata; /* resurect it */
374 G(L)->rootudata = udata; 375 G(L)->rootudata = udata;
375 setuvalue(L->top, udata); 376 setuvalue(L->top - 1, udata);
376 L->top++; /* keep it in stack to avoid being (recursively) collected */ 377 callgcTM(L, udata);
377 callgcTM(L, L->top-1); 378 /* mark udata as finalized (default event table) */
378 uvalue(L->top-1)->uv.tag = 0; /* default tag (udata is `finalized') */ 379 uvalue(L->top-1)->uv.eventtable = hvalue(defaultet(L));
379 L->top--;
380 }
381 } 380 }
381 L->top--;
382} 382}
383 383
384 384
385void luaC_callallgcTM (lua_State *L) { 385void luaC_callallgcTM (lua_State *L) {
386 if (G(L)->rootudata) { /* avoid problems with incomplete states */ 386 if (G(L)->rootudata) { /* avoid problems with incomplete states */
387 collectudata(L, 1); /* collect all udata into tag lists */ 387 Udata *c = collectudata(L, 1); /* collect all udata */
388 callgcTMudata(L); /* call their GC tag methods */ 388 callgcTMudata(L, c); /* call their GC tag methods */
389 } 389 }
390} 390}
391 391
392 392
393void luaC_collect (lua_State *L, int all) { 393Udata *luaC_collect (lua_State *L, int all) {
394 collectudata(L, 0); 394 Udata *c = collectudata(L, 0);
395 collectstrings(L, all); 395 collectstrings(L, all);
396 collecttable(L); 396 collecttable(L);
397 collectproto(L); 397 collectproto(L);
398 collectupval(L); 398 collectupval(L);
399 collectclosures(L); 399 collectclosures(L);
400 return c;
400} 401}
401 402
402 403
403void luaC_collectgarbage (lua_State *L) { 404void luaC_collectgarbage (lua_State *L) {
405 Udata *c;
404 GCState st; 406 GCState st;
405 st.tmark = NULL; 407 st.tmark = NULL;
406 st.toclear = NULL; 408 st.toclear = NULL;
407 markall(L, &st); 409 markall(L, &st);
408 cleartables(st.toclear); 410 cleartables(st.toclear);
409 luaC_collect(L, 0); 411 c = luaC_collect(L, 0);
410 checkMbuffer(L); 412 checkMbuffer(L);
411 G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ 413 G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */
412 callgcTMudata(L); 414 callgcTMudata(L, c);
413 callgcTM(L, &luaO_nilobject);
414} 415}
415 416