summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lgc.c49
-rw-r--r--lstate.c4
-rw-r--r--lstate.h3
3 files changed, 31 insertions, 25 deletions
diff --git a/lgc.c b/lgc.c
index 3aa9f98d..29586007 100644
--- a/lgc.c
+++ b/lgc.c
@@ -136,6 +136,8 @@ static void markudet (lua_State *L, GCState *st) {
136 Udata *u; 136 Udata *u;
137 for (u = G(L)->rootudata; u; u = u->uv.next) 137 for (u = G(L)->rootudata; u; u = u->uv.next)
138 marktable(st, u->uv.eventtable); 138 marktable(st, u->uv.eventtable);
139 for (u = G(L)->tmudata; u; u = u->uv.next)
140 marktable(st, u->uv.eventtable);
139} 141}
140 142
141 143
@@ -290,27 +292,30 @@ static void collecttable (lua_State *L) {
290} 292}
291 293
292 294
293static Udata *collectudata (lua_State *L, int keep) { 295static void collectudata (lua_State *L) {
294 Udata **p = &G(L)->rootudata; 296 Udata **p = &G(L)->rootudata;
295 Udata *curr; 297 Udata *curr;
296 Udata *collected = NULL; 298 Udata *collected = NULL; /* to collect udata with gc event */
299 Udata **lastcollected = &collected;
297 while ((curr = *p) != NULL) { 300 while ((curr = *p) != NULL) {
298 if (isudmarked(curr)) { 301 if (isudmarked(curr)) {
299 unmarkud(curr); 302 unmarkud(curr);
300 p = &curr->uv.next; 303 p = &curr->uv.next;
301 } 304 }
302 else { /* collect */ 305 else {
303 const TObject *tm = fasttm(L, curr->uv.eventtable, TM_GC);
304 *p = curr->uv.next; 306 *p = curr->uv.next;
305 if (keep || tm != NULL) { 307 if (fasttm(L, curr->uv.eventtable, TM_GC) != NULL) { /* gc event? */
306 curr->uv.next = collected; 308 curr->uv.next = NULL; /* link `curr' at the end of `collected' list */
307 collected = curr; 309 *lastcollected = curr;
310 lastcollected = &curr->uv.next;
308 } 311 }
309 else /* no gc action; delete udata */ 312 else /* no gc event; delete udata */
310 luaM_free(L, curr, sizeudata(curr->uv.len)); 313 luaM_free(L, curr, sizeudata(curr->uv.len));
311 } 314 }
312 } 315 }
313 return collected; 316 /* insert collected udata with gc event into `tmudata' list */
317 *lastcollected = G(L)->tmudata;
318 G(L)->tmudata = collected;
314} 319}
315 320
316 321
@@ -365,12 +370,12 @@ static void callgcTM (lua_State *L, Udata *udata) {
365} 370}
366 371
367 372
368static void callgcTMudata (lua_State *L, Udata *c) { 373static void callgcTMudata (lua_State *L) {
369 luaD_checkstack(L, 3); 374 luaD_checkstack(L, 3);
370 L->top++; /* reserve space to keep udata while runs its gc method */ 375 L->top++; /* reserve space to keep udata while runs its gc method */
371 while (c != NULL) { 376 while (G(L)->tmudata != NULL) {
372 Udata *udata = c; 377 Udata *udata = G(L)->tmudata;
373 c = udata->uv.next; /* remove udata from list */ 378 G(L)->tmudata = udata->uv.next; /* remove udata from list */
374 udata->uv.next = G(L)->rootudata; /* resurect it */ 379 udata->uv.next = G(L)->rootudata; /* resurect it */
375 G(L)->rootudata = udata; 380 G(L)->rootudata = udata;
376 setuvalue(L->top - 1, udata); 381 setuvalue(L->top - 1, udata);
@@ -383,34 +388,32 @@ static void callgcTMudata (lua_State *L, Udata *c) {
383 388
384 389
385void luaC_callallgcTM (lua_State *L) { 390void luaC_callallgcTM (lua_State *L) {
386 if (G(L)->rootudata) { /* avoid problems with incomplete states */ 391 lua_assert(G(L)->tmudata == NULL);
387 Udata *c = collectudata(L, 1); /* collect all udata */ 392 G(L)->tmudata = G(L)->rootudata; /* all udata must be collected */
388 callgcTMudata(L, c); /* call their GC tag methods */ 393 G(L)->rootudata = NULL;
389 } 394 callgcTMudata(L); /* call their GC tag methods */
390} 395}
391 396
392 397
393Udata *luaC_collect (lua_State *L, int all) { 398void luaC_collect (lua_State *L, int all) {
394 Udata *c = collectudata(L, 0); 399 collectudata(L);
395 collectstrings(L, all); 400 collectstrings(L, all);
396 collecttable(L); 401 collecttable(L);
397 collectproto(L); 402 collectproto(L);
398 collectupval(L); 403 collectupval(L);
399 collectclosures(L); 404 collectclosures(L);
400 return c;
401} 405}
402 406
403 407
404void luaC_collectgarbage (lua_State *L) { 408void luaC_collectgarbage (lua_State *L) {
405 Udata *c;
406 GCState st; 409 GCState st;
407 st.tmark = NULL; 410 st.tmark = NULL;
408 st.toclear = NULL; 411 st.toclear = NULL;
409 markall(L, &st); 412 markall(L, &st);
410 cleartables(st.toclear); 413 cleartables(st.toclear);
411 c = luaC_collect(L, 0); 414 luaC_collect(L, 0);
412 checkMbuffer(L); 415 checkMbuffer(L);
413 G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ 416 G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */
414 callgcTMudata(L, c); 417 callgcTMudata(L);
415} 418}
416 419
diff --git a/lstate.c b/lstate.c
index 35518cbc..6f66df93 100644
--- a/lstate.c
+++ b/lstate.c
@@ -59,8 +59,9 @@ static void f_luaopen (lua_State *L, void *ud) {
59 G(L)->rootproto = NULL; 59 G(L)->rootproto = NULL;
60 G(L)->rootcl = NULL; 60 G(L)->rootcl = NULL;
61 G(L)->roottable = NULL; 61 G(L)->roottable = NULL;
62 G(L)->rootudata = NULL;
63 G(L)->rootupval = NULL; 62 G(L)->rootupval = NULL;
63 G(L)->rootudata = NULL;
64 G(L)->tmudata = NULL;
64 G(L)->nblocks = sizeof(lua_State) + sizeof(global_State); 65 G(L)->nblocks = sizeof(lua_State) + sizeof(global_State);
65 luaD_init(L, so->stacksize); /* init stack */ 66 luaD_init(L, so->stacksize); /* init stack */
66 /* create default event table with a dummy table, and then close the loop */ 67 /* create default event table with a dummy table, and then close the loop */
@@ -118,6 +119,7 @@ static void close_state (lua_State *L, lua_State *OL) {
118 else if (G(L)) { /* last thread; close global state */ 119 else if (G(L)) { /* last thread; close global state */
119 if (G(L)->rootudata) /* (avoid problems with incomplete states) */ 120 if (G(L)->rootudata) /* (avoid problems with incomplete states) */
120 luaC_callallgcTM(L); /* call GC tag methods for all udata */ 121 luaC_callallgcTM(L); /* call GC tag methods for all udata */
122 lua_assert(G(L)->tmudata == NULL);
121 luaC_collect(L, 1); /* collect all elements */ 123 luaC_collect(L, 1); /* collect all elements */
122 lua_assert(G(L)->rootproto == NULL); 124 lua_assert(G(L)->rootproto == NULL);
123 lua_assert(G(L)->rootudata == NULL); 125 lua_assert(G(L)->rootudata == NULL);
diff --git a/lstate.h b/lstate.h
index 84d3358e..158f7f8a 100644
--- a/lstate.h
+++ b/lstate.h
@@ -81,8 +81,9 @@ typedef struct global_State {
81 Proto *rootproto; /* list of all prototypes */ 81 Proto *rootproto; /* list of all prototypes */
82 Closure *rootcl; /* list of all closures */ 82 Closure *rootcl; /* list of all closures */
83 Table *roottable; /* list of all tables */ 83 Table *roottable; /* list of all tables */
84 Udata *rootudata; /* list of all userdata */
85 UpVal *rootupval; /* list of closed up values */ 84 UpVal *rootupval; /* list of closed up values */
85 Udata *rootudata; /* list of all userdata */
86 Udata *tmudata; /* list of userdata to be GC */
86 TString *tmname[TM_N]; /* array with tag-method names */ 87 TString *tmname[TM_N]; /* array with tag-method names */
87} global_State; 88} global_State;
88 89