diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-03-23 09:57:12 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-03-23 09:57:12 -0300 |
commit | 178246062ccda6f8bd2cc2dc847ceb3b8800850c (patch) | |
tree | 4ea7f813b293dd24428171367d9538ff78d82a34 | |
parent | 24f2d1183c6bda0832456168c59109b6708b0738 (diff) | |
download | lua-178246062ccda6f8bd2cc2dc847ceb3b8800850c.tar.gz lua-178246062ccda6f8bd2cc2dc847ceb3b8800850c.tar.bz2 lua-178246062ccda6f8bd2cc2dc847ceb3b8800850c.zip |
reuse `sweeplist' for all lists
-rw-r--r-- | lgc.c | 83 |
1 files changed, 36 insertions, 47 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.4 2004/03/09 17:34:35 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.5 2004/03/15 21:04:33 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,6 +25,7 @@ | |||
25 | #define GCSTEPSIZE (40*sizeof(TValue)) | 25 | #define GCSTEPSIZE (40*sizeof(TValue)) |
26 | #define GCFREECOST (sizeof(TValue)/2) | 26 | #define GCFREECOST (sizeof(TValue)/2) |
27 | #define GCSWEEPCOST sizeof(TValue) | 27 | #define GCSWEEPCOST sizeof(TValue) |
28 | #define GCFINALIZECOST (10*sizeof(TValue)) | ||
28 | 29 | ||
29 | 30 | ||
30 | #define FIXEDMASK bitmask(FIXEDBIT) | 31 | #define FIXEDMASK bitmask(FIXEDBIT) |
@@ -392,31 +393,22 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
392 | } | 393 | } |
393 | 394 | ||
394 | 395 | ||
395 | static void sweepupvalues (global_State *g, lua_State *l) { | 396 | static l_mem sweepwholelist (lua_State *L, GCObject **p, int keepfixed, |
396 | GCObject *curr; | 397 | lu_int32 *count); |
397 | for (curr = l->openupval; curr != NULL; curr = curr->gch.next) | ||
398 | makewhite(g, curr); | ||
399 | } | ||
400 | |||
401 | |||
402 | /* | ||
403 | ** macros to test dead bit and optionally the fix bit | ||
404 | */ | ||
405 | #define makedeadmask(g,kf) (otherwhite(g) | ((kf) ? FIXEDMASK : 0)) | ||
406 | #define notdead(mark,mask) ((((mark) ^ FIXEDMASK) & mask) != mask) | ||
407 | 398 | ||
408 | 399 | ||
409 | static GCObject **sweeplist (lua_State *L, GCObject **p, int keepfixed, | 400 | static GCObject **sweeplist (lua_State *L, GCObject **p, int keepfixed, |
410 | l_mem *plim) { | 401 | l_mem *plim, lu_int32 *count) { |
411 | GCObject *curr; | 402 | GCObject *curr; |
412 | global_State *g = G(L); | 403 | global_State *g = G(L); |
413 | l_mem lim = *plim; | 404 | l_mem lim = *plim; |
414 | int deadmask = makedeadmask(g, keepfixed); | 405 | int deadmask = otherwhite(g); |
406 | if (keepfixed) deadmask |= FIXEDMASK; | ||
415 | while ((curr = *p) != NULL) { | 407 | while ((curr = *p) != NULL) { |
416 | if (notdead(curr->gch.marked, deadmask)) { | 408 | if (((curr->gch.marked ^ FIXEDMASK) & deadmask) != deadmask) { |
417 | makewhite(g, curr); | 409 | makewhite(g, curr); |
418 | if (curr->gch.tt == LUA_TTHREAD) | 410 | if (curr->gch.tt == LUA_TTHREAD) |
419 | sweepupvalues(g, gco2th(curr)); | 411 | lim -= sweepwholelist(L, &gco2th(curr)->openupval, keepfixed, count); |
420 | p = &curr->gch.next; | 412 | p = &curr->gch.next; |
421 | lim -= GCSWEEPCOST; | 413 | lim -= GCSWEEPCOST; |
422 | } | 414 | } |
@@ -427,6 +419,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int keepfixed, | |||
427 | g->rootgc = curr->gch.next; /* adjust first */ | 419 | g->rootgc = curr->gch.next; /* adjust first */ |
428 | freeobj(L, curr); | 420 | freeobj(L, curr); |
429 | lim -= GCFREECOST; | 421 | lim -= GCFREECOST; |
422 | if (count) (*count)--; | ||
430 | } | 423 | } |
431 | if (lim <= 0) break; | 424 | if (lim <= 0) break; |
432 | } | 425 | } |
@@ -435,28 +428,20 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int keepfixed, | |||
435 | } | 428 | } |
436 | 429 | ||
437 | 430 | ||
431 | static l_mem sweepwholelist (lua_State *L, GCObject **p, int keepfixed, | ||
432 | lu_int32 *count) { | ||
433 | l_mem lim = MAXLMEM; | ||
434 | /* empty lists are quite common here, so avoid useless calls */ | ||
435 | if (*p) sweeplist(L, p, keepfixed, &lim, count); | ||
436 | return MAXLMEM - lim; | ||
437 | } | ||
438 | |||
439 | |||
438 | static l_mem sweepstrings (lua_State *L, int keepfixed, l_mem lim) { | 440 | static l_mem sweepstrings (lua_State *L, int keepfixed, l_mem lim) { |
439 | int i; | 441 | int i; |
440 | global_State *g = G(L); | 442 | global_State *g = G(L); |
441 | int deadmask = makedeadmask(g, keepfixed); | ||
442 | for (i = g->sweepstrgc; i < g->strt.size; i++) { /* for each list */ | 443 | for (i = g->sweepstrgc; i < g->strt.size; i++) { /* for each list */ |
443 | GCObject *curr; | 444 | lim -= sweepwholelist(L, &G(L)->strt.hash[i], keepfixed, &g->strt.nuse); |
444 | GCObject **p = &G(L)->strt.hash[i]; | ||
445 | while ((curr = *p) != NULL) { | ||
446 | lu_mem size = sizestring(gco2ts(curr)->len); | ||
447 | if (notdead(curr->gch.marked, deadmask)) { | ||
448 | makewhite(g, curr); | ||
449 | lua_assert(iswhite(curr) && !isdead(g, curr)); | ||
450 | p = &curr->gch.next; | ||
451 | } | ||
452 | else { | ||
453 | lua_assert(iswhite(curr)); | ||
454 | g->strt.nuse--; | ||
455 | *p = curr->gch.next; | ||
456 | luaM_free(L, curr, size); | ||
457 | } | ||
458 | lim -= size; | ||
459 | } | ||
460 | if (lim <= 0) break; | 445 | if (lim <= 0) break; |
461 | } | 446 | } |
462 | g->sweepstrgc = i+1; | 447 | g->sweepstrgc = i+1; |
@@ -513,16 +498,15 @@ void luaC_sweepall (lua_State *L) { | |||
513 | global_State *g = G(L); | 498 | global_State *g = G(L); |
514 | l_mem dummy = MAXLMEM; | 499 | l_mem dummy = MAXLMEM; |
515 | /* finish (occasional) current sweep */ | 500 | /* finish (occasional) current sweep */ |
516 | markobject(g, g->mainthread); /* cannot collect main thread */ | ||
517 | sweepstrings(L, 0, MAXLMEM); | 501 | sweepstrings(L, 0, MAXLMEM); |
518 | sweeplist(L, &g->rootgc, 0, &dummy); | 502 | sweeplist(L, &g->rootgc, 0, &dummy, NULL); |
519 | /* do a whole new sweep */ | 503 | /* do a whole new sweep */ |
520 | markobject(g, g->mainthread); /* cannot collect main thread */ | 504 | markobject(g, g->mainthread); /* cannot collect main thread */ |
521 | g->currentwhite = otherwhite(g); | 505 | g->currentwhite = otherwhite(g); |
522 | g->sweepgc = &g->rootgc; | 506 | g->sweepgc = &g->rootgc; |
523 | g->sweepstrgc = 0; | 507 | g->sweepstrgc = 0; |
524 | sweepstrings(L, 0, MAXLMEM); | 508 | sweepstrings(L, 0, MAXLMEM); |
525 | sweeplist(L, &g->rootgc, 0, &dummy); | 509 | sweeplist(L, &g->rootgc, 0, &dummy, NULL); |
526 | } | 510 | } |
527 | 511 | ||
528 | 512 | ||
@@ -532,10 +516,10 @@ static void markroot (lua_State *L) { | |||
532 | lua_assert(g->gray == NULL); | 516 | lua_assert(g->gray == NULL); |
533 | g->grayagain = NULL; | 517 | g->grayagain = NULL; |
534 | g->weak = NULL; | 518 | g->weak = NULL; |
535 | makewhite(g, obj2gco(g->mainthread)); | ||
536 | markobject(g, g->mainthread); | 519 | markobject(g, g->mainthread); |
520 | /* make global table be traversed before main stack */ | ||
521 | markvalue(g, gt(g->mainthread)); | ||
537 | markvalue(g, registry(L)); | 522 | markvalue(g, registry(L)); |
538 | markobject(g, L); /* mark running thread */ | ||
539 | g->gcstate = GCSpropagate; | 523 | g->gcstate = GCSpropagate; |
540 | } | 524 | } |
541 | 525 | ||
@@ -600,7 +584,7 @@ static l_mem singlestep (lua_State *L, l_mem lim) { | |||
600 | break; | 584 | break; |
601 | } | 585 | } |
602 | case GCSsweep: { | 586 | case GCSsweep: { |
603 | g->sweepgc = sweeplist(L, g->sweepgc, 1, &lim); | 587 | g->sweepgc = sweeplist(L, g->sweepgc, 1, &lim, NULL); |
604 | if (*g->sweepgc == NULL) { /* nothing more to sweep? */ | 588 | if (*g->sweepgc == NULL) { /* nothing more to sweep? */ |
605 | checkSizes(L); | 589 | checkSizes(L); |
606 | g->sweepgc = &g->rootgc; | 590 | g->sweepgc = &g->rootgc; |
@@ -609,11 +593,14 @@ static l_mem singlestep (lua_State *L, l_mem lim) { | |||
609 | break; | 593 | break; |
610 | } | 594 | } |
611 | case GCSfinalize: { | 595 | case GCSfinalize: { |
612 | if (g->tmudata) | 596 | if (g->tmudata) { |
613 | GCTM(L); | 597 | GCTM(L); |
614 | else /* no more `udata' to finalize */ | 598 | lim -= GCFINALIZECOST; |
599 | } | ||
600 | else { /* no more `udata' to finalize */ | ||
615 | markroot(L); /* may restart collection */ | 601 | markroot(L); /* may restart collection */ |
616 | lim = 0; | 602 | lim = 0; |
603 | } | ||
617 | break; | 604 | break; |
618 | } | 605 | } |
619 | default: lua_assert(0); | 606 | default: lua_assert(0); |
@@ -625,10 +612,12 @@ static l_mem singlestep (lua_State *L, l_mem lim) { | |||
625 | void luaC_step (lua_State *L) { | 612 | void luaC_step (lua_State *L) { |
626 | global_State *g = G(L); | 613 | global_State *g = G(L); |
627 | l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * 2; | 614 | l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * 2; |
628 | /*printf("+ %d %lu %lu %ld\n", g->gcstate, g->nblocks, g->GCthreshold, lim);*/ | 615 | do { |
629 | while (lim > 0) lim = singlestep(L, lim); | 616 | lim = singlestep(L, lim); |
617 | if (g->gcstate == GCSfinalize && g->tmudata == NULL) | ||
618 | break; /* do not start new collection */ | ||
619 | } while (lim > 0); | ||
630 | g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/2; | 620 | g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/2; |
631 | /*printf("- %d %lu %lu %ld\n", g->gcstate, g->nblocks, g->GCthreshold, lim);*/ | ||
632 | lua_assert((long)g->nblocks + (long)GCSTEPSIZE >= lim/2); | 621 | lua_assert((long)g->nblocks + (long)GCSTEPSIZE >= lim/2); |
633 | } | 622 | } |
634 | 623 | ||