Lua 5.1.4: lgc.c
L0001
L0006
L0007 #include <string.h>
L0008
L0009 #define lgc_c
L0010 #define LUA_CORE
L0011
L0012 #include "lua.h"
L0013
L0014 #include "ldebug.h"
L0015 #include "ldo.h"
L0016 #include "lfunc.h"
L0017 #include "lgc.h"
L0018 #include "lmem.h"
L0019 #include "lobject.h"
L0020 #include "lstate.h"
L0021 #include "lstring.h"
L0022 #include "ltable.h"
L0023 #include "ltm.h"
L0024
L0025
L0026 #define GCSTEPSIZE 1024u
L0027 #define GCSWEEPMAX 40
L0028 #define GCSWEEPCOST 10
L0029 #define GCFINALIZECOST 100
L0030
L0031
L0032 #define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS))
L0033
L0034 #define makewhite(g,x) \
L0035 ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g)))
L0036
L0037 #define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
L0038 #define black2gray(x) resetbit((x)->gch.marked, BLACKBIT)
L0039
L0040 #define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)
L0041
L0042
L0043 #define isfinalized(u) testbit((u)->marked, FINALIZEDBIT)
L0044 #define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT)
L0045
L0046
L0047 #define KEYWEAK bitmask(KEYWEAKBIT)
L0048 #define VALUEWEAK bitmask(VALUEWEAKBIT)
L0049
L0050
L0051
L0052 #define markvalue(g,o) { checkconsistency(o); \
L0053 if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
L0054
L0055 #define markobject(g,t) { if (iswhite(obj2gco(t))) \
L0056 reallymarkobject(g, obj2gco(t)); }
L0057
L0058
L0059 #define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause)
L0060
L0061
L0062 static void removeentry (Node *n) {
L0063 lua_assert(ttisnil(gval(n)));
L0064 if (iscollectable(gkey(n)))
L0065 setttype(gkey(n), LUA_TDEADKEY);
L0066 }
L0067
L0068
L0069 static void reallymarkobject (global_State *g, GCObject *o) {
L0070 lua_assert(iswhite(o) && !isdead(g, o));
L0071 white2gray(o);
L0072 switch (o->gch.tt) {
L0073 case LUA_TSTRING: {
L0074 return;
L0075 }
L0076 case LUA_TUSERDATA: {
L0077 Table *mt = gco2u(o)->metatable;
L0078 gray2black(o);
L0079 if (mt) markobject(g, mt);
L0080 markobject(g, gco2u(o)->env);
L0081 return;
L0082 }
L0083 case LUA_TUPVAL: {
L0084 UpVal *uv = gco2uv(o);
L0085 markvalue(g, uv->v);
L0086 if (uv->v == &uv->u.value)
L0087 gray2black(o);
L0088 return;
L0089 }
L0090 case LUA_TFUNCTION: {
L0091 gco2cl(o)->c.gclist = g->gray;
L0092 g->gray = o;
L0093 break;
L0094 }
L0095 case LUA_TTABLE: {
L0096 gco2h(o)->gclist = g->gray;
L0097 g->gray = o;
L0098 break;
L0099 }
L0100 case LUA_TTHREAD: {
L0101 gco2th(o)->gclist = g->gray;
L0102 g->gray = o;
L0103 break;
L0104 }
L0105 case LUA_TPROTO: {
L0106 gco2p(o)->gclist = g->gray;
L0107 g->gray = o;
L0108 break;
L0109 }
L0110 default: lua_assert(0);
L0111 }
L0112 }
L0113
L0114
L0115 static void marktmu (global_State *g) {
L0116 GCObject *u = g->tmudata;
L0117 if (u) {
L0118 do {
L0119 u = u->gch.next;
L0120 makewhite(g, u);
L0121 reallymarkobject(g, u);
L0122 } while (u != g->tmudata);
L0123 }
L0124 }
L0125
L0126
L0127
L0128 size_t luaC_separateudata (lua_State *L, int all) {
L0129 global_State *g = G(L);
L0130 size_t deadmem = 0;
L0131 GCObject **p = &g->mainthread->next;
L0132 GCObject *curr;
L0133 while ((curr = *p) != NULL) {
L0134 if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
L0135 p = &curr->gch.next;
L0136 else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
L0137 markfinalized(gco2u(curr));
L0138 p = &curr->gch.next;
L0139 }
L0140 else {
L0141 deadmem += sizeudata(gco2u(curr));
L0142 markfinalized(gco2u(curr));
L0143 *p = curr->gch.next;
L0144
L0145 if (g->tmudata == NULL)
L0146 g->tmudata = curr->gch.next = curr;
L0147 else {
L0148 curr->gch.next = g->tmudata->gch.next;
L0149 g->tmudata->gch.next = curr;
L0150 g->tmudata = curr;
L0151 }
L0152 }
L0153 }
L0154 return deadmem;
L0155 }
L0156
L0157
L0158 static int traversetable (global_State *g, Table *h) {
L0159 int i;
L0160 int weakkey = 0;
L0161 int weakvalue = 0;
L0162 const TValue *mode;
L0163 if (h->metatable)
L0164 markobject(g, h->metatable);
L0165 mode = gfasttm(g, h->metatable, TM_MODE);
L0166 if (mode && ttisstring(mode)) {
L0167 weakkey = (strchr(svalue(mode), 'k') != NULL);
L0168 weakvalue = (strchr(svalue(mode), 'v') != NULL);
L0169 if (weakkey || weakvalue) {
L0170 h->marked &= ~(KEYWEAK | VALUEWEAK);
L0171 h->marked |= cast_byte((weakkey << KEYWEAKBIT) |
L0172 (weakvalue << VALUEWEAKBIT));
L0173 h->gclist = g->weak;
L0174 g->weak = obj2gco(h);
L0175 }
L0176 }
L0177 if (weakkey && weakvalue) return 1;
L0178 if (!weakvalue) {
L0179 i = h->sizearray;
L0180 while (i--)
L0181 markvalue(g, &h->array[i]);
L0182 }
L0183 i = sizenode(h);
L0184 while (i--) {
L0185 Node *n = gnode(h, i);
L0186 lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));
L0187 if (ttisnil(gval(n)))
L0188 removeentry(n);
L0189 else {
L0190 lua_assert(!ttisnil(gkey(n)));
L0191 if (!weakkey) markvalue(g, gkey(n));
L0192 if (!weakvalue) markvalue(g, gval(n));
L0193 }
L0194 }
L0195 return weakkey || weakvalue;
L0196 }
L0197
L0198
L0199
L0203 static void traverseproto (global_State *g, Proto *f) {
L0204 int i;
L0205 if (f->source) stringmark(f->source);
L0206 for (i=0; i<f->sizek; i++)
L0207 markvalue(g, &f->k[i]);
L0208 for (i=0; i<f->sizeupvalues; i++) {
L0209 if (f->upvalues[i])
L0210 stringmark(f->upvalues[i]);
L0211 }
L0212 for (i=0; i<f->sizep; i++) {
L0213 if (f->p[i])
L0214 markobject(g, f->p[i]);
L0215 }
L0216 for (i=0; i<f->sizelocvars; i++) {
L0217 if (f->locvars[i].varname)
L0218 stringmark(f->locvars[i].varname);
L0219 }
L0220 }
L0221
L0222
L0223
L0224 static void traverseclosure (global_State *g, Closure *cl) {
L0225 markobject(g, cl->c.env);
L0226 if (cl->c.isC) {
L0227 int i;
L0228 for (i=0; i<cl->c.nupvalues; i++)
L0229 markvalue(g, &cl->c.upvalue[i]);
L0230 }
L0231 else {
L0232 int i;
L0233 lua_assert(cl->l.nupvalues == cl->l.p->nups);
L0234 markobject(g, cl->l.p);
L0235 for (i=0; i<cl->l.nupvalues; i++)
L0236 markobject(g, cl->l.upvals[i]);
L0237 }
L0238 }
L0239
L0240
L0241 static void checkstacksizes (lua_State *L, StkId max) {
L0242 int ci_used = cast_int(L->ci - L->base_ci);
L0243 int s_used = cast_int(max - L->stack);
L0244 if (L->size_ci > LUAI_MAXCALLS)
L0245 return;
L0246 if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
L0247 luaD_reallocCI(L, L->size_ci/2);
L0248 condhardstacktests(luaD_reallocCI(L, ci_used + 1));
L0249 if (4*s_used < L->stacksize &&
L0250 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
L0251 luaD_reallocstack(L, L->stacksize/2);
L0252 condhardstacktests(luaD_reallocstack(L, s_used));
L0253 }
L0254
L0255
L0256 static void traversestack (global_State *g, lua_State *l) {
L0257 StkId o, lim;
L0258 CallInfo *ci;
L0259 markvalue(g, gt(l));
L0260 lim = l->top;
L0261 for (ci = l->base_ci; ci <= l->ci; ci++) {
L0262 lua_assert(ci->top <= l->stack_last);
L0263 if (lim < ci->top) lim = ci->top;
L0264 }
L0265 for (o = l->stack; o < l->top; o++)
L0266 markvalue(g, o);
L0267 for (; o <= lim; o++)
L0268 setnilvalue(o);
L0269 checkstacksizes(l, lim);
L0270 }
L0271
L0272
L0273
L0277 static l_mem propagatemark (global_State *g) {
L0278 GCObject *o = g->gray;
L0279 lua_assert(isgray(o));
L0280 gray2black(o);
L0281 switch (o->gch.tt) {
L0282 case LUA_TTABLE: {
L0283 Table *h = gco2h(o);
L0284 g->gray = h->gclist;
L0285 if (traversetable(g, h))
L0286 black2gray(o);
L0287 return sizeof(Table) + sizeof(TValue) * h->sizearray +
L0288 sizeof(Node) * sizenode(h);
L0289 }
L0290 case LUA_TFUNCTION: {
L0291 Closure *cl = gco2cl(o);
L0292 g->gray = cl->c.gclist;
L0293 traverseclosure(g, cl);
L0294 return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
L0295 sizeLclosure(cl->l.nupvalues);
L0296 }
L0297 case LUA_TTHREAD: {
L0298 lua_State *th = gco2th(o);
L0299 g->gray = th->gclist;
L0300 th->gclist = g->grayagain;
L0301 g->grayagain = o;
L0302 black2gray(o);
L0303 traversestack(g, th);
L0304 return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
L0305 sizeof(CallInfo) * th->size_ci;
L0306 }
L0307 case LUA_TPROTO: {
L0308 Proto *p = gco2p(o);
L0309 g->gray = p->gclist;
L0310 traverseproto(g, p);
L0311 return sizeof(Proto) + sizeof(Instruction) * p->sizecode +
L0312 sizeof(Proto *) * p->sizep +
L0313 sizeof(TValue) * p->sizek +
L0314 sizeof(int) * p->sizelineinfo +
L0315 sizeof(LocVar) * p->sizelocvars +
L0316 sizeof(TString *) * p->sizeupvalues;
L0317 }
L0318 default: lua_assert(0); return 0;
L0319 }
L0320 }
L0321
L0322
L0323 static size_t propagateall (global_State *g) {
L0324 size_t m = 0;
L0325 while (g->gray) m += propagatemark(g);
L0326 return m;
L0327 }
L0328
L0329
L0330
L0337 static int iscleared (const TValue *o, int iskey) {
L0338 if (!iscollectable(o)) return 0;
L0339 if (ttisstring(o)) {
L0340 stringmark(rawtsvalue(o));
L0341 return 0;
L0342 }
L0343 return iswhite(gcvalue(o)) ||
L0344 (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));
L0345 }
L0346
L0347
L0348
L0351 static void cleartable (GCObject *l) {
L0352 while (l) {
L0353 Table *h = gco2h(l);
L0354 int i = h->sizearray;
L0355 lua_assert(testbit(h->marked, VALUEWEAKBIT) ||
L0356 testbit(h->marked, KEYWEAKBIT));
L0357 if (testbit(h->marked, VALUEWEAKBIT)) {
L0358 while (i--) {
L0359 TValue *o = &h->array[i];
L0360 if (iscleared(o, 0))
L0361 setnilvalue(o);
L0362 }
L0363 }
L0364 i = sizenode(h);
L0365 while (i--) {
L0366 Node *n = gnode(h, i);
L0367 if (!ttisnil(gval(n)) &&
L0368 (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) {
L0369 setnilvalue(gval(n));
L0370 removeentry(n);
L0371 }
L0372 }
L0373 l = h->gclist;
L0374 }
L0375 }
L0376
L0377
L0378 static void freeobj (lua_State *L, GCObject *o) {
L0379 switch (o->gch.tt) {
L0380 case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
L0381 case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;
L0382 case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;
L0383 case LUA_TTABLE: luaH_free(L, gco2h(o)); break;
L0384 case LUA_TTHREAD: {
L0385 lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread);
L0386 luaE_freethread(L, gco2th(o));
L0387 break;
L0388 }
L0389 case LUA_TSTRING: {
L0390 G(L)->strt.nuse--;
L0391 luaM_freemem(L, o, sizestring(gco2ts(o)));
L0392 break;
L0393 }
L0394 case LUA_TUSERDATA: {
L0395 luaM_freemem(L, o, sizeudata(gco2u(o)));
L0396 break;
L0397 }
L0398 default: lua_assert(0);
L0399 }
L0400 }
L0401
L0402
L0403
L0404 #define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM)
L0405
L0406
L0407 static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
L0408 GCObject *curr;
L0409 global_State *g = G(L);
L0410 int deadmask = otherwhite(g);
L0411 while ((curr = *p) != NULL && count-- > 0) {
L0412 if (curr->gch.tt == LUA_TTHREAD)
L0413 sweepwholelist(L, &gco2th(curr)->openupval);
L0414 if ((curr->gch.marked ^ WHITEBITS) & deadmask) {
L0415 lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));
L0416 makewhite(g, curr);
L0417 p = &curr->gch.next;
L0418 }
L0419 else {
L0420 lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));
L0421 *p = curr->gch.next;
L0422 if (curr == g->rootgc)
L0423 g->rootgc = curr->gch.next;
L0424 freeobj(L, curr);
L0425 }
L0426 }
L0427 return p;
L0428 }
L0429
L0430
L0431 static void checkSizes (lua_State *L) {
L0432 global_State *g = G(L);
L0433
L0434 if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&
L0435 g->strt.size > MINSTRTABSIZE*2)
L0436 luaS_resize(L, g->strt.size/2);
L0437
L0438 if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) {
L0439 size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
L0440 luaZ_resizebuffer(L, &g->buff, newsize);
L0441 }
L0442 }
L0443
L0444
L0445 static void GCTM (lua_State *L) {
L0446 global_State *g = G(L);
L0447 GCObject *o = g->tmudata->gch.next;
L0448 Udata *udata = rawgco2u(o);
L0449 const TValue *tm;
L0450
L0451 if (o == g->tmudata)
L0452 g->tmudata = NULL;
L0453 else
L0454 g->tmudata->gch.next = udata->uv.next;
L0455 udata->uv.next = g->mainthread->next;
L0456 g->mainthread->next = o;
L0457 makewhite(g, o);
L0458 tm = fasttm(L, udata->uv.metatable, TM_GC);
L0459 if (tm != NULL) {
L0460 lu_byte oldah = L->allowhook;
L0461 lu_mem oldt = g->GCthreshold;
L0462 L->allowhook = 0;
L0463 g->GCthreshold = 2*g->totalbytes;
L0464 setobj2s(L, L->top, tm);
L0465 setuvalue(L, L->top+1, udata);
L0466 L->top += 2;
L0467 luaD_call(L, L->top - 2, 0);
L0468 L->allowhook = oldah;
L0469 g->GCthreshold = oldt;
L0470 }
L0471 }
L0472
L0473
L0474
L0477 void luaC_callGCTM (lua_State *L) {
L0478 while (G(L)->tmudata)
L0479 GCTM(L);
L0480 }
L0481
L0482
L0483 void luaC_freeall (lua_State *L) {
L0484 global_State *g = G(L);
L0485 int i;
L0486 g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT);
L0487 sweepwholelist(L, &g->rootgc);
L0488 for (i = 0; i < g->strt.size; i++)
L0489 sweepwholelist(L, &g->strt.hash[i]);
L0490 }
L0491
L0492
L0493 static void markmt (global_State *g) {
L0494 int i;
L0495 for (i=0; i<NUM_TAGS; i++)
L0496 if (g->mt[i]) markobject(g, g->mt[i]);
L0497 }
L0498
L0499
L0500
L0501 static void markroot (lua_State *L) {
L0502 global_State *g = G(L);
L0503 g->gray = NULL;
L0504 g->grayagain = NULL;
L0505 g->weak = NULL;
L0506 markobject(g, g->mainthread);
L0507
L0508 markvalue(g, gt(g->mainthread));
L0509 markvalue(g, registry(L));
L0510 markmt(g);
L0511 g->gcstate = GCSpropagate;
L0512 }
L0513
L0514
L0515 static void remarkupvals (global_State *g) {
L0516 UpVal *uv;
L0517 for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
L0518 lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
L0519 if (isgray(obj2gco(uv)))
L0520 markvalue(g, uv->v);
L0521 }
L0522 }
L0523
L0524
L0525 static void atomic (lua_State *L) {
L0526 global_State *g = G(L);
L0527 size_t udsize;
L0528
L0529 remarkupvals(g);
L0530
L0531 propagateall(g);
L0532
L0533 g->gray = g->weak;
L0534 g->weak = NULL;
L0535 lua_assert(!iswhite(obj2gco(g->mainthread)));
L0536 markobject(g, L);
L0537 markmt(g);
L0538 propagateall(g);
L0539
L0540 g->gray = g->grayagain;
L0541 g->grayagain = NULL;
L0542 propagateall(g);
L0543 udsize = luaC_separateudata(L, 0);
L0544 marktmu(g);
L0545 udsize += propagateall(g);
L0546 cleartable(g->weak);
L0547
L0548 g->currentwhite = cast_byte(otherwhite(g));
L0549 g->sweepstrgc = 0;
L0550 g->sweepgc = &g->rootgc;
L0551 g->gcstate = GCSsweepstring;
L0552 g->estimate = g->totalbytes - udsize;
L0553 }
L0554
L0555
L0556 static l_mem singlestep (lua_State *L) {
L0557 global_State *g = G(L);
L0558
L0559 switch (g->gcstate) {
L0560 case GCSpause: {
L0561 markroot(L);
L0562 return 0;
L0563 }
L0564 case GCSpropagate: {
L0565 if (g->gray)
L0566 return propagatemark(g);
L0567 else {
L0568 atomic(L);
L0569 return 0;
L0570 }
L0571 }
L0572 case GCSsweepstring: {
L0573 lu_mem old = g->totalbytes;
L0574 sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
L0575 if (g->sweepstrgc >= g->strt.size)
L0576 g->gcstate = GCSsweep;
L0577 lua_assert(old >= g->totalbytes);
L0578 g->estimate -= old - g->totalbytes;
L0579 return GCSWEEPCOST;
L0580 }
L0581 case GCSsweep: {
L0582 lu_mem old = g->totalbytes;
L0583 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
L0584 if (*g->sweepgc == NULL) {
L0585 checkSizes(L);
L0586 g->gcstate = GCSfinalize;
L0587 }
L0588 lua_assert(old >= g->totalbytes);
L0589 g->estimate -= old - g->totalbytes;
L0590 return GCSWEEPMAX*GCSWEEPCOST;
L0591 }
L0592 case GCSfinalize: {
L0593 if (g->tmudata) {
L0594 GCTM(L);
L0595 if (g->estimate > GCFINALIZECOST)
L0596 g->estimate -= GCFINALIZECOST;
L0597 return GCFINALIZECOST;
L0598 }
L0599 else {
L0600 g->gcstate = GCSpause;
L0601 g->gcdept = 0;
L0602 return 0;
L0603 }
L0604 }
L0605 default: lua_assert(0); return 0;
L0606 }
L0607 }
L0608
L0609
L0610 void luaC_step (lua_State *L) {
L0611 global_State *g = G(L);
L0612 l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
L0613 if (lim == 0)
L0614 lim = (MAX_LUMEM-1)/2;
L0615 g->gcdept += g->totalbytes - g->GCthreshold;
L0616 do {
L0617 lim -= singlestep(L);
L0618 if (g->gcstate == GCSpause)
L0619 break;
L0620 } while (lim > 0);
L0621 if (g->gcstate != GCSpause) {
L0622 if (g->gcdept < GCSTEPSIZE)
L0623 g->GCthreshold = g->totalbytes + GCSTEPSIZE;
L0624 else {
L0625 g->gcdept -= GCSTEPSIZE;
L0626 g->GCthreshold = g->totalbytes;
L0627 }
L0628 }
L0629 else {
L0630 lua_assert(g->totalbytes >= g->estimate);
L0631 setthreshold(g);
L0632 }
L0633 }
L0634
L0635
L0636 void luaC_fullgc (lua_State *L) {
L0637 global_State *g = G(L);
L0638 if (g->gcstate <= GCSpropagate) {
L0639
L0640 g->sweepstrgc = 0;
L0641 g->sweepgc = &g->rootgc;
L0642
L0643 g->gray = NULL;
L0644 g->grayagain = NULL;
L0645 g->weak = NULL;
L0646 g->gcstate = GCSsweepstring;
L0647 }
L0648 lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate);
L0649
L0650 while (g->gcstate != GCSfinalize) {
L0651 lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
L0652 singlestep(L);
L0653 }
L0654 markroot(L);
L0655 while (g->gcstate != GCSpause) {
L0656 singlestep(L);
L0657 }
L0658 setthreshold(g);
L0659 }
L0660
L0661
L0662 void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
L0663 global_State *g = G(L);
L0664 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
L0665 lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
L0666 lua_assert(ttype(&o->gch) != LUA_TTABLE);
L0667
L0668 if (g->gcstate == GCSpropagate)
L0669 reallymarkobject(g, v);
L0670 else
L0671 makewhite(g, o);
L0672 }
L0673
L0674
L0675 void luaC_barrierback (lua_State *L, Table *t) {
L0676 global_State *g = G(L);
L0677 GCObject *o = obj2gco(t);
L0678 lua_assert(isblack(o) && !isdead(g, o));
L0679 lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
L0680 black2gray(o);
L0681 t->gclist = g->grayagain;
L0682 g->grayagain = o;
L0683 }
L0684
L0685
L0686 void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
L0687 global_State *g = G(L);
L0688 o->gch.next = g->rootgc;
L0689 g->rootgc = o;
L0690 o->gch.marked = luaC_white(g);
L0691 o->gch.tt = tt;
L0692 }
L0693
L0694
L0695 void luaC_linkupval (lua_State *L, UpVal *uv) {
L0696 global_State *g = G(L);
L0697 GCObject *o = obj2gco(uv);
L0698 o->gch.next = g->rootgc;
L0699 g->rootgc = o;
L0700 if (isgray(o)) {
L0701 if (g->gcstate == GCSpropagate) {
L0702 gray2black(o);
L0703 luaC_barrier(L, uv, uv->v);
L0704 }
L0705 else {
L0706 makewhite(g, o);
L0707 lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
L0708 }
L0709 }
L0710 }
L0711
Generated by pretty.lua