aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c76
1 files changed, 46 insertions, 30 deletions
diff --git a/lgc.c b/lgc.c
index 935d8c1b..93316741 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.37 2005/12/22 16:19:56 roberto Exp roberto $ 2** $Id: lgc.c,v 2.38 2006/05/24 14:34:06 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -52,7 +52,7 @@
52#define markvalue(g,o) { checkconsistency(o); \ 52#define markvalue(g,o) { checkconsistency(o); \
53 if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } 53 if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
54 54
55#define markobject(g,t) { if (iswhite(obj2gco(t))) \ 55#define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \
56 reallymarkobject(g, obj2gco(t)); } 56 reallymarkobject(g, obj2gco(t)); }
57 57
58 58
@@ -76,7 +76,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
76 case LUA_TUSERDATA: { 76 case LUA_TUSERDATA: {
77 Table *mt = gco2u(o)->metatable; 77 Table *mt = gco2u(o)->metatable;
78 gray2black(o); /* udata are never gray */ 78 gray2black(o); /* udata are never gray */
79 if (mt) markobject(g, mt); 79 markobject(g, mt);
80 markobject(g, gco2u(o)->env); 80 markobject(g, gco2u(o)->env);
81 return; 81 return;
82 } 82 }
@@ -160,8 +160,7 @@ static int traversetable (global_State *g, Table *h) {
160 int weakkey = 0; 160 int weakkey = 0;
161 int weakvalue = 0; 161 int weakvalue = 0;
162 const TValue *mode; 162 const TValue *mode;
163 if (h->metatable) 163 markobject(g, h->metatable);
164 markobject(g, h->metatable);
165 mode = gfasttm(g, h->metatable, TM_MODE); 164 mode = gfasttm(g, h->metatable, TM_MODE);
166 if (mode && ttisstring(mode)) { /* is there a weak mode? */ 165 if (mode && ttisstring(mode)) { /* is there a weak mode? */
167 weakkey = (strchr(svalue(mode), 'k') != NULL); 166 weakkey = (strchr(svalue(mode), 'k') != NULL);
@@ -209,10 +208,8 @@ static void traverseproto (global_State *g, Proto *f) {
209 if (f->upvalues[i]) 208 if (f->upvalues[i])
210 stringmark(f->upvalues[i]); 209 stringmark(f->upvalues[i]);
211 } 210 }
212 for (i=0; i<f->sizep; i++) { /* mark nested protos */ 211 for (i=0; i<f->sizep; i++) /* mark nested protos */
213 if (f->p[i]) 212 markobject(g, f->p[i]);
214 markobject(g, f->p[i]);
215 }
216 for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */ 213 for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */
217 if (f->locvars[i].varname) 214 if (f->locvars[i].varname)
218 stringmark(f->locvars[i].varname); 215 stringmark(f->locvars[i].varname);
@@ -256,6 +253,8 @@ static void checkstacksizes (lua_State *L, StkId max) {
256static void traversestack (global_State *g, lua_State *l) { 253static void traversestack (global_State *g, lua_State *l) {
257 StkId o, lim; 254 StkId o, lim;
258 CallInfo *ci; 255 CallInfo *ci;
256 if (l->stack == NULL || l->base_ci == NULL)
257 return; /* stack not completely built yet */
259 markvalue(g, gt(l)); 258 markvalue(g, gt(l));
260 lim = l->top; 259 lim = l->top;
261 for (ci = l->base_ci; ci <= l->ci; ci++) { 260 for (ci = l->base_ci; ci <= l->ci; ci++) {
@@ -266,7 +265,8 @@ static void traversestack (global_State *g, lua_State *l) {
266 markvalue(g, o); 265 markvalue(g, o);
267 for (; o <= lim; o++) 266 for (; o <= lim; o++)
268 setnilvalue(o); 267 setnilvalue(o);
269 checkstacksizes(l, lim); 268 if (!g->emergencygc) /* cannot change stack in emergency... */
269 checkstacksizes(l, lim); /* ...(interpreter does not expect that change) */
270} 270}
271 271
272 272
@@ -442,11 +442,9 @@ static void checkSizes (lua_State *L) {
442} 442}
443 443
444 444
445static void GCTM (lua_State *L) { 445static Udata *udata2finalize (global_State *g) {
446 global_State *g = G(L);
447 GCObject *o = g->tmudata->gch.next; /* get first element */ 446 GCObject *o = g->tmudata->gch.next; /* get first element */
448 Udata *udata = rawgco2u(o); 447 Udata *udata = rawgco2u(o);
449 const TValue *tm;
450 /* remove udata from `tmudata' */ 448 /* remove udata from `tmudata' */
451 if (o == g->tmudata) /* last element? */ 449 if (o == g->tmudata) /* last element? */
452 g->tmudata = NULL; 450 g->tmudata = NULL;
@@ -455,7 +453,14 @@ static void GCTM (lua_State *L) {
455 udata->uv.next = g->mainthread->next; /* return it to `root' list */ 453 udata->uv.next = g->mainthread->next; /* return it to `root' list */
456 g->mainthread->next = o; 454 g->mainthread->next = o;
457 makewhite(g, o); 455 makewhite(g, o);
458 tm = fasttm(L, udata->uv.metatable, TM_GC); 456 return udata;
457}
458
459
460static void GCTM (lua_State *L) {
461 global_State *g = G(L);
462 Udata *udata = udata2finalize(g);
463 const TValue *tm = fasttm(L, udata->uv.metatable, TM_GC);
459 if (tm != NULL) { 464 if (tm != NULL) {
460 lu_byte oldah = L->allowhook; 465 lu_byte oldah = L->allowhook;
461 lu_mem oldt = g->GCthreshold; 466 lu_mem oldt = g->GCthreshold;
@@ -475,8 +480,17 @@ static void GCTM (lua_State *L) {
475** Call all GC tag methods 480** Call all GC tag methods
476*/ 481*/
477void luaC_callGCTM (lua_State *L) { 482void luaC_callGCTM (lua_State *L) {
478 while (G(L)->tmudata) 483 global_State *g = G(L);
484 GCObject *last = g->tmudata;
485 GCObject *curr;
486 if (last == NULL) return; /* empty list? */
487 do {
488 curr = g->tmudata->gch.next; /* element to be collected */
479 GCTM(L); 489 GCTM(L);
490 } while (curr != last); /* go only until original last */
491 /* do not finalize new udata created during previous finalizations */
492 while (g->tmudata)
493 udata2finalize(g); /* simply remove them from list */
480} 494}
481 495
482 496
@@ -493,7 +507,7 @@ void luaC_freeall (lua_State *L) {
493static void markmt (global_State *g) { 507static void markmt (global_State *g) {
494 int i; 508 int i;
495 for (i=0; i<NUM_TAGS; i++) 509 for (i=0; i<NUM_TAGS; i++)
496 if (g->mt[i]) markobject(g, g->mt[i]); 510 markobject(g, g->mt[i]);
497} 511}
498 512
499 513
@@ -553,6 +567,10 @@ static void atomic (lua_State *L) {
553} 567}
554 568
555 569
570#define correctestimate(g,s) {lu_mem old = g->totalbytes; s; \
571 lua_assert(old >= g->totalbytes); g->estimate -= old - g->totalbytes;}
572
573
556static l_mem singlestep (lua_State *L) { 574static l_mem singlestep (lua_State *L) {
557 global_State *g = G(L); 575 global_State *g = G(L);
558 /*lua_checkmemory(L);*/ 576 /*lua_checkmemory(L);*/
@@ -570,23 +588,15 @@ static l_mem singlestep (lua_State *L) {
570 } 588 }
571 } 589 }
572 case GCSsweepstring: { 590 case GCSsweepstring: {
573 lu_mem old = g->totalbytes; 591 correctestimate(g, sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]));
574 sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
575 if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ 592 if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */
576 g->gcstate = GCSsweep; /* end sweep-string phase */ 593 g->gcstate = GCSsweep; /* end sweep-string phase */
577 lua_assert(old >= g->totalbytes);
578 g->estimate -= old - g->totalbytes;
579 return GCSWEEPCOST; 594 return GCSWEEPCOST;
580 } 595 }
581 case GCSsweep: { 596 case GCSsweep: {
582 lu_mem old = g->totalbytes; 597 correctestimate(g, g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX));
583 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); 598 if (*g->sweepgc == NULL) /* nothing more to sweep? */
584 if (*g->sweepgc == NULL) { /* nothing more to sweep? */
585 checkSizes(L);
586 g->gcstate = GCSfinalize; /* end sweep phase */ 599 g->gcstate = GCSfinalize; /* end sweep phase */
587 }
588 lua_assert(old >= g->totalbytes);
589 g->estimate -= old - g->totalbytes;
590 return GCSWEEPMAX*GCSWEEPCOST; 600 return GCSWEEPMAX*GCSWEEPCOST;
591 } 601 }
592 case GCSfinalize: { 602 case GCSfinalize: {
@@ -597,6 +607,7 @@ static l_mem singlestep (lua_State *L) {
597 return GCFINALIZECOST; 607 return GCFINALIZECOST;
598 } 608 }
599 else { 609 else {
610 correctestimate(g, checkSizes(L));
600 g->gcstate = GCSpause; /* end collection */ 611 g->gcstate = GCSpause; /* end collection */
601 g->gcdept = 0; 612 g->gcdept = 0;
602 return 0; 613 return 0;
@@ -610,6 +621,7 @@ static l_mem singlestep (lua_State *L) {
610void luaC_step (lua_State *L) { 621void luaC_step (lua_State *L) {
611 global_State *g = G(L); 622 global_State *g = G(L);
612 l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; 623 l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
624 lua_assert(!g->emergencygc);
613 if (lim == 0) 625 if (lim == 0)
614 lim = (MAX_LUMEM-1)/2; /* no limit */ 626 lim = (MAX_LUMEM-1)/2; /* no limit */
615 g->gcdept += g->totalbytes - g->GCthreshold; 627 g->gcdept += g->totalbytes - g->GCthreshold;
@@ -633,8 +645,10 @@ void luaC_step (lua_State *L) {
633} 645}
634 646
635 647
636void luaC_fullgc (lua_State *L) { 648void luaC_fullgc (lua_State *L, int isemergency) {
649 int stopstate;
637 global_State *g = G(L); 650 global_State *g = G(L);
651 g->emergencygc = isemergency;
638 if (g->gcstate <= GCSpropagate) { 652 if (g->gcstate <= GCSpropagate) {
639 /* reset sweep marks to sweep all elements (returning them to white) */ 653 /* reset sweep marks to sweep all elements (returning them to white) */
640 g->sweepstrgc = 0; 654 g->sweepstrgc = 0;
@@ -652,10 +666,12 @@ void luaC_fullgc (lua_State *L) {
652 singlestep(L); 666 singlestep(L);
653 } 667 }
654 markroot(L); 668 markroot(L);
655 while (g->gcstate != GCSpause) { 669 /* do not run finalizers during emergency GC */
670 stopstate = isemergency ? GCSfinalize : GCSpause;
671 while (g->gcstate != stopstate)
656 singlestep(L); 672 singlestep(L);
657 }
658 setthreshold(g); 673 setthreshold(g);
674 g->emergencygc = 0;
659} 675}
660 676
661 677