00001
00002
00003
00004
00005
00006
00007 #include <string.h>
00008
00009 #define lgc_c
00010 #define LUA_CORE
00011
00012 #include "lua.h"
00013
00014 #include "ldebug.h"
00015 #include "ldo.h"
00016 #include "lfunc.h"
00017 #include "lgc.h"
00018 #include "lmem.h"
00019 #include "lobject.h"
00020 #include "lstate.h"
00021 #include "lstring.h"
00022 #include "ltable.h"
00023 #include "ltm.h"
00024
00025
00026
00027
00028 #define GCSTEPSIZE 1024
00029
00030
00031 #define GCSWEEPMAX 40
00032
00033
00034 #define GCSWEEPCOST 1
00035
00036
00037 #define GCFINALIZENUM 4
00038
00039
00040 #define GCROOTCOST 10
00041
00042
00043 #define GCATOMICCOST 1000
00044
00045
00046
00047 #define TRAVCOST 5
00048
00049
00050
00051
00052
00053
00054 #define stddebt(g) (-cast(l_mem, gettotalbytes(g)/100) * g->gcpause)
00055
00056
00057
00058
00059
00060
00061 #define maskcolors (~(bit2mask(BLACKBIT, OLDBIT) | WHITEBITS))
00062 #define makewhite(g,x) \
00063 (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g)))
00064
00065 #define white2gray(x) resetbits(gch(x)->marked, WHITEBITS)
00066 #define black2gray(x) resetbit(gch(x)->marked, BLACKBIT)
00067
00068 #define stringmark(s) ((void)((s) && resetbits((s)->tsv.marked, WHITEBITS)))
00069
00070
00071 #define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT)
00072
00073 #define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n)))
00074
00075
00076 #define checkconsistency(obj) \
00077 lua_longassert(!iscollectable(obj) || righttt(obj))
00078
00079
00080 #define markvalue(g,o) { checkconsistency(o); \
00081 if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
00082
00083 #define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \
00084 reallymarkobject(g, obj2gco(t)); }
00085
00086 static void reallymarkobject (global_State *g, GCObject *o);
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 #define gnodelast(h) gnode(h, cast(size_t, sizenode(h)))
00100
00101
00102
00103
00104
00105 #define linktable(h,p) ((h)->gclist = *(p), *(p) = obj2gco(h))
00106
00107
00108
00109
00110
00111
00112 static void removeentry (Node *n) {
00113 lua_assert(ttisnil(gval(n)));
00114 if (valiswhite(gkey(n)))
00115 setdeadvalue(gkey(n));
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 static int iscleared (const TValue *o) {
00127 if (!iscollectable(o)) return 0;
00128 else if (ttisstring(o)) {
00129 stringmark(rawtsvalue(o));
00130 return 0;
00131 }
00132 else return iswhite(gcvalue(o));
00133 }
00134
00135
00136
00137
00138
00139
00140 void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
00141 global_State *g = G(L);
00142 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
00143 lua_assert(isgenerational(g) || g->gcstate != GCSpause);
00144 lua_assert(gch(o)->tt != LUA_TTABLE);
00145 if (keepinvariant(g))
00146 reallymarkobject(g, v);
00147 else {
00148 lua_assert(issweepphase(g));
00149 makewhite(g, o);
00150 }
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160 void luaC_barrierback_ (lua_State *L, GCObject *o) {
00161 global_State *g = G(L);
00162 lua_assert(isblack(o) && !isdead(g, o) && gch(o)->tt == LUA_TTABLE);
00163 black2gray(o);
00164 gco2t(o)->gclist = g->grayagain;
00165 g->grayagain = o;
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c) {
00178 global_State *g = G(L);
00179 lua_assert(isblack(obj2gco(p)));
00180 if (p->cache == NULL) {
00181 luaC_objbarrier(L, p, c);
00182 }
00183 else {
00184 black2gray(obj2gco(p));
00185 p->gclist = g->grayagain;
00186 g->grayagain = obj2gco(p);
00187 }
00188 }
00189
00190
00191
00192
00193
00194
00195 void luaC_checkupvalcolor (global_State *g, UpVal *uv) {
00196 GCObject *o = obj2gco(uv);
00197 lua_assert(!isblack(o));
00198 if (isgray(o)) {
00199 if (keepinvariant(g)) {
00200 resetoldbit(o);
00201 gray2black(o);
00202 markvalue(g, uv->v);
00203 }
00204 else {
00205 lua_assert(issweepphase(g));
00206 makewhite(g, o);
00207 }
00208 }
00209 }
00210
00211
00212
00213
00214
00215
00216
00217 GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list,
00218 int offset) {
00219 global_State *g = G(L);
00220 GCObject *o = obj2gco(cast(char *, luaM_newobject(L, tt, sz)) + offset);
00221 if (list == NULL)
00222 list = &g->allgc;
00223 gch(o)->marked = luaC_white(g);
00224 gch(o)->tt = tt;
00225 gch(o)->next = *list;
00226 *list = o;
00227 return o;
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 static void reallymarkobject (global_State *g, GCObject *o) {
00249 lua_assert(iswhite(o) && !isdead(g, o));
00250 white2gray(o);
00251 switch (gch(o)->tt) {
00252 case LUA_TSTRING: {
00253 return;
00254 }
00255 case LUA_TUSERDATA: {
00256 Table *mt = gco2u(o)->metatable;
00257 markobject(g, mt);
00258 markobject(g, gco2u(o)->env);
00259 gray2black(o);
00260 return;
00261 }
00262 case LUA_TUPVAL: {
00263 UpVal *uv = gco2uv(o);
00264 markvalue(g, uv->v);
00265 if (uv->v == &uv->u.value)
00266 gray2black(o);
00267 return;
00268 }
00269 case LUA_TFUNCTION: {
00270 gco2cl(o)->c.gclist = g->gray;
00271 g->gray = o;
00272 break;
00273 }
00274 case LUA_TTABLE: {
00275 linktable(gco2t(o), &g->gray);
00276 break;
00277 }
00278 case LUA_TTHREAD: {
00279 gco2th(o)->gclist = g->gray;
00280 g->gray = o;
00281 break;
00282 }
00283 case LUA_TPROTO: {
00284 gco2p(o)->gclist = g->gray;
00285 g->gray = o;
00286 break;
00287 }
00288 default: lua_assert(0);
00289 }
00290 }
00291
00292
00293
00294
00295
00296 static void markmt (global_State *g) {
00297 int i;
00298 for (i=0; i < LUA_NUMTAGS; i++)
00299 markobject(g, g->mt[i]);
00300 }
00301
00302
00303
00304
00305
00306 static void markbeingfnz (global_State *g) {
00307 GCObject *o;
00308 for (o = g->tobefnz; o != NULL; o = gch(o)->next) {
00309 makewhite(g, o);
00310 reallymarkobject(g, o);
00311 }
00312 }
00313
00314
00315
00316
00317
00318
00319 static void remarkupvals (global_State *g) {
00320 UpVal *uv;
00321 for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
00322 if (isgray(obj2gco(uv)))
00323 markvalue(g, uv->v);
00324 }
00325 }
00326
00327
00328
00329
00330
00331
00332 static void markroot (global_State *g) {
00333 g->gray = g->grayagain = NULL;
00334 g->weak = g->allweak = g->ephemeron = NULL;
00335 markobject(g, g->mainthread);
00336 markvalue(g, &g->l_registry);
00337 markmt(g);
00338 markbeingfnz(g);
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 static void traverseweakvalue (global_State *g, Table *h) {
00351 Node *n, *limit = gnodelast(h);
00352
00353
00354 int hasclears = (h->sizearray > 0);
00355 for (n = gnode(h, 0); n < limit; n++) {
00356 checkdeadkey(n);
00357 if (ttisnil(gval(n)))
00358 removeentry(n);
00359 else {
00360 lua_assert(!ttisnil(gkey(n)));
00361 markvalue(g, gkey(n));
00362 if (!hasclears && iscleared(gval(n)))
00363 hasclears = 1;
00364 }
00365 }
00366 if (hasclears)
00367 linktable(h, &g->weak);
00368 else
00369 linktable(h, &g->grayagain);
00370 }
00371
00372
00373 static int traverseephemeron (global_State *g, Table *h) {
00374 int marked = 0;
00375 int hasclears = 0;
00376 int prop = 0;
00377 Node *n, *limit = gnodelast(h);
00378 int i;
00379
00380 for (i = 0; i < h->sizearray; i++) {
00381 if (valiswhite(&h->array[i])) {
00382 marked = 1;
00383 reallymarkobject(g, gcvalue(&h->array[i]));
00384 }
00385 }
00386
00387 for (n = gnode(h, 0); n < limit; n++) {
00388 checkdeadkey(n);
00389 if (ttisnil(gval(n)))
00390 removeentry(n);
00391 else if (iscleared(gkey(n))) {
00392 hasclears = 1;
00393 if (valiswhite(gval(n)))
00394 prop = 1;
00395 }
00396 else if (valiswhite(gval(n))) {
00397 marked = 1;
00398 reallymarkobject(g, gcvalue(gval(n)));
00399 }
00400 }
00401 if (prop)
00402 linktable(h, &g->ephemeron);
00403 else if (hasclears)
00404 linktable(h, &g->allweak);
00405 else
00406 linktable(h, &g->grayagain);
00407 return marked;
00408 }
00409
00410
00411 static void traversestrongtable (global_State *g, Table *h) {
00412 Node *n, *limit = gnodelast(h);
00413 int i;
00414 for (i = 0; i < h->sizearray; i++)
00415 markvalue(g, &h->array[i]);
00416 for (n = gnode(h, 0); n < limit; n++) {
00417 checkdeadkey(n);
00418 if (ttisnil(gval(n)))
00419 removeentry(n);
00420 else {
00421 lua_assert(!ttisnil(gkey(n)));
00422 markvalue(g, gkey(n));
00423 markvalue(g, gval(n));
00424 }
00425 }
00426 }
00427
00428
00429 static int traversetable (global_State *g, Table *h) {
00430 const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
00431 markobject(g, h->metatable);
00432 if (mode && ttisstring(mode)) {
00433 int weakkey = (strchr(svalue(mode), 'k') != NULL);
00434 int weakvalue = (strchr(svalue(mode), 'v') != NULL);
00435 if (weakkey || weakvalue) {
00436 black2gray(obj2gco(h));
00437 if (!weakkey) {
00438 traverseweakvalue(g, h);
00439 return TRAVCOST + sizenode(h);
00440 }
00441 else if (!weakvalue) {
00442 traverseephemeron(g, h);
00443 return TRAVCOST + h->sizearray + sizenode(h);
00444 }
00445 else {
00446 linktable(h, &g->allweak);
00447 return TRAVCOST;
00448 }
00449 }
00450 }
00451 traversestrongtable(g, h);
00452 return TRAVCOST + h->sizearray + (2 * sizenode(h));
00453 }
00454
00455
00456 static int traverseproto (global_State *g, Proto *f) {
00457 int i;
00458 if (f->cache && iswhite(obj2gco(f->cache)))
00459 f->cache = NULL;
00460 stringmark(f->source);
00461 for (i = 0; i < f->sizek; i++)
00462 markvalue(g, &f->k[i]);
00463 for (i = 0; i < f->sizeupvalues; i++)
00464 stringmark(f->upvalues[i].name);
00465 for (i = 0; i < f->sizep; i++)
00466 markobject(g, f->p[i]);
00467 for (i = 0; i < f->sizelocvars; i++)
00468 stringmark(f->locvars[i].varname);
00469 return TRAVCOST + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars;
00470 }
00471
00472
00473 static int traverseclosure (global_State *g, Closure *cl) {
00474 if (cl->c.isC) {
00475 int i;
00476 for (i=0; i<cl->c.nupvalues; i++)
00477 markvalue(g, &cl->c.upvalue[i]);
00478 }
00479 else {
00480 int i;
00481 lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues);
00482 markobject(g, cl->l.p);
00483 for (i=0; i<cl->l.nupvalues; i++)
00484 markobject(g, cl->l.upvals[i]);
00485 }
00486 return TRAVCOST + cl->c.nupvalues;
00487 }
00488
00489
00490 static int traversestack (global_State *g, lua_State *L) {
00491 StkId o = L->stack;
00492 if (o == NULL)
00493 return 1;
00494 for (; o < L->top; o++)
00495 markvalue(g, o);
00496 if (g->gcstate == GCSatomic) {
00497 StkId lim = L->stack + L->stacksize;
00498 for (; o < lim; o++)
00499 setnilvalue(o);
00500 }
00501 return TRAVCOST + cast_int(o - L->stack);
00502 }
00503
00504
00505
00506
00507
00508
00509
00510 static int propagatemark (global_State *g) {
00511 GCObject *o = g->gray;
00512 lua_assert(isgray(o));
00513 gray2black(o);
00514 switch (gch(o)->tt) {
00515 case LUA_TTABLE: {
00516 Table *h = gco2t(o);
00517 g->gray = h->gclist;
00518 return traversetable(g, h);
00519 }
00520 case LUA_TFUNCTION: {
00521 Closure *cl = gco2cl(o);
00522 g->gray = cl->c.gclist;
00523 return traverseclosure(g, cl);
00524 }
00525 case LUA_TTHREAD: {
00526 lua_State *th = gco2th(o);
00527 g->gray = th->gclist;
00528 th->gclist = g->grayagain;
00529 g->grayagain = o;
00530 black2gray(o);
00531 return traversestack(g, th);
00532 }
00533 case LUA_TPROTO: {
00534 Proto *p = gco2p(o);
00535 g->gray = p->gclist;
00536 return traverseproto(g, p);
00537 }
00538 default: lua_assert(0); return 0;
00539 }
00540 }
00541
00542
00543 static void propagateall (global_State *g) {
00544 while (g->gray) propagatemark(g);
00545 }
00546
00547
00548 static void propagatelist (global_State *g, GCObject *l) {
00549 lua_assert(g->gray == NULL);
00550 g->gray = l;
00551 propagateall(g);
00552 }
00553
00554
00555
00556
00557
00558
00559 static void retraversegrays (global_State *g) {
00560 GCObject *weak = g->weak;
00561 GCObject *grayagain = g->grayagain;
00562 GCObject *ephemeron = g->ephemeron;
00563 g->weak = g->grayagain = g->ephemeron = NULL;
00564 propagateall(g);
00565 propagatelist(g, grayagain);
00566 propagatelist(g, weak);
00567 propagatelist(g, ephemeron);
00568 }
00569
00570
00571 static void convergeephemerons (global_State *g) {
00572 int changed;
00573 do {
00574 GCObject *w;
00575 GCObject *next = g->ephemeron;
00576 g->ephemeron = NULL;
00577 changed = 0;
00578 while ((w = next) != NULL) {
00579 next = gco2t(w)->gclist;
00580 if (traverseephemeron(g, gco2t(w))) {
00581 propagateall(g);
00582 changed = 1;
00583 }
00584 }
00585 } while (changed);
00586 }
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602 static void clearkeys (GCObject *l, GCObject *f) {
00603 for (; l != f; l = gco2t(l)->gclist) {
00604 Table *h = gco2t(l);
00605 Node *n, *limit = gnodelast(h);
00606 for (n = gnode(h, 0); n < limit; n++) {
00607 if (!ttisnil(gval(n)) && (iscleared(gkey(n)))) {
00608 setnilvalue(gval(n));
00609 removeentry(n);
00610 }
00611 }
00612 }
00613 }
00614
00615
00616
00617
00618
00619
00620 static void clearvalues (GCObject *l, GCObject *f) {
00621 for (; l != f; l = gco2t(l)->gclist) {
00622 Table *h = gco2t(l);
00623 Node *n, *limit = gnodelast(h);
00624 int i;
00625 for (i = 0; i < h->sizearray; i++) {
00626 TValue *o = &h->array[i];
00627 if (iscleared(o))
00628 setnilvalue(o);
00629 }
00630 for (n = gnode(h, 0); n < limit; n++) {
00631 if (!ttisnil(gval(n)) && iscleared(gval(n))) {
00632 setnilvalue(gval(n));
00633 removeentry(n);
00634 }
00635 }
00636 }
00637 }
00638
00639
00640 static void freeobj (lua_State *L, GCObject *o) {
00641 switch (gch(o)->tt) {
00642 case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
00643 case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;
00644 case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
00645 case LUA_TTABLE: luaH_free(L, gco2t(o)); break;
00646 case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break;
00647 case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
00648 case LUA_TSTRING: {
00649 G(L)->strt.nuse--;
00650 luaM_freemem(L, o, sizestring(gco2ts(o)));
00651 break;
00652 }
00653 default: lua_assert(0);
00654 }
00655 }
00656
00657
00658 #define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM)
00659 static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count);
00660
00661
00662
00663
00664
00665
00666 static void sweepthread (lua_State *L, lua_State *L1) {
00667 if (L1->stack == NULL) return;
00668 sweepwholelist(L, &L1->openupval);
00669 luaE_freeCI(L1);
00670
00671 if (G(L)->gckind != KGC_EMERGENCY)
00672 luaD_shrinkstack(L1);
00673 }
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
00688 global_State *g = G(L);
00689 int ow = otherwhite(g);
00690 int toclear, toset;
00691 int tostop;
00692 l_mem debt = g->GCdebt;
00693 if (isgenerational(g)) {
00694 toclear = ~0;
00695 toset = bitmask(OLDBIT);
00696 tostop = bitmask(OLDBIT);
00697 }
00698 else {
00699 toclear = maskcolors;
00700 toset = luaC_white(g);
00701 tostop = 0;
00702 }
00703 while (*p != NULL && count-- > 0) {
00704 GCObject *curr = *p;
00705 int marked = gch(curr)->marked;
00706 if (isdeadm(ow, marked)) {
00707 *p = gch(curr)->next;
00708 freeobj(L, curr);
00709 }
00710 else {
00711 if (gch(curr)->tt == LUA_TTHREAD)
00712 sweepthread(L, gco2th(curr));
00713 if (testbits(marked, tostop)) {
00714 static GCObject *nullp = NULL;
00715 p = &nullp;
00716 break;
00717 }
00718
00719 gch(curr)->marked = cast_byte((marked & toclear) | toset);
00720 p = &gch(curr)->next;
00721 }
00722 }
00723 luaE_setdebt(g, debt);
00724 return p;
00725 }
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 static void checkSizes (lua_State *L) {
00737 global_State *g = G(L);
00738 if (g->gckind != KGC_EMERGENCY) {
00739 int hs = g->strt.size / 2;
00740 if (g->strt.nuse < cast(lu_int32, hs))
00741 luaS_resize(L, hs);
00742 luaZ_freebuffer(L, &g->buff);
00743 }
00744 }
00745
00746
00747 static GCObject *udata2finalize (global_State *g) {
00748 GCObject *o = g->tobefnz;
00749 lua_assert(isfinalized(o));
00750 g->tobefnz = gch(o)->next;
00751 gch(o)->next = g->allgc;
00752 g->allgc = o;
00753 resetbit(gch(o)->marked, SEPARATED);
00754 lua_assert(!isold(o));
00755 if (!keepinvariant(g))
00756 makewhite(g, o);
00757 return o;
00758 }
00759
00760
00761 static void dothecall (lua_State *L, void *ud) {
00762 UNUSED(ud);
00763 luaD_call(L, L->top - 2, 0, 0);
00764 }
00765
00766
00767 static void GCTM (lua_State *L, int propagateerrors) {
00768 global_State *g = G(L);
00769 const TValue *tm;
00770 TValue v;
00771 setgcovalue(L, &v, udata2finalize(g));
00772 tm = luaT_gettmbyobj(L, &v, TM_GC);
00773 if (tm != NULL && ttisfunction(tm)) {
00774 int status;
00775 lu_byte oldah = L->allowhook;
00776 int running = g->gcrunning;
00777 L->allowhook = 0;
00778 g->gcrunning = 0;
00779 setobj2s(L, L->top, tm);
00780 setobj2s(L, L->top + 1, &v);
00781 L->top += 2;
00782 status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0);
00783 L->allowhook = oldah;
00784 g->gcrunning = running;
00785 if (status != LUA_OK && propagateerrors) {
00786 if (status == LUA_ERRRUN) {
00787 luaO_pushfstring(L, "error in __gc metamethod (%s)",
00788 lua_tostring(L, -1));
00789 status = LUA_ERRGCMM;
00790 }
00791 luaD_throw(L, status);
00792 }
00793 }
00794 }
00795
00796
00797
00798
00799
00800
00801 static void separatetobefnz (lua_State *L, int all) {
00802 global_State *g = G(L);
00803 GCObject **p = &g->finobj;
00804 GCObject *curr;
00805 GCObject **lastnext = &g->tobefnz;
00806
00807 while (*lastnext != NULL)
00808 lastnext = &gch(*lastnext)->next;
00809 while ((curr = *p) != NULL) {
00810 lua_assert(!isfinalized(curr));
00811 lua_assert(testbit(gch(curr)->marked, SEPARATED));
00812 if (!(all || iswhite(curr)))
00813 p = &gch(curr)->next;
00814 else {
00815 l_setbit(gch(curr)->marked, FINALIZEDBIT);
00816 *p = gch(curr)->next;
00817 gch(curr)->next = *lastnext;
00818 *lastnext = curr;
00819 lastnext = &gch(curr)->next;
00820 }
00821 }
00822 }
00823
00824
00825
00826
00827
00828
00829 void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
00830 global_State *g = G(L);
00831 if (testbit(gch(o)->marked, SEPARATED) ||
00832 isfinalized(o) ||
00833 gfasttm(g, mt, TM_GC) == NULL)
00834 return;
00835 else {
00836 GCObject **p;
00837 for (p = &g->allgc; *p != o; p = &gch(*p)->next) ;
00838 *p = gch(o)->next;
00839 gch(o)->next = g->finobj;
00840 g->finobj = o;
00841 l_setbit(gch(o)->marked, SEPARATED);
00842 resetoldbit(o);
00843 }
00844 }
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856 #define sweepphases \
00857 (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep))
00858
00859
00860
00861
00862 void luaC_changemode (lua_State *L, int mode) {
00863 global_State *g = G(L);
00864 if (mode == g->gckind) return;
00865 if (mode == KGC_GEN) {
00866
00867 luaC_runtilstate(L, bitmask(GCSpropagate));
00868 g->lastmajormem = gettotalbytes(g);
00869 g->gckind = KGC_GEN;
00870 }
00871 else {
00872
00873
00874 g->sweepstrgc = 0;
00875 g->gcstate = GCSsweepstring;
00876 g->gckind = KGC_NORMAL;
00877 luaC_runtilstate(L, ~sweepphases);
00878 }
00879 }
00880
00881
00882
00883
00884
00885 static void callallpendingfinalizers (lua_State *L, int propagateerrors) {
00886 global_State *g = G(L);
00887 while (g->tobefnz) {
00888 resetoldbit(g->tobefnz);
00889 GCTM(L, propagateerrors);
00890 }
00891 }
00892
00893
00894 void luaC_freeallobjects (lua_State *L) {
00895 global_State *g = G(L);
00896 int i;
00897 separatetobefnz(L, 1);
00898 lua_assert(g->finobj == NULL);
00899 callallpendingfinalizers(L, 0);
00900 g->currentwhite = WHITEBITS;
00901 g->gckind = KGC_NORMAL;
00902 sweepwholelist(L, &g->finobj);
00903 sweepwholelist(L, &g->allgc);
00904 for (i = 0; i < g->strt.size; i++)
00905 sweepwholelist(L, &g->strt.hash[i]);
00906 lua_assert(g->strt.nuse == 0);
00907 }
00908
00909
00910 static void atomic (lua_State *L) {
00911 global_State *g = G(L);
00912 GCObject *origweak, *origall;
00913 lua_assert(!iswhite(obj2gco(g->mainthread)));
00914 markobject(g, L);
00915
00916 markvalue(g, &g->l_registry);
00917 markmt(g);
00918
00919 remarkupvals(g);
00920
00921 retraversegrays(g);
00922 convergeephemerons(g);
00923
00924
00925 clearvalues(g->weak, NULL);
00926 clearvalues(g->allweak, NULL);
00927 origweak = g->weak; origall = g->allweak;
00928 separatetobefnz(L, 0);
00929 markbeingfnz(g);
00930 propagateall(g);
00931 convergeephemerons(g);
00932
00933
00934 clearkeys(g->ephemeron, NULL);
00935 clearkeys(g->allweak, NULL);
00936
00937 clearvalues(g->weak, origweak);
00938 clearvalues(g->allweak, origall);
00939 g->sweepstrgc = 0;
00940 g->gcstate = GCSsweepstring;
00941 g->currentwhite = cast_byte(otherwhite(g));
00942
00943 }
00944
00945
00946 static l_mem singlestep (lua_State *L) {
00947 global_State *g = G(L);
00948 switch (g->gcstate) {
00949 case GCSpause: {
00950 if (!isgenerational(g))
00951 markroot(g);
00952
00953 lua_assert(!iswhite(obj2gco(g->mainthread))
00954 && !iswhite(gcvalue(&g->l_registry)));
00955 g->gcstate = GCSpropagate;
00956 return GCROOTCOST;
00957 }
00958 case GCSpropagate: {
00959 if (g->gray)
00960 return propagatemark(g);
00961 else {
00962 g->gcstate = GCSatomic;
00963 atomic(L);
00964 return GCATOMICCOST;
00965 }
00966 }
00967 case GCSsweepstring: {
00968 if (g->sweepstrgc < g->strt.size) {
00969 sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
00970 return GCSWEEPCOST;
00971 }
00972 else {
00973 g->sweepgc = &g->finobj;
00974 g->gcstate = GCSsweepudata;
00975 return 0;
00976 }
00977 }
00978 case GCSsweepudata: {
00979 if (*g->sweepgc) {
00980 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
00981 return GCSWEEPMAX*GCSWEEPCOST;
00982 }
00983 else {
00984 g->sweepgc = &g->allgc;
00985 g->gcstate = GCSsweep;
00986 return GCSWEEPCOST;
00987 }
00988 }
00989 case GCSsweep: {
00990 if (*g->sweepgc) {
00991 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
00992 return GCSWEEPMAX*GCSWEEPCOST;
00993 }
00994 else {
00995
00996 GCObject *mt = obj2gco(g->mainthread);
00997 sweeplist(L, &mt, 1);
00998 checkSizes(L);
00999 g->gcstate = GCSpause;
01000 return GCSWEEPCOST;
01001 }
01002 }
01003 default: lua_assert(0); return 0;
01004 }
01005 }
01006
01007
01008
01009
01010
01011
01012 void luaC_runtilstate (lua_State *L, int statesmask) {
01013 global_State *g = G(L);
01014 while (!testbit(statesmask, g->gcstate))
01015 singlestep(L);
01016 }
01017
01018
01019 static void generationalcollection (lua_State *L) {
01020 global_State *g = G(L);
01021 if (g->lastmajormem == 0) {
01022 luaC_fullgc(L, 0);
01023 g->lastmajormem = gettotalbytes(g);
01024 }
01025 else {
01026 luaC_runtilstate(L, ~bitmask(GCSpause));
01027 luaC_runtilstate(L, bitmask(GCSpause));
01028 if (gettotalbytes(g) > g->lastmajormem/100 * g->gcmajorinc)
01029 g->lastmajormem = 0;
01030 }
01031 luaE_setdebt(g, stddebt(g));
01032 }
01033
01034
01035 static void step (lua_State *L) {
01036 global_State *g = G(L);
01037 l_mem lim = g->gcstepmul;
01038 do {
01039 lim -= singlestep(L);
01040 } while (lim > 0 && g->gcstate != GCSpause);
01041 if (g->gcstate != GCSpause)
01042 luaE_setdebt(g, g->GCdebt - GCSTEPSIZE);
01043 else
01044 luaE_setdebt(g, stddebt(g));
01045 }
01046
01047
01048
01049
01050
01051 void luaC_forcestep (lua_State *L) {
01052 global_State *g = G(L);
01053 int i;
01054 if (isgenerational(g)) generationalcollection(L);
01055 else step(L);
01056 for (i = 0; i < GCFINALIZENUM && g->tobefnz; i++)
01057 GCTM(L, 1);
01058 }
01059
01060
01061
01062
01063
01064 void luaC_step (lua_State *L) {
01065 if (G(L)->gcrunning) luaC_forcestep(L);
01066 }
01067
01068
01069
01070
01071
01072
01073 void luaC_fullgc (lua_State *L, int isemergency) {
01074 global_State *g = G(L);
01075 int origkind = g->gckind;
01076 lua_assert(origkind != KGC_EMERGENCY);
01077 if (!isemergency)
01078 callallpendingfinalizers(L, 1);
01079 if (keepinvariant(g)) {
01080
01081
01082 g->sweepstrgc = 0;
01083 g->gcstate = GCSsweepstring;
01084 }
01085 g->gckind = isemergency ? KGC_EMERGENCY : KGC_NORMAL;
01086
01087 luaC_runtilstate(L, bitmask(GCSpause));
01088
01089 luaC_runtilstate(L, ~bitmask(GCSpause));
01090 luaC_runtilstate(L, bitmask(GCSpause));
01091 if (origkind == KGC_GEN) {
01092
01093 luaC_runtilstate(L, bitmask(GCSpropagate));
01094 }
01095 g->gckind = origkind;
01096 luaE_setdebt(g, stddebt(g));
01097 if (!isemergency)
01098 callallpendingfinalizers(L, 1);
01099 }
01100
01101
01102
01103