diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-12-09 14:56:11 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-12-09 14:56:11 -0200 |
| commit | df429f163ada6581d921e7f51b016f1abfeefddd (patch) | |
| tree | a1af3ce961377e6548074f706f65e2b34181918f | |
| parent | fe595a45c246faf2cf12084e7aac4b772f8f72da (diff) | |
| download | lua-df429f163ada6581d921e7f51b016f1abfeefddd.tar.gz lua-df429f163ada6581d921e7f51b016f1abfeefddd.tar.bz2 lua-df429f163ada6581d921e7f51b016f1abfeefddd.zip | |
First version of incremental GC
| -rw-r--r-- | lapi.c | 31 | ||||
| -rw-r--r-- | lcode.c | 6 | ||||
| -rw-r--r-- | lfunc.c | 5 | ||||
| -rw-r--r-- | lgc.c | 75 | ||||
| -rw-r--r-- | lgc.h | 25 | ||||
| -rw-r--r-- | lparser.c | 11 | ||||
| -rw-r--r-- | lstring.c | 7 | ||||
| -rw-r--r-- | ltable.c | 5 | ||||
| -rw-r--r-- | lvm.c | 17 |
9 files changed, 118 insertions, 64 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lapi.c,v 1.249 2003/10/20 17:42:41 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 1.250 2003/12/01 18:22:56 roberto Exp roberto $ |
| 3 | ** Lua API | 3 | ** Lua API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -193,7 +193,7 @@ LUA_API void lua_replace (lua_State *L, int idx) { | |||
| 193 | api_checknelems(L, 1); | 193 | api_checknelems(L, 1); |
| 194 | o = luaA_index(L, idx); | 194 | o = luaA_index(L, idx); |
| 195 | api_checkvalidindex(L, o); | 195 | api_checkvalidindex(L, o); |
| 196 | setobj(o, L->top - 1); /* write barrier */ | 196 | setobj(o, L->top - 1); /* write barrier???? */ |
| 197 | L->top--; | 197 | L->top--; |
| 198 | lua_unlock(L); | 198 | lua_unlock(L); |
| 199 | } | 199 | } |
| @@ -615,7 +615,8 @@ LUA_API void lua_rawset (lua_State *L, int idx) { | |||
| 615 | api_checknelems(L, 2); | 615 | api_checknelems(L, 2); |
| 616 | t = luaA_index(L, idx); | 616 | t = luaA_index(L, idx); |
| 617 | api_check(L, ttistable(t)); | 617 | api_check(L, ttistable(t)); |
| 618 | setobj2t(luaH_set(L, hvalue(t), L->top-2), L->top-1); /* write barrier */ | 618 | setobj2t(luaH_set(L, hvalue(t), L->top-2), L->top-1); |
| 619 | luaC_barrier(L, hvalue(t), L->top-1); | ||
| 619 | L->top -= 2; | 620 | L->top -= 2; |
| 620 | lua_unlock(L); | 621 | lua_unlock(L); |
| 621 | } | 622 | } |
| @@ -627,7 +628,8 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) { | |||
| 627 | api_checknelems(L, 1); | 628 | api_checknelems(L, 1); |
| 628 | o = luaA_index(L, idx); | 629 | o = luaA_index(L, idx); |
| 629 | api_check(L, ttistable(o)); | 630 | api_check(L, ttistable(o)); |
| 630 | setobj2t(luaH_setnum(L, hvalue(o), n), L->top-1); /* write barrier */ | 631 | setobj2t(luaH_setnum(L, hvalue(o), n), L->top-1); |
| 632 | luaC_barrier(L, hvalue(o), L->top-1); | ||
| 631 | L->top--; | 633 | L->top--; |
| 632 | lua_unlock(L); | 634 | lua_unlock(L); |
| 633 | } | 635 | } |
| @@ -649,11 +651,15 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { | |||
| 649 | } | 651 | } |
| 650 | switch (ttype(obj)) { | 652 | switch (ttype(obj)) { |
| 651 | case LUA_TTABLE: { | 653 | case LUA_TTABLE: { |
| 652 | hvalue(obj)->metatable = mt; /* write barrier */ | 654 | hvalue(obj)->metatable = mt; |
| 655 | if (mt) | ||
| 656 | luaC_objbarrier(L, hvalue(obj), mt); | ||
| 653 | break; | 657 | break; |
| 654 | } | 658 | } |
| 655 | case LUA_TUSERDATA: { | 659 | case LUA_TUSERDATA: { |
| 656 | uvalue(obj)->uv.metatable = mt; /* write barrier */ | 660 | uvalue(obj)->uv.metatable = mt; |
| 661 | if (mt) | ||
| 662 | luaC_objbarrier(L, uvalue(obj), mt); | ||
| 657 | break; | 663 | break; |
| 658 | } | 664 | } |
| 659 | default: { | 665 | default: { |
| @@ -907,10 +913,8 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { | |||
| 907 | 913 | ||
| 908 | 914 | ||
| 909 | 915 | ||
| 910 | static const char *aux_upvalue (lua_State *L, int funcindex, int n, | 916 | static const char *aux_upvalue (lua_State *L, StkId fi, int n, TObject **val) { |
| 911 | TObject **val) { | ||
| 912 | Closure *f; | 917 | Closure *f; |
| 913 | StkId fi = luaA_index(L, funcindex); | ||
| 914 | if (!ttisfunction(fi)) return NULL; | 918 | if (!ttisfunction(fi)) return NULL; |
| 915 | f = clvalue(fi); | 919 | f = clvalue(fi); |
| 916 | if (f->c.isC) { | 920 | if (f->c.isC) { |
| @@ -931,7 +935,7 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { | |||
| 931 | const char *name; | 935 | const char *name; |
| 932 | TObject *val; | 936 | TObject *val; |
| 933 | lua_lock(L); | 937 | lua_lock(L); |
| 934 | name = aux_upvalue(L, funcindex, n, &val); | 938 | name = aux_upvalue(L, luaA_index(L, funcindex), n, &val); |
| 935 | if (name) { | 939 | if (name) { |
| 936 | setobj2s(L->top, val); | 940 | setobj2s(L->top, val); |
| 937 | api_incr_top(L); | 941 | api_incr_top(L); |
| @@ -944,12 +948,15 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { | |||
| 944 | LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { | 948 | LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { |
| 945 | const char *name; | 949 | const char *name; |
| 946 | TObject *val; | 950 | TObject *val; |
| 951 | StkId fi; | ||
| 947 | lua_lock(L); | 952 | lua_lock(L); |
| 953 | fi = luaA_index(L, funcindex); | ||
| 948 | api_checknelems(L, 1); | 954 | api_checknelems(L, 1); |
| 949 | name = aux_upvalue(L, funcindex, n, &val); | 955 | name = aux_upvalue(L, fi, n, &val); |
| 950 | if (name) { | 956 | if (name) { |
| 951 | L->top--; | 957 | L->top--; |
| 952 | setobj(val, L->top); /* write barrier */ | 958 | setobj(val, L->top); |
| 959 | luaC_barrier(L, clvalue(fi), L->top); | ||
| 953 | } | 960 | } |
| 954 | lua_unlock(L); | 961 | lua_unlock(L); |
| 955 | return name; | 962 | return name; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 1.119 2003/08/27 21:01:44 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.120 2003/11/19 19:59:18 roberto Exp roberto $ |
| 3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "lcode.h" | 14 | #include "lcode.h" |
| 15 | #include "ldebug.h" | 15 | #include "ldebug.h" |
| 16 | #include "ldo.h" | 16 | #include "ldo.h" |
| 17 | #include "lgc.h" | ||
| 17 | #include "llex.h" | 18 | #include "llex.h" |
| 18 | #include "lmem.h" | 19 | #include "lmem.h" |
| 19 | #include "lobject.h" | 20 | #include "lobject.h" |
| @@ -219,7 +220,8 @@ static int addk (FuncState *fs, TObject *k, TObject *v) { | |||
| 219 | luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject, | 220 | luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject, |
| 220 | MAXARG_Bx, "constant table overflow"); | 221 | MAXARG_Bx, "constant table overflow"); |
| 221 | while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); | 222 | while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); |
| 222 | setobj(&f->k[fs->nk], v); /* write barrier */ | 223 | setobj(&f->k[fs->nk], v); |
| 224 | luaC_barrier(fs->L, f, v); | ||
| 223 | return fs->nk++; | 225 | return fs->nk++; |
| 224 | } | 226 | } |
| 225 | } | 227 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lfunc.c,v 1.72 2003/11/24 18:50:36 roberto Exp roberto $ | 2 | ** $Id: lfunc.c,v 1.73 2003/12/03 20:03:07 roberto Exp roberto $ |
| 3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -68,7 +68,8 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { | |||
| 68 | void luaF_close (lua_State *L, StkId level) { | 68 | void luaF_close (lua_State *L, StkId level) { |
| 69 | UpVal *uv; | 69 | UpVal *uv; |
| 70 | while ((uv = ngcotouv(L->openupval)) != NULL && uv->v >= level) { | 70 | while ((uv = ngcotouv(L->openupval)) != NULL && uv->v >= level) { |
| 71 | setobj(&uv->value, uv->v); /* save current value (write barrier) */ | 71 | setobj(&uv->value, uv->v); |
| 72 | luaC_barrier(L, uv, uv->v); | ||
| 72 | uv->v = &uv->value; /* now current value lives here */ | 73 | uv->v = &uv->value; /* now current value lives here */ |
| 73 | L->openupval = uv->next; /* remove from `open' list */ | 74 | L->openupval = uv->next; /* remove from `open' list */ |
| 74 | luaC_link(L, valtogco(uv), LUA_TUPVAL); | 75 | luaC_link(L, valtogco(uv), LUA_TUPVAL); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 1.185 2003/12/04 17:22:42 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.186 2003/12/04 18:52: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,12 +25,8 @@ | |||
| 25 | #define GCSTEPSIZE (20*sizeof(TObject)) | 25 | #define GCSTEPSIZE (20*sizeof(TObject)) |
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | #define otherwhite(g) (g->currentwhite ^ bit2mask(WHITE0BIT, WHITE1BIT)) | ||
| 29 | |||
| 30 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) | ||
| 31 | #define gray2black(x) setbit((x)->gch.marked, BLACKBIT) | 28 | #define gray2black(x) setbit((x)->gch.marked, BLACKBIT) |
| 32 | 29 | ||
| 33 | #define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) | ||
| 34 | #define maskmarks \ | 30 | #define maskmarks \ |
| 35 | cast(lu_byte, ~(bitmask(BLACKBIT)|bit2mask(WHITE0BIT, WHITE1BIT))) | 31 | cast(lu_byte, ~(bitmask(BLACKBIT)|bit2mask(WHITE0BIT, WHITE1BIT))) |
| 36 | #define makewhite(g,x) \ | 32 | #define makewhite(g,x) \ |
| @@ -47,7 +43,6 @@ | |||
| 47 | #define markfinalized(u) setbit((u)->uv.marked, FINALIZEDBIT) | 43 | #define markfinalized(u) setbit((u)->uv.marked, FINALIZEDBIT) |
| 48 | 44 | ||
| 49 | 45 | ||
| 50 | |||
| 51 | #define KEYWEAK bitmask(KEYWEAKBIT) | 46 | #define KEYWEAK bitmask(KEYWEAKBIT) |
| 52 | #define VALUEWEAK bitmask(VALUEWEAKBIT) | 47 | #define VALUEWEAK bitmask(VALUEWEAKBIT) |
| 53 | 48 | ||
| @@ -110,7 +105,7 @@ static size_t objsize (GCObject *o) { | |||
| 110 | 105 | ||
| 111 | static void reallymarkobject (global_State *g, GCObject *o) { | 106 | static void reallymarkobject (global_State *g, GCObject *o) { |
| 112 | lua_assert(iswhite(o)); | 107 | lua_assert(iswhite(o)); |
| 113 | lua_assert(!(o->gch.marked & otherwhite(g))); | 108 | lua_assert(!isdead(g, o)); |
| 114 | white2gray(o); | 109 | white2gray(o); |
| 115 | switch (o->gch.tt) { | 110 | switch (o->gch.tt) { |
| 116 | case LUA_TSTRING: { | 111 | case LUA_TSTRING: { |
| @@ -118,6 +113,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
| 118 | } | 113 | } |
| 119 | case LUA_TUSERDATA: { | 114 | case LUA_TUSERDATA: { |
| 120 | Table *mt = gcotou(o)->uv.metatable; | 115 | Table *mt = gcotou(o)->uv.metatable; |
| 116 | gray2black(o); /* udata are never gray */ | ||
| 121 | if (mt) markobject(g, mt); | 117 | if (mt) markobject(g, mt); |
| 122 | return; | 118 | return; |
| 123 | } | 119 | } |
| @@ -442,7 +438,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all, | |||
| 442 | int dead = otherwhite(g); | 438 | int dead = otherwhite(g); |
| 443 | while ((curr = *p) != NULL) { | 439 | while ((curr = *p) != NULL) { |
| 444 | int mark = curr->gch.marked; | 440 | int mark = curr->gch.marked; |
| 445 | lua_assert(all || !(mark & g->currentwhite)); | ||
| 446 | lim -= objsize(curr); | 441 | lim -= objsize(curr); |
| 447 | if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) { | 442 | if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) { |
| 448 | makewhite(g, curr); | 443 | makewhite(g, curr); |
| @@ -469,9 +464,9 @@ static l_mem sweepstrings (lua_State *L, int all, l_mem lim) { | |||
| 469 | while ((curr = *p) != NULL) { | 464 | while ((curr = *p) != NULL) { |
| 470 | int mark = curr->gch.marked; | 465 | int mark = curr->gch.marked; |
| 471 | lu_mem size = sizestring(gcotots(curr)->tsv.len); | 466 | lu_mem size = sizestring(gcotots(curr)->tsv.len); |
| 472 | lua_assert(all || !(mark & g->currentwhite)); | ||
| 473 | if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) { | 467 | if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) { |
| 474 | makewhite(g, curr); | 468 | makewhite(g, curr); |
| 469 | lua_assert(iswhite(curr) && !isdead(g, curr)); | ||
| 475 | p = &curr->gch.next; | 470 | p = &curr->gch.next; |
| 476 | } | 471 | } |
| 477 | else { | 472 | else { |
| @@ -499,8 +494,6 @@ static void checkSizes (lua_State *L) { | |||
| 499 | size_t newsize = luaZ_sizebuffer(&g->buff) / 2; | 494 | size_t newsize = luaZ_sizebuffer(&g->buff) / 2; |
| 500 | luaZ_resizebuffer(L, &g->buff, newsize); | 495 | luaZ_resizebuffer(L, &g->buff, newsize); |
| 501 | } | 496 | } |
| 502 | lua_assert(g->nblocks > g->GCthreshold); | ||
| 503 | g->GCthreshold = 2*G(L)->nblocks - g->GCthreshold; /* new threshold */ | ||
| 504 | } | 497 | } |
| 505 | 498 | ||
| 506 | 499 | ||
| @@ -562,11 +555,13 @@ static void markroot (lua_State *L) { | |||
| 562 | 555 | ||
| 563 | static void atomic (lua_State *L) { | 556 | static void atomic (lua_State *L) { |
| 564 | global_State *g = G(L); | 557 | global_State *g = G(L); |
| 558 | /* there may be some gray elements due to the write barrier */ | ||
| 559 | propagatemarks(g, MAXLMEM); /* traverse them */ | ||
| 565 | lua_assert(g->gray == NULL); | 560 | lua_assert(g->gray == NULL); |
| 566 | g->gray = g->grayagain; | 561 | g->gray = g->grayagain; |
| 567 | g->grayagain = NULL; | 562 | g->grayagain = NULL; |
| 568 | propagatemarks(g, MAXLMEM); | 563 | propagatemarks(g, MAXLMEM); |
| 569 | g->GCthreshold = luaC_separateudata(L); /* separate userdata to be preserved */ | 564 | luaC_separateudata(L); /* separate userdata to be preserved */ |
| 570 | marktmu(g); /* mark `preserved' userdata */ | 565 | marktmu(g); /* mark `preserved' userdata */ |
| 571 | propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */ | 566 | propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */ |
| 572 | cleartable(g->weak); /* remove collected objects from weak tables */ | 567 | cleartable(g->weak); /* remove collected objects from weak tables */ |
| @@ -597,30 +592,48 @@ static void sweepstep (lua_State *L) { | |||
| 597 | global_State *g = G(L); | 592 | global_State *g = G(L); |
| 598 | l_mem lim = GCSTEPSIZE; | 593 | l_mem lim = GCSTEPSIZE; |
| 599 | g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim); | 594 | g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim); |
| 600 | if (lim == GCSTEPSIZE) /* nothing more to sweep? */ | 595 | if (lim == GCSTEPSIZE) { /* nothing more to sweep? */ |
| 601 | g->gcstate = GCSfinalize; /* end sweep phase */ | 596 | g->gcstate = GCSfinalize; /* end sweep phase */ |
| 597 | checkSizes(L); | ||
| 598 | } | ||
| 602 | } | 599 | } |
| 603 | 600 | ||
| 604 | 601 | ||
| 605 | void luaC_collectgarbage (lua_State *L) { | 602 | void luaC_step (lua_State *L) { |
| 606 | global_State *g = G(L); | 603 | global_State *g = G(L); |
| 607 | /* GCSroot */ | 604 | switch (g->gcstate) { |
| 608 | markroot(L); | 605 | case GCSroot: |
| 609 | /* GCSpropagate */ | 606 | markroot(L); |
| 610 | while (g->gcstate == GCSpropagate) | 607 | break; |
| 611 | propagatemarks(g, GCSTEPSIZE); | 608 | case GCSpropagate: |
| 612 | /* atomic */ | 609 | propagatemarks(g, GCSTEPSIZE); |
| 613 | atomic(L); | 610 | break; |
| 614 | /* GCSsweepstring */ | 611 | case GCSatomic: |
| 615 | while (g->gcstate == GCSsweepstring) | 612 | atomic(L); |
| 616 | sweepstringstep(L); | 613 | break; |
| 617 | /* GCSsweep */ | 614 | case GCSsweepstring: |
| 618 | while (g->gcstate == GCSsweep) | 615 | sweepstringstep(L); |
| 619 | sweepstep(L); | 616 | break; |
| 620 | /* GCSfinalize */ | 617 | case GCSsweep: |
| 621 | checkSizes(L); | 618 | sweepstep(L); |
| 622 | while (g->gcstate == GCSfinalize) | 619 | break; |
| 623 | GCTM(L); | 620 | case GCSfinalize: |
| 621 | GCTM(L); | ||
| 622 | break; | ||
| 623 | default: lua_assert(0); | ||
| 624 | } | ||
| 625 | g->GCthreshold = g->nblocks + GCSTEPSIZE; | ||
| 626 | } | ||
| 627 | |||
| 628 | |||
| 629 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { | ||
| 630 | global_State *g = G(L); | ||
| 631 | lua_assert(isblack(o) && iswhite(v)); | ||
| 632 | lua_assert(!isdead(g, v) && !isdead(g, o)); | ||
| 633 | if (g->gcstate > GCSatomic) /* sweeping phases? */ | ||
| 634 | black2gray(o); /* just mark as gray to avoid other barriers */ | ||
| 635 | else /* breaking invariant! */ | ||
| 636 | reallymarkobject(g, v); /* restore it */ | ||
| 624 | } | 637 | } |
| 625 | 638 | ||
| 626 | 639 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.h,v 1.26 2003/12/03 20:03:07 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 1.27 2003/12/04 17:22:42 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 | */ |
| @@ -58,18 +58,37 @@ | |||
| 58 | #define FIXEDBIT 5 | 58 | #define FIXEDBIT 5 |
| 59 | 59 | ||
| 60 | 60 | ||
| 61 | #define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) | ||
| 62 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) | ||
| 63 | |||
| 64 | |||
| 65 | #define otherwhite(g) (g->currentwhite ^ bit2mask(WHITE0BIT, WHITE1BIT)) | ||
| 66 | #define isdead(g,v) ((v)->gch.marked & otherwhite(g)) | ||
| 67 | |||
| 68 | #define changewhite(x) ((x)->gch.marked ^= bit2mask(WHITE0BIT, WHITE1BIT)) | ||
| 69 | |||
| 70 | #define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) | ||
| 71 | |||
| 61 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite) | 72 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite) |
| 62 | 73 | ||
| 63 | 74 | ||
| 64 | #define luaC_checkGC(L) { if (G(L)->nblocks >= G(L)->GCthreshold) \ | 75 | #define luaC_checkGC(L) { if (G(L)->nblocks >= G(L)->GCthreshold) \ |
| 65 | luaC_collectgarbage(L); } | 76 | luaC_step(L); } |
| 77 | |||
| 78 | |||
| 79 | #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(valtogco(p))) \ | ||
| 80 | luaC_barrierf(L,valtogco(p),gcvalue(v)); } | ||
| 66 | 81 | ||
| 82 | #define luaC_objbarrier(L,p,o) \ | ||
| 83 | { if (iswhite(valtogco(o)) && isblack(valtogco(p))) \ | ||
| 84 | luaC_barrierf(L,valtogco(p),valtogco(o)); } | ||
| 67 | 85 | ||
| 68 | size_t luaC_separateudata (lua_State *L); | 86 | size_t luaC_separateudata (lua_State *L); |
| 69 | void luaC_callGCTM (lua_State *L); | 87 | void luaC_callGCTM (lua_State *L); |
| 70 | void luaC_sweepall (lua_State *L); | 88 | void luaC_sweepall (lua_State *L); |
| 71 | void luaC_collectgarbage (lua_State *L); | 89 | void luaC_step (lua_State *L); |
| 72 | void luaC_link (lua_State *L, GCObject *o, lu_byte tt); | 90 | void luaC_link (lua_State *L, GCObject *o, lu_byte tt); |
| 91 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); | ||
| 73 | 92 | ||
| 74 | 93 | ||
| 75 | #endif | 94 | #endif |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.c,v 1.220 2003/10/03 16:04:24 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.221 2003/10/09 17:56:23 roberto Exp roberto $ |
| 3 | ** Lua Parser | 3 | ** Lua Parser |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -151,7 +151,8 @@ static int luaI_registerlocalvar (LexState *ls, TString *varname) { | |||
| 151 | luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, | 151 | luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, |
| 152 | LocVar, USHRT_MAX, "too many local variables"); | 152 | LocVar, USHRT_MAX, "too many local variables"); |
| 153 | while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; | 153 | while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; |
| 154 | f->locvars[fs->nlocvars].varname = varname; /* write barrier */ | 154 | f->locvars[fs->nlocvars].varname = varname; |
| 155 | luaC_objbarrier(ls->L, f, varname); | ||
| 155 | return fs->nlocvars++; | 156 | return fs->nlocvars++; |
| 156 | } | 157 | } |
| 157 | 158 | ||
| @@ -199,7 +200,8 @@ static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { | |||
| 199 | luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, | 200 | luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, |
| 200 | TString *, MAX_INT, ""); | 201 | TString *, MAX_INT, ""); |
| 201 | while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; | 202 | while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; |
| 202 | f->upvalues[f->nups] = name; /* write barrier */ | 203 | f->upvalues[f->nups] = name; |
| 204 | luaC_objbarrier(fs->L, f, name); | ||
| 203 | lua_assert(v->k == VLOCAL || v->k == VUPVAL); | 205 | lua_assert(v->k == VLOCAL || v->k == VUPVAL); |
| 204 | fs->upvalues[f->nups].k = cast(lu_byte, v->k); | 206 | fs->upvalues[f->nups].k = cast(lu_byte, v->k); |
| 205 | fs->upvalues[f->nups].info = cast(lu_byte, v->info); | 207 | fs->upvalues[f->nups].info = cast(lu_byte, v->info); |
| @@ -307,7 +309,8 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { | |||
| 307 | luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, | 309 | luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, |
| 308 | MAXARG_Bx, "constant table overflow"); | 310 | MAXARG_Bx, "constant table overflow"); |
| 309 | while (oldsize < f->sizep) f->p[oldsize++] = NULL; | 311 | while (oldsize < f->sizep) f->p[oldsize++] = NULL; |
| 310 | f->p[fs->np++] = func->f; /* write barrier */ | 312 | f->p[fs->np++] = func->f; |
| 313 | luaC_objbarrier(ls->L, f, func->f); | ||
| 311 | init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); | 314 | init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); |
| 312 | for (i=0; i<func->f->nups; i++) { | 315 | for (i=0; i<func->f->nups; i++) { |
| 313 | OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; | 316 | OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstring.c,v 1.83 2003/12/03 20:03:07 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 1.84 2003/12/04 17:22:42 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 | */ |
| @@ -84,8 +84,11 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { | |||
| 84 | o != NULL; | 84 | o != NULL; |
| 85 | o = o->gch.next) { | 85 | o = o->gch.next) { |
| 86 | TString *ts = gcotots(o); | 86 | TString *ts = gcotots(o); |
| 87 | if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) | 87 | if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { |
| 88 | /* string may be dead */ | ||
| 89 | if (isdead(G(L), o)) changewhite(o); | ||
| 88 | return ts; | 90 | return ts; |
| 91 | } | ||
| 89 | } | 92 | } |
| 90 | return newlstr(L, str, l, h); /* not found */ | 93 | return newlstr(L, str, l, h); /* not found */ |
| 91 | } | 94 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltable.c,v 1.136 2003/11/27 18:05:14 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 1.137 2003/12/01 18:22:56 roberto Exp roberto $ |
| 3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -398,7 +398,8 @@ static TObject *newkey (lua_State *L, Table *t, const TObject *key) { | |||
| 398 | mp = n; | 398 | mp = n; |
| 399 | } | 399 | } |
| 400 | } | 400 | } |
| 401 | setobj2t(gkey(mp), key); /* write barrier */ | 401 | setobj2t(gkey(mp), key); |
| 402 | luaC_barrier(L, t, key); | ||
| 402 | lua_assert(ttisnil(gval(mp))); | 403 | lua_assert(ttisnil(gval(mp))); |
| 403 | for (;;) { /* correct `firstfree' */ | 404 | for (;;) { /* correct `firstfree' */ |
| 404 | if (ttisnil(gkey(t->firstfree))) | 405 | if (ttisnil(gkey(t->firstfree))) |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 1.289 2003/07/16 20:49:02 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.290 2003/10/27 19:14:31 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -151,7 +151,8 @@ void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) { | |||
| 151 | TObject *oldval = luaH_set(L, h, key); /* do a primitive set */ | 151 | TObject *oldval = luaH_set(L, h, key); /* do a primitive set */ |
| 152 | if (!ttisnil(oldval) || /* result is no nil? */ | 152 | if (!ttisnil(oldval) || /* result is no nil? */ |
| 153 | (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ | 153 | (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ |
| 154 | setobj2t(oldval, val); /* write barrier */ | 154 | setobj2t(oldval, val); |
| 155 | luaC_barrier(L, h, val); | ||
| 155 | return; | 156 | return; |
| 156 | } | 157 | } |
| 157 | /* else will try the tag method */ | 158 | /* else will try the tag method */ |
| @@ -454,8 +455,9 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { | |||
| 454 | break; | 455 | break; |
| 455 | } | 456 | } |
| 456 | case OP_SETUPVAL: { | 457 | case OP_SETUPVAL: { |
| 457 | int b = GETARG_B(i); | 458 | UpVal *uv = cl->upvals[GETARG_B(i)]; |
| 458 | setobj(cl->upvals[b]->v, ra); /* write barrier */ | 459 | setobj(uv->v, ra); |
| 460 | luaC_barrier(L, uv, ra); | ||
| 459 | break; | 461 | break; |
| 460 | } | 462 | } |
| 461 | case OP_SETTABLE: { | 463 | case OP_SETTABLE: { |
| @@ -713,8 +715,11 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { | |||
| 713 | L->top = L->ci->top; | 715 | L->top = L->ci->top; |
| 714 | } | 716 | } |
| 715 | bc &= ~(LFIELDS_PER_FLUSH-1); /* bc = bc - bc%FPF */ | 717 | bc &= ~(LFIELDS_PER_FLUSH-1); /* bc = bc - bc%FPF */ |
| 716 | for (; n > 0; n--) | 718 | for (; n > 0; n--) { |
| 717 | setobj2t(luaH_setnum(L, h, bc+n), ra+n); /* write barrier */ | 719 | TObject *val = ra+n; |
| 720 | setobj2t(luaH_setnum(L, h, bc+n), val); | ||
| 721 | luaC_barrier(L, h, val); | ||
| 722 | } | ||
| 718 | break; | 723 | break; |
| 719 | } | 724 | } |
| 720 | case OP_CLOSE: { | 725 | case OP_CLOSE: { |
