diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-12-12 16:29:34 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-12-12 16:29:34 -0200 |
commit | beb2aa5a46d0f0a8464f4045b1cfb790e97f08c7 (patch) | |
tree | 2ddcd1ac23b6a4275fc6d16b0316651b7cfb87f6 /lgc.c | |
parent | 47fc57a2529c83376883f36954082cfe80ae588f (diff) | |
download | lua-beb2aa5a46d0f0a8464f4045b1cfb790e97f08c7.tar.gz lua-beb2aa5a46d0f0a8464f4045b1cfb790e97f08c7.tar.bz2 lua-beb2aa5a46d0f0a8464f4045b1cfb790e97f08c7.zip |
atomic operations are not GC "states"
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 122 |
1 files changed, 54 insertions, 68 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.187 2003/12/09 16:56:11 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.1 2003/12/10 12:13:36 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 | */ |
@@ -22,7 +22,7 @@ | |||
22 | #include "ltm.h" | 22 | #include "ltm.h" |
23 | 23 | ||
24 | 24 | ||
25 | #define GCSTEPSIZE (20*sizeof(TValue)) | 25 | #define GCSTEPSIZE (40*sizeof(TValue)) |
26 | 26 | ||
27 | 27 | ||
28 | #define gray2black(x) setbit((x)->gch.marked, BLACKBIT) | 28 | #define gray2black(x) setbit((x)->gch.marked, BLACKBIT) |
@@ -104,8 +104,7 @@ static size_t objsize (GCObject *o) { | |||
104 | 104 | ||
105 | 105 | ||
106 | static void reallymarkobject (global_State *g, GCObject *o) { | 106 | static void reallymarkobject (global_State *g, GCObject *o) { |
107 | lua_assert(iswhite(o)); | 107 | lua_assert(iswhite(o) && !isdead(g, o)); |
108 | lua_assert(!isdead(g, o)); | ||
109 | white2gray(o); | 108 | white2gray(o); |
110 | switch (o->gch.tt) { | 109 | switch (o->gch.tt) { |
111 | case LUA_TSTRING: { | 110 | case LUA_TSTRING: { |
@@ -348,7 +347,6 @@ static l_mem propagatemarks (global_State *g, l_mem lim) { | |||
348 | lim -= objsize(o); | 347 | lim -= objsize(o); |
349 | if (lim <= 0) return lim; | 348 | if (lim <= 0) return lim; |
350 | } | 349 | } |
351 | g->gcstate = GCSatomic; | ||
352 | return lim; | 350 | return lim; |
353 | } | 351 | } |
354 | 352 | ||
@@ -499,26 +497,22 @@ static void checkSizes (lua_State *L) { | |||
499 | 497 | ||
500 | static void GCTM (lua_State *L) { | 498 | static void GCTM (lua_State *L) { |
501 | global_State *g = G(L); | 499 | global_State *g = G(L); |
502 | if (g->tmudata == NULL) | 500 | GCObject *o = g->tmudata; |
503 | g->gcstate = GCSroot; /* will restart GC */ | 501 | Udata *udata = rawgco2u(o); |
504 | else { | 502 | const TValue *tm; |
505 | GCObject *o = g->tmudata; | 503 | g->tmudata = udata->uv.next; /* remove udata from `tmudata' */ |
506 | Udata *udata = rawgco2u(o); | 504 | udata->uv.next = g->firstudata->uv.next; /* return it to `root' list */ |
507 | const TValue *tm; | 505 | g->firstudata->uv.next = o; |
508 | g->tmudata = udata->uv.next; /* remove udata from `tmudata' */ | 506 | makewhite(g, o); |
509 | udata->uv.next = g->firstudata->uv.next; /* return it to `root' list */ | 507 | tm = fasttm(L, udata->uv.metatable, TM_GC); |
510 | g->firstudata->uv.next = o; | 508 | if (tm != NULL) { |
511 | makewhite(g, o); | 509 | lu_byte oldah = L->allowhook; |
512 | tm = fasttm(L, udata->uv.metatable, TM_GC); | 510 | L->allowhook = 0; /* stop debug hooks during GC tag method */ |
513 | if (tm != NULL) { | 511 | setobj2s(L, L->top, tm); |
514 | lu_byte oldah = L->allowhook; | 512 | setuvalue(L, L->top+1, udata); |
515 | L->allowhook = 0; /* stop debug hooks during GC tag method */ | 513 | L->top += 2; |
516 | setobj2s(L, L->top, tm); | 514 | luaD_call(L, L->top - 2, 0); |
517 | setuvalue(L, L->top+1, udata); | 515 | L->allowhook = oldah; /* restore hooks */ |
518 | L->top += 2; | ||
519 | luaD_call(L, L->top - 2, 0); | ||
520 | L->allowhook = oldah; /* restore hooks */ | ||
521 | } | ||
522 | } | 516 | } |
523 | } | 517 | } |
524 | 518 | ||
@@ -543,7 +537,7 @@ void luaC_sweepall (lua_State *L) { | |||
543 | /* mark root set */ | 537 | /* mark root set */ |
544 | static void markroot (lua_State *L) { | 538 | static void markroot (lua_State *L) { |
545 | global_State *g = G(L); | 539 | global_State *g = G(L); |
546 | lua_assert(g->gray == NULL); | 540 | lua_assert(g->gray == NULL && g->grayagain == NULL); |
547 | g->weak = NULL; | 541 | g->weak = NULL; |
548 | makewhite(g, obj2gco(g->mainthread)); | 542 | makewhite(g, obj2gco(g->mainthread)); |
549 | markobject(g, g->mainthread); | 543 | markobject(g, g->mainthread); |
@@ -555,8 +549,6 @@ static void markroot (lua_State *L) { | |||
555 | 549 | ||
556 | static void atomic (lua_State *L) { | 550 | static void atomic (lua_State *L) { |
557 | global_State *g = G(L); | 551 | global_State *g = G(L); |
558 | /* there may be some gray elements due to the write barrier */ | ||
559 | propagatemarks(g, MAXLMEM); /* traverse them */ | ||
560 | lua_assert(g->gray == NULL); | 552 | lua_assert(g->gray == NULL); |
561 | g->gray = g->grayagain; | 553 | g->gray = g->grayagain; |
562 | g->grayagain = NULL; | 554 | g->grayagain = NULL; |
@@ -577,60 +569,54 @@ static void atomic (lua_State *L) { | |||
577 | } | 569 | } |
578 | 570 | ||
579 | 571 | ||
580 | static void sweepstringstep (lua_State *L) { | ||
581 | global_State *g = G(L); | ||
582 | l_mem lim = sweepstrings(L, 0, GCSTEPSIZE); | ||
583 | if (lim == GCSTEPSIZE) { /* nothing more to sweep? */ | ||
584 | lua_assert(g->sweepstrgc > g->strt.size); | ||
585 | g->sweepstrgc = 0; | ||
586 | g->gcstate = GCSsweep; /* end sweep-string phase */ | ||
587 | } | ||
588 | } | ||
589 | |||
590 | |||
591 | static void sweepstep (lua_State *L) { | ||
592 | global_State *g = G(L); | ||
593 | l_mem lim = GCSTEPSIZE; | ||
594 | g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim); | ||
595 | if (lim == GCSTEPSIZE) { /* nothing more to sweep? */ | ||
596 | g->gcstate = GCSfinalize; /* end sweep phase */ | ||
597 | checkSizes(L); | ||
598 | } | ||
599 | } | ||
600 | |||
601 | |||
602 | void luaC_step (lua_State *L) { | 572 | void luaC_step (lua_State *L) { |
603 | global_State *g = G(L); | 573 | global_State *g = G(L); |
574 | l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * 2; | ||
604 | switch (g->gcstate) { | 575 | switch (g->gcstate) { |
605 | case GCSroot: | 576 | case GCSpropagate: { |
606 | markroot(L); | 577 | if (g->gray) |
607 | break; | 578 | lim = propagatemarks(g, lim); |
608 | case GCSpropagate: | 579 | else { /* no more `gray' objects */ |
609 | propagatemarks(g, GCSTEPSIZE); | 580 | atomic(L); /* finish mark phase */ |
610 | break; | 581 | lim = 0; |
611 | case GCSatomic: | 582 | } |
612 | atomic(L); | ||
613 | break; | 583 | break; |
614 | case GCSsweepstring: | 584 | } |
615 | sweepstringstep(L); | 585 | case GCSsweepstring: { |
586 | lim = sweepstrings(L, 0, lim); | ||
587 | if (g->sweepstrgc >= g->strt.size) { /* nothing more to sweep? */ | ||
588 | g->sweepstrgc = 0; | ||
589 | g->gcstate = GCSsweep; /* end sweep-string phase */ | ||
590 | } | ||
616 | break; | 591 | break; |
617 | case GCSsweep: | 592 | } |
618 | sweepstep(L); | 593 | case GCSsweep: { |
594 | g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim); | ||
595 | if (*g->sweepgc == NULL) { /* nothing more to sweep? */ | ||
596 | g->gcstate = GCSfinalize; /* end sweep phase */ | ||
597 | checkSizes(L); | ||
598 | } | ||
619 | break; | 599 | break; |
620 | case GCSfinalize: | 600 | } |
621 | GCTM(L); | 601 | case GCSfinalize: { |
602 | if (g->tmudata) { | ||
603 | GCTM(L); | ||
604 | lim = 0; | ||
605 | } | ||
606 | else /* no more `udata' to finalize */ | ||
607 | markroot(L); /* may restart collection */ | ||
622 | break; | 608 | break; |
609 | } | ||
623 | default: lua_assert(0); | 610 | default: lua_assert(0); |
624 | } | 611 | } |
625 | g->GCthreshold = g->nblocks + GCSTEPSIZE; | 612 | g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/2; |
626 | } | 613 | } |
627 | 614 | ||
628 | 615 | ||
629 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { | 616 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { |
630 | global_State *g = G(L); | 617 | global_State *g = G(L); |
631 | lua_assert(isblack(o) && iswhite(v)); | 618 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); |
632 | lua_assert(!isdead(g, v) && !isdead(g, o)); | 619 | if (g->gcstate >= GCSsweepstring) /* sweeping phases? */ |
633 | if (g->gcstate > GCSatomic) /* sweeping phases? */ | ||
634 | black2gray(o); /* just mark as gray to avoid other barriers */ | 620 | black2gray(o); /* just mark as gray to avoid other barriers */ |
635 | else /* breaking invariant! */ | 621 | else /* breaking invariant! */ |
636 | reallymarkobject(g, v); /* restore it */ | 622 | reallymarkobject(g, v); /* restore it */ |