aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lgc.c257
-rw-r--r--lgc.h17
-rw-r--r--lstate.c10
-rw-r--r--lstate.h7
-rw-r--r--lstring.c11
-rw-r--r--lstring.h3
-rw-r--r--ltests.c16
7 files changed, 162 insertions, 159 deletions
diff --git a/lgc.c b/lgc.c
index 86f4e637..561c6350 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.7 2004/04/30 20:13:38 roberto Exp roberto $ 2** $Id: lgc.c,v 2.8 2004/08/10 19:17:23 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*/
@@ -25,10 +25,11 @@
25 25
26#define GCSTEPSIZE (40*sizeof(TValue)) 26#define GCSTEPSIZE (40*sizeof(TValue))
27#define STEPMUL 2 27#define STEPMUL 2
28#define GCFREECOST (sizeof(TValue)/10) 28#define GCSWEEPMAX 40
29#define GCSWEEPCOST (sizeof(TValue)/20) 29#define GCSWEEPCOST 1
30#define GCFINALIZECOST (10*sizeof(TValue)) 30#define GCFINALIZECOST (10*sizeof(TValue))
31#define WAITNEXTCYCLE (10 * GCSTEPSIZE) 31#define WAITNEXTCYCLE (40 * GCSTEPSIZE)
32#define WAITNEXTCYCLEGN (200 * GCSTEPSIZE)
32 33
33 34
34#define FIXEDMASK bitmask(FIXEDBIT) 35#define FIXEDMASK bitmask(FIXEDBIT)
@@ -269,60 +270,61 @@ static void traversestack (global_State *g, lua_State *l) {
269 270
270 271
271/* 272/*
272** traverse a given `quantity' of gray objects, 273** traverse one gray object, turning it to black.
273** turning them to black. Returns extra `quantity' traversed. 274** Returns `quantity' traversed.
274*/ 275*/
275static l_mem propagatemarks (global_State *g, l_mem lim) { 276static l_mem propagatemark (global_State *g) {
276 GCObject *o; 277 GCObject *o = g->gray;
277 while ((o = g->gray) != NULL) { 278 lua_assert(isgray(o));
278 lua_assert(isgray(o)); 279 gray2black(o);
279 gray2black(o); 280 switch (o->gch.tt) {
280 switch (o->gch.tt) { 281 case LUA_TTABLE: {
281 case LUA_TTABLE: { 282 Table *h = gco2h(o);
282 Table *h = gco2h(o); 283 g->gray = h->gclist;
283 g->gray = h->gclist; 284 if (traversetable(g, h)) /* table is weak? */
284 if (traversetable(g, h)) /* table is weak? */ 285 black2gray(o); /* keep it gray */
285 black2gray(o); /* keep it gray */ 286 return sizeof(Table) + sizeof(TValue) * h->sizearray +
286 lim -= sizeof(Table) + sizeof(TValue) * h->sizearray + 287 sizeof(Node) * sizenode(h);
287 sizeof(Node) * sizenode(h); 288 break;
288 break; 289 }
289 } 290 case LUA_TFUNCTION: {
290 case LUA_TFUNCTION: { 291 Closure *cl = gco2cl(o);
291 Closure *cl = gco2cl(o); 292 g->gray = cl->c.gclist;
292 g->gray = cl->c.gclist; 293 traverseclosure(g, cl);
293 traverseclosure(g, cl); 294 return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
294 lim -= (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : 295 sizeLclosure(cl->l.nupvalues);
295 sizeLclosure(cl->l.nupvalues); 296 break;
296 break;
297 }
298 case LUA_TTHREAD: {
299 lua_State *th = gco2th(o);
300 g->gray = th->gclist;
301 th->gclist = g->grayagain;
302 g->grayagain = o;
303 black2gray(o);
304 traversestack(g, th);
305 lim -= sizeof(lua_State) + sizeof(TValue) * th->stacksize +
306 sizeof(CallInfo) * th->size_ci;
307 break;
308 }
309 case LUA_TPROTO: {
310 Proto *p = gco2p(o);
311 g->gray = p->gclist;
312 traverseproto(g, p);
313 lim -= sizeof(Proto) + sizeof(Instruction) * p->sizecode +
314 sizeof(Proto *) * p->sizep +
315 sizeof(TValue) * p->sizek +
316 sizeof(int) * p->sizelineinfo +
317 sizeof(LocVar) * p->sizelocvars +
318 sizeof(TString *) * p->sizeupvalues;
319 break;
320 }
321 default: lua_assert(0);
322 } 297 }
323 if (lim <= 0) return lim; 298 case LUA_TTHREAD: {
299 lua_State *th = gco2th(o);
300 g->gray = th->gclist;
301 th->gclist = g->grayagain;
302 g->grayagain = o;
303 black2gray(o);
304 traversestack(g, th);
305 return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
306 sizeof(CallInfo) * th->size_ci;
307 break;
308 }
309 case LUA_TPROTO: {
310 Proto *p = gco2p(o);
311 g->gray = p->gclist;
312 traverseproto(g, p);
313 return sizeof(Proto) + sizeof(Instruction) * p->sizecode +
314 sizeof(Proto *) * p->sizep +
315 sizeof(TValue) * p->sizek +
316 sizeof(int) * p->sizelineinfo +
317 sizeof(LocVar) * p->sizelocvars +
318 sizeof(TString *) * p->sizeupvalues;
319 break;
320 }
321 default: lua_assert(0); return 0;
324 } 322 }
325 return lim; 323}
324
325
326static void propagateall (global_State *g) {
327 while (g->gray) propagatemark(g);
326} 328}
327 329
328 330
@@ -384,6 +386,7 @@ static void freeobj (lua_State *L, GCObject *o) {
384 break; 386 break;
385 } 387 }
386 case LUA_TSTRING: { 388 case LUA_TSTRING: {
389 G(L)->strt.nuse--;
387 luaM_free(L, o, sizestring(gco2ts(o)->len)); 390 luaM_free(L, o, sizestring(gco2ts(o)->len));
388 break; 391 break;
389 } 392 }
@@ -396,59 +399,50 @@ static void freeobj (lua_State *L, GCObject *o) {
396} 399}
397 400
398 401
399static l_mem sweepwholelist (lua_State *L, GCObject **p, int keepfixed, 402
400 lu_int32 *count); 403#define sweepwholelist(L,p) sweeplist(L,p,LUA_MAXINT32)
401 404
402 405
403static GCObject **sweeplist (lua_State *L, GCObject **p, int keepfixed, 406static GCObject **sweeplist (lua_State *L, GCObject **p, lu_int32 count) {
404 l_mem *plim, lu_int32 *count) {
405 GCObject *curr; 407 GCObject *curr;
406 global_State *g = G(L); 408 global_State *g = G(L);
407 l_mem lim = *plim; 409 int whitebit = otherwhite(g);
408 int deadmask = otherwhite(g); 410 int deadmask = whitebit | FIXEDMASK;
409 if (keepfixed) deadmask |= FIXEDMASK;
410 while ((curr = *p) != NULL) { 411 while ((curr = *p) != NULL) {
411 if (((curr->gch.marked ^ FIXEDMASK) & deadmask) != deadmask) { 412 if ((curr->gch.marked ^ whitebit) & deadmask) {
412 makewhite(g, curr); 413 lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));
414 if (!G(L)->gcgenerational || isdead(g, curr))
415 makewhite(g, curr);
413 if (curr->gch.tt == LUA_TTHREAD) 416 if (curr->gch.tt == LUA_TTHREAD)
414 lim -= sweepwholelist(L, &gco2th(curr)->openupval, keepfixed, count); 417 sweepwholelist(L, &gco2th(curr)->openupval);
415 p = &curr->gch.next; 418 p = &curr->gch.next;
416 lim -= GCSWEEPCOST;
417 } 419 }
418 else { 420 else {
419 lua_assert(iswhite(curr)); 421 lua_assert(isdead(g, curr));
420 *p = curr->gch.next; 422 *p = curr->gch.next;
421 if (curr == g->rootgc) /* is the first element of the list? */ 423 if (curr == g->rootgc) /* is the first element of the list? */
422 g->rootgc = curr->gch.next; /* adjust first */ 424 g->rootgc = curr->gch.next; /* adjust first */
423 freeobj(L, curr); 425 freeobj(L, curr);
424 lim -= GCFREECOST;
425 if (count) (*count)--;
426 } 426 }
427 if (lim <= 0) break; 427 if (count-- == 0) break;
428 } 428 }
429 *plim = lim;
430 return p; 429 return p;
431} 430}
432 431
433 432
434static l_mem sweepwholelist (lua_State *L, GCObject **p, int keepfixed, 433static void sweepstrings (lua_State *L) {
435 lu_int32 *count) { 434 global_State *g = G(L);
436 l_mem lim = MAXLMEM; 435 sweepwholelist(L, &G(L)->strt.hash[g->sweepstrgc++]);
437 /* empty lists are quite common here, so avoid useless calls */
438 if (*p) sweeplist(L, p, keepfixed, &lim, count);
439 return MAXLMEM - lim;
440} 436}
441 437
442 438
443static l_mem sweepstrings (lua_State *L, int keepfixed, l_mem lim) { 439static void freelist (lua_State *L, GCObject **p) {
444 int i; 440 while (*p) {
445 global_State *g = G(L); 441 GCObject *curr = *p;
446 for (i = g->sweepstrgc; i < g->strt.size; i++) { /* for each list */ 442 *p = (*p)->gch.next;
447 lim -= sweepwholelist(L, &G(L)->strt.hash[i], keepfixed, &g->strt.nuse); 443 if (curr != obj2gco(L))
448 if (lim <= 0) break; 444 freeobj(L, curr);
449 } 445 }
450 g->sweepstrgc = i+1;
451 return lim;
452} 446}
453 447
454 448
@@ -497,19 +491,12 @@ void luaC_callGCTM (lua_State *L) {
497} 491}
498 492
499 493
500void luaC_sweepall (lua_State *L) { 494void luaC_freeall (lua_State *L) {
501 global_State *g = G(L); 495 global_State *g = G(L);
502 l_mem dummy = MAXLMEM; 496 int i;
503 /* finish (occasional) current sweep */ 497 freelist(L, &g->rootgc);
504 sweepstrings(L, 0, MAXLMEM); 498 for (i = 0; i < g->strt.size; i++) /* free all string lists */
505 sweeplist(L, &g->rootgc, 0, &dummy, NULL); 499 freelist(L, &G(L)->strt.hash[i]);
506 /* do a whole new sweep */
507 markobject(g, g->mainthread); /* cannot collect main thread */
508 g->currentwhite = otherwhite(g);
509 g->sweepgc = &g->rootgc;
510 g->sweepstrgc = 0;
511 sweepstrings(L, 0, MAXLMEM);
512 sweeplist(L, &g->rootgc, 0, &dummy, NULL);
513} 500}
514 501
515 502
@@ -553,64 +540,68 @@ static void atomic (lua_State *L) {
553 g->weak = NULL; 540 g->weak = NULL;
554 lua_assert(!iswhite(obj2gco(g->mainthread))); 541 lua_assert(!iswhite(obj2gco(g->mainthread)));
555 markobject(g, L); /* mark running thread */ 542 markobject(g, L); /* mark running thread */
556 propagatemarks(g, MAXLMEM); 543 propagateall(g);
557 /* remark gray again */ 544 /* remark gray again */
558 g->gray = g->grayagain; 545 g->gray = g->grayagain;
559 g->grayagain = NULL; 546 g->grayagain = NULL;
560 propagatemarks(g, MAXLMEM); 547 propagateall(g);
561 luaC_separateudata(L, 0); /* separate userdata to be preserved */ 548 luaC_separateudata(L, 0); /* separate userdata to be preserved */
562 marktmu(g); /* mark `preserved' userdata */ 549 marktmu(g); /* mark `preserved' userdata */
563 propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */ 550 propagateall(g); /* remark, to propagate `preserveness' */
564 cleartable(g->weak); /* remove collected objects from weak tables */ 551 cleartable(g->weak); /* remove collected objects from weak tables */
565 /* flip current white */ 552 /* flip current white */
566 g->currentwhite = otherwhite(g); 553 g->currentwhite = otherwhite(g);
554 g->sweepstrgc = 0;
555 g->sweepgc = &g->rootgc;
567 g->gcstate = GCSsweepstring; 556 g->gcstate = GCSsweepstring;
557 if (g->gcgenerational++ > 20) g->gcgenerational = 0;
568} 558}
569 559
570 560
571static l_mem singlestep (lua_State *L, l_mem lim) { 561static l_mem singlestep (lua_State *L) {
572 global_State *g = G(L); 562 global_State *g = G(L);
563 /*lua_checkmemory(L);*/
573 switch (g->gcstate) { 564 switch (g->gcstate) {
574 case GCSpropagate: { 565 case GCSpropagate: {
575 if (g->gray) 566 if (g->gray)
576 lim = propagatemarks(g, lim); 567 return propagatemark(g);
577 else { /* no more `gray' objects */ 568 else { /* no more `gray' objects */
578 atomic(L); /* finish mark phase */ 569 atomic(L); /* finish mark phase */
579 lim = 0; 570 return 0;
580 } 571 }
581 break;
582 } 572 }
583 case GCSsweepstring: { 573 case GCSsweepstring: {
584 lim = sweepstrings(L, 1, lim); 574 sweepstrings(L);
585 if (g->sweepstrgc >= g->strt.size) { /* nothing more to sweep? */ 575 if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */
586 g->sweepstrgc = 0;
587 g->gcstate = GCSsweep; /* end sweep-string phase */ 576 g->gcstate = GCSsweep; /* end sweep-string phase */
588 } 577 return GCSWEEPCOST;
589 break;
590 } 578 }
591 case GCSsweep: { 579 case GCSsweep: {
592 g->sweepgc = sweeplist(L, g->sweepgc, 1, &lim, NULL); 580 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
593 if (*g->sweepgc == NULL) { /* nothing more to sweep? */ 581 if (*g->sweepgc == NULL) { /* nothing more to sweep? */
594 checkSizes(L); 582 checkSizes(L);
595 g->sweepgc = &g->rootgc;
596 g->gcstate = GCSfinalize; /* end sweep phase */ 583 g->gcstate = GCSfinalize; /* end sweep phase */
597 } 584 }
598 break; 585 return GCSWEEPCOST;
599 } 586 }
600 case GCSfinalize: { 587 case GCSfinalize: {
601 if (g->tmudata) { 588 if (g->tmudata) {
602 GCTM(L); 589 GCTM(L);
603 lim -= GCFINALIZECOST; 590 return GCFINALIZECOST;
604 } 591 }
605 else { /* no more `udata' to finalize */ 592 else { /* no more `udata' to finalize */
606 markroot(L); /* may restart collection */ 593 if (g->gcgenerational) {
607 lim = 0; 594 atomic(L);
595 return WAITNEXTCYCLEGN;
596 }
597 else {
598 markroot(L); /* may restart collection */
599 return WAITNEXTCYCLE;
600 }
608 } 601 }
609 break;
610 } 602 }
611 default: lua_assert(0); 603 default: lua_assert(0); return 0;
612 } 604 }
613 return lim;
614} 605}
615 606
616 607
@@ -618,11 +609,7 @@ void luaC_step (lua_State *L) {
618 global_State *g = G(L); 609 global_State *g = G(L);
619 l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * STEPMUL; 610 l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * STEPMUL;
620 do { 611 do {
621 lim = singlestep(L, lim); 612 lim -= singlestep(L);
622 if (g->gcstate == GCSfinalize && g->tmudata == NULL) {
623 lim = -WAITNEXTCYCLE;
624 break; /* do not start new collection */
625 }
626 } while (lim > 0); 613 } while (lim > 0);
627 g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/STEPMUL; 614 g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/STEPMUL;
628 lua_assert((long)g->nblocks + (long)GCSTEPSIZE >= lim/STEPMUL); 615 lua_assert((long)g->nblocks + (long)GCSTEPSIZE >= lim/STEPMUL);
@@ -631,12 +618,26 @@ void luaC_step (lua_State *L) {
631 618
632void luaC_fullgc (lua_State *L) { 619void luaC_fullgc (lua_State *L) {
633 global_State *g = G(L); 620 global_State *g = G(L);
621 if (g->gcstate == GCSpropagate || g->gcgenerational) {
622 g->gcgenerational = 0;
623 /* reset sweep marks to sweep all elements (returning them to white) */
624 g->sweepstrgc = 0;
625 g->sweepgc = &g->rootgc;
626 /* reset other collector lists */
627 g->gray = NULL;
628 g->grayagain = NULL;
629 g->weak = NULL;
630 g->gcstate = GCSsweepstring;
631 }
632 /* finish any pending sweep phase */
634 while (g->gcstate != GCSfinalize) { 633 while (g->gcstate != GCSfinalize) {
635 singlestep(L, MAXLMEM); 634 singlestep(L);
636 } 635 }
637 markroot(L); 636 markroot(L);
637 lua_assert(!g->gcgenerational);
638 while (g->gcstate != GCSfinalize) { 638 while (g->gcstate != GCSfinalize) {
639 singlestep(L, MAXLMEM); 639 singlestep(L);
640 g->gcgenerational = 0; /* keep it in this mode */
640 } 641 }
641 g->GCthreshold = g->nblocks + GCSTEPSIZE; 642 g->GCthreshold = g->nblocks + GCSTEPSIZE;
642 luaC_callGCTM(L); /* call finalizers */ 643 luaC_callGCTM(L); /* call finalizers */
@@ -646,7 +647,7 @@ void luaC_fullgc (lua_State *L) {
646void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { 647void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
647 global_State *g = G(L); 648 global_State *g = G(L);
648 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); 649 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
649 lua_assert(g->gcstate != GCSfinalize); 650 lua_assert(g->gcgenerational || g->gcstate != GCSfinalize);
650 if (g->gcstate != GCSpropagate) /* sweeping phases? */ 651 if (g->gcstate != GCSpropagate) /* sweeping phases? */
651 black2gray(o); /* just mark as gray to avoid other barriers */ 652 black2gray(o); /* just mark as gray to avoid other barriers */
652 else /* breaking invariant! */ 653 else /* breaking invariant! */
@@ -657,7 +658,7 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
657void luaC_barrierback (lua_State *L, GCObject *o, GCObject *v) { 658void luaC_barrierback (lua_State *L, GCObject *o, GCObject *v) {
658 global_State *g = G(L); 659 global_State *g = G(L);
659 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); 660 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
660 lua_assert(g->gcstate != GCSfinalize); 661 lua_assert(g->gcgenerational || g->gcstate != GCSfinalize);
661 black2gray(o); /* make table gray (again) */ 662 black2gray(o); /* make table gray (again) */
662 gco2h(o)->gclist = g->grayagain; 663 gco2h(o)->gclist = g->grayagain;
663 g->grayagain = o; 664 g->grayagain = o;
@@ -679,7 +680,7 @@ void luaC_linkupval (lua_State *L, UpVal *uv) {
679 o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ 680 o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */
680 g->rootgc = o; 681 g->rootgc = o;
681 if (isgray(o)) { 682 if (isgray(o)) {
682 if (g->gcstate == GCSpropagate) { 683 if (g->gcstate == GCSpropagate || g->gcgenerational) {
683 gray2black(o); /* closed upvalues need barrier */ 684 gray2black(o); /* closed upvalues need barrier */
684 luaC_barrier(L, uv, uv->v); 685 luaC_barrier(L, uv, uv->v);
685 } 686 }
diff --git a/lgc.h b/lgc.h
index 56d5af39..c1d102f9 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.h,v 2.5 2004/03/15 21:04:33 roberto Exp roberto $ 2** $Id: lgc.h,v 2.6 2004/08/10 19:17:23 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*/
@@ -39,12 +39,13 @@
39 39
40/* 40/*
41** Layout for bit use in `marked' field: 41** Layout for bit use in `marked' field:
42** bit 0 - object is gray 42** bit 0 - object is white (type 0)
43** bit 1 - object is black 43** bit 1 - object is white (type 1)
44** bit 2 - For userdata: is finalized; 44** bit 2 - object is black
45 for tables: has weak keys 45** bit 3 - for userdata: has been finalized
46** bit 3 - for tables: has weak values 46** bit 3 - for tables: has weak keys
47** bit 4 - object is fixed (should not be collected) 47** bit 4 - for tables: has weak values
48** bit 5 - object is fixed (should not be collected)
48*/ 49*/
49 50
50#define WHITE0BIT 0 51#define WHITE0BIT 0
@@ -86,7 +87,7 @@
86 87
87size_t luaC_separateudata (lua_State *L, int all); 88size_t luaC_separateudata (lua_State *L, int all);
88void luaC_callGCTM (lua_State *L); 89void luaC_callGCTM (lua_State *L);
89void luaC_sweepall (lua_State *L); 90void luaC_freeall (lua_State *L);
90void luaC_step (lua_State *L); 91void luaC_step (lua_State *L);
91void luaC_fullgc (lua_State *L); 92void luaC_fullgc (lua_State *L);
92void luaC_link (lua_State *L, GCObject *o, lu_byte tt); 93void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
diff --git a/lstate.c b/lstate.c
index 0c7ca889..11f57728 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 2.9 2004/06/17 14:06:52 roberto Exp roberto $ 2** $Id: lstate.c,v 2.10 2004/06/17 14:25:31 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -122,9 +122,10 @@ static void preinit_state (lua_State *L, global_State *g) {
122static void close_state (lua_State *L) { 122static void close_state (lua_State *L) {
123 global_State *g = G(L); 123 global_State *g = G(L);
124 luaF_close(L, L->stack); /* close all upvalues for this thread */ 124 luaF_close(L, L->stack); /* close all upvalues for this thread */
125 luaC_sweepall(L); /* collect all elements */ 125 luaC_freeall(L); /* collect all objects */
126 lua_assert(g->rootgc == obj2gco(L)); 126 lua_assert(g->rootgc == NULL);
127 luaS_freeall(L); 127 lua_assert(g->strt.nuse == 0);
128 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
128 luaZ_freebuffer(L, &g->buff); 129 luaZ_freebuffer(L, &g->buff);
129 freestack(L, L); 130 freestack(L, L);
130 lua_assert(g->nblocks == sizeof(LG)); 131 lua_assert(g->nblocks == sizeof(LG));
@@ -177,6 +178,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
177 luaZ_initbuffer(L, &g->buff); 178 luaZ_initbuffer(L, &g->buff);
178 g->panic = NULL; 179 g->panic = NULL;
179 g->gcstate = GCSfinalize; 180 g->gcstate = GCSfinalize;
181 g->gcgenerational = 0;
180 g->rootgc = obj2gco(L); 182 g->rootgc = obj2gco(L);
181 g->sweepstrgc = 0; 183 g->sweepstrgc = 0;
182 g->sweepgc = &g->rootgc; 184 g->sweepgc = &g->rootgc;
diff --git a/lstate.h b/lstate.h
index bec73a5b..8c85b6f6 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 2.4 2004/05/31 18:51:50 roberto Exp roberto $ 2** $Id: lstate.h,v 2.5 2004/06/02 19:07:55 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -69,7 +69,9 @@ typedef struct global_State {
69 stringtable strt; /* hash table for strings */ 69 stringtable strt; /* hash table for strings */
70 lua_Alloc realloc; /* function to reallocate memory */ 70 lua_Alloc realloc; /* function to reallocate memory */
71 void *ud; /* auxiliary data to `realloc' */ 71 void *ud; /* auxiliary data to `realloc' */
72 int currentwhite; 72 lu_byte currentwhite;
73 lu_byte gcstate; /* state of garbage collector */
74 lu_byte gcgenerational;
73 GCObject *rootgc; /* list of all collectable objects */ 75 GCObject *rootgc; /* list of all collectable objects */
74 GCObject *firstudata; /* udata go to the end of `rootgc' */ 76 GCObject *firstudata; /* udata go to the end of `rootgc' */
75 GCObject **sweepgc; /* position of sweep in `rootgc' */ 77 GCObject **sweepgc; /* position of sweep in `rootgc' */
@@ -78,7 +80,6 @@ typedef struct global_State {
78 GCObject *grayagain; /* list of objects to be traversed atomically */ 80 GCObject *grayagain; /* list of objects to be traversed atomically */
79 GCObject *weak; /* list of weak tables (to be cleared) */ 81 GCObject *weak; /* list of weak tables (to be cleared) */
80 GCObject *tmudata; /* list of userdata to be GC */ 82 GCObject *tmudata; /* list of userdata to be GC */
81 int gcstate; /* state of garbage collector */
82 Mbuffer buff; /* temporary buffer for string concatentation */ 83 Mbuffer buff; /* temporary buffer for string concatentation */
83 lu_mem GCthreshold; 84 lu_mem GCthreshold;
84 lu_mem nblocks; /* number of `bytes' currently allocated */ 85 lu_mem nblocks; /* number of `bytes' currently allocated */
diff --git a/lstring.c b/lstring.c
index 8ecfb44e..13b75086 100644
--- a/lstring.c
+++ b/lstring.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstring.c,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $ 2** $Id: lstring.c,v 2.2 2004/04/30 20:13:38 roberto Exp roberto $
3** String table (keeps all strings handled by Lua) 3** String table (keeps all strings handled by Lua)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -19,17 +19,12 @@
19 19
20 20
21 21
22void luaS_freeall (lua_State *L) {
23 lua_assert(G(L)->strt.nuse==0);
24 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
25}
26
27
28void luaS_resize (lua_State *L, int newsize) { 22void luaS_resize (lua_State *L, int newsize) {
29 GCObject **newhash; 23 GCObject **newhash;
30 stringtable *tb; 24 stringtable *tb;
31 int i; 25 int i;
32 if (G(L)->sweepstrgc > 0) return; /* cannot resize during GC traverse */ 26 if (G(L)->gcstate == GCSsweepstring)
27 return; /* cannot resize during GC traverse */
33 newhash = luaM_newvector(L, newsize, GCObject *); 28 newhash = luaM_newvector(L, newsize, GCObject *);
34 tb = &G(L)->strt; 29 tb = &G(L)->strt;
35 for (i=0; i<newsize; i++) newhash[i] = NULL; 30 for (i=0; i<newsize; i++) newhash[i] = NULL;
diff --git a/lstring.h b/lstring.h
index 1fae1a58..dc3dc0e1 100644
--- a/lstring.h
+++ b/lstring.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstring.h,v 1.37 2002/08/16 14:45:55 roberto Exp roberto $ 2** $Id: lstring.h,v 1.38 2003/11/17 19:50:05 roberto Exp roberto $
3** String table (keep all strings handled by Lua) 3** String table (keep all strings handled by Lua)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -26,7 +26,6 @@
26 26
27void luaS_resize (lua_State *L, int newsize); 27void luaS_resize (lua_State *L, int newsize);
28Udata *luaS_newudata (lua_State *L, size_t s); 28Udata *luaS_newudata (lua_State *L, size_t s);
29void luaS_freeall (lua_State *L);
30TString *luaS_newlstr (lua_State *L, const char *str, size_t l); 29TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
31 30
32 31
diff --git a/ltests.c b/ltests.c
index 5f3b4bba..5f2cddf1 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 2.9 2004/06/02 19:08:52 roberto Exp roberto $ 2** $Id: ltests.c,v 2.10 2004/07/09 18:23:17 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -153,9 +153,9 @@ void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) {
153 153
154static int testobjref1 (global_State *g, GCObject *f, GCObject *t) { 154static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
155 if (isdead(g,t)) return 0; 155 if (isdead(g,t)) return 0;
156 if (g->gcstate == GCSpropagate) 156 if (g->gcstate == GCSpropagate || g->gcgenerational)
157 return !isblack(f) || !iswhite(t); 157 return !isblack(f) || !iswhite(t);
158 else if (g->gcstate == GCSfinalize) 158 else if (g->gcstate == GCSfinalize && !g->gcgenerational)
159 return iswhite(f); 159 return iswhite(f);
160 else 160 else
161 return 1; 161 return 1;
@@ -175,7 +175,8 @@ static void printobj (global_State *g, GCObject *o) {
175static int testobjref (global_State *g, GCObject *f, GCObject *t) { 175static int testobjref (global_State *g, GCObject *f, GCObject *t) {
176 int r = testobjref1(g,f,t); 176 int r = testobjref1(g,f,t);
177 if (!r) { 177 if (!r) {
178 printf("%d(%02X) - ", g->gcstate, g->currentwhite); 178 printf("%d(%02X) %c - ", g->gcstate, g->currentwhite,
179 g->gcgenerational ? 'G' : ' ');
179 printobj(g, f); 180 printobj(g, f);
180 printf("\t-> "); 181 printf("\t-> ");
181 printobj(g, t); 182 printobj(g, t);
@@ -290,9 +291,12 @@ static void checkstack (global_State *g, lua_State *L1) {
290 291
291static void checkobject (global_State *g, GCObject *o) { 292static void checkobject (global_State *g, GCObject *o) {
292 if (isdead(g, o)) 293 if (isdead(g, o))
293 lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); 294/* lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);*/
295{ if (!(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep))
296printf(">>> %d %s %02x\n", g->gcstate, luaT_typenames[o->gch.tt], o->gch.marked);
297}
294 else { 298 else {
295 if (g->gcstate == GCSfinalize) 299 if (g->gcstate == GCSfinalize && !g->gcgenerational)
296 lua_assert(iswhite(o)); 300 lua_assert(iswhite(o));
297 switch (o->gch.tt) { 301 switch (o->gch.tt) {
298 case LUA_TUPVAL: { 302 case LUA_TUPVAL: {