xref: /netbsd-src/external/mit/lua/dist/src/lgc.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: lgc.c,v 1.9 2017/09/07 12:52:29 mbalmer Exp $	*/
2 
3 /*
4 ** Id: lgc.c,v 2.215 2016/12/22 13:08:50 roberto Exp
5 ** Garbage Collector
6 ** See Copyright Notice in lua.h
7 */
8 
9 #define lgc_c
10 #define LUA_CORE
11 
12 #include "lprefix.h"
13 
14 
15 #ifndef _KERNEL
16 #include <string.h>
17 #endif /* _KERNEL */
18 
19 #include "lua.h"
20 
21 #include "ldebug.h"
22 #include "ldo.h"
23 #include "lfunc.h"
24 #include "lgc.h"
25 #include "lmem.h"
26 #include "lobject.h"
27 #include "lstate.h"
28 #include "lstring.h"
29 #include "ltable.h"
30 #include "ltm.h"
31 
32 
33 /*
34 ** internal state for collector while inside the atomic phase. The
35 ** collector should never be in this state while running regular code.
36 */
37 #define GCSinsideatomic		(GCSpause + 1)
38 
39 /*
40 ** cost of sweeping one element (the size of a small object divided
41 ** by some adjust for the sweep speed)
42 */
43 #define GCSWEEPCOST	((sizeof(TString) + 4) / 4)
44 
45 /* maximum number of elements to sweep in each single step */
46 #define GCSWEEPMAX	(cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4))
47 
48 /* cost of calling one finalizer */
49 #define GCFINALIZECOST	GCSWEEPCOST
50 
51 
52 /*
53 ** macro to adjust 'stepmul': 'stepmul' is actually used like
54 ** 'stepmul / STEPMULADJ' (value chosen by tests)
55 */
56 #define STEPMULADJ		200
57 
58 
59 /*
60 ** macro to adjust 'pause': 'pause' is actually used like
61 ** 'pause / PAUSEADJ' (value chosen by tests)
62 */
63 #define PAUSEADJ		100
64 
65 
66 /*
67 ** 'makewhite' erases all color bits then sets only the current white
68 ** bit
69 */
70 #define maskcolors	(~(bitmask(BLACKBIT) | WHITEBITS))
71 #define makewhite(g,x)	\
72  (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g)))
73 
74 #define white2gray(x)	resetbits(x->marked, WHITEBITS)
75 #define black2gray(x)	resetbit(x->marked, BLACKBIT)
76 
77 
78 #define valiswhite(x)   (iscollectable(x) && iswhite(gcvalue(x)))
79 
80 #define checkdeadkey(n)	lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n)))
81 
82 
83 #define checkconsistency(obj)  \
84   lua_longassert(!iscollectable(obj) || righttt(obj))
85 
86 
87 #define markvalue(g,o) { checkconsistency(o); \
88   if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
89 
90 #define markobject(g,t)	{ if (iswhite(t)) reallymarkobject(g, obj2gco(t)); }
91 
92 /*
93 ** mark an object that can be NULL (either because it is really optional,
94 ** or it was stripped as debug info, or inside an uncompleted structure)
95 */
96 #define markobjectN(g,t)	{ if (t) markobject(g,t); }
97 
98 static void reallymarkobject (global_State *g, GCObject *o);
99 
100 
101 /*
102 ** {======================================================
103 ** Generic functions
104 ** =======================================================
105 */
106 
107 
108 /*
109 ** one after last element in a hash array
110 */
111 #define gnodelast(h)	gnode(h, cast(size_t, sizenode(h)))
112 
113 
114 /*
115 ** link collectable object 'o' into list pointed by 'p'
116 */
117 #define linkgclist(o,p)	((o)->gclist = (p), (p) = obj2gco(o))
118 
119 
120 /*
121 ** If key is not marked, mark its entry as dead. This allows key to be
122 ** collected, but keeps its entry in the table.  A dead node is needed
123 ** when Lua looks up for a key (it may be part of a chain) and when
124 ** traversing a weak table (key might be removed from the table during
125 ** traversal). Other places never manipulate dead keys, because its
126 ** associated nil value is enough to signal that the entry is logically
127 ** empty.
128 */
129 static void removeentry (Node *n) {
130   lua_assert(ttisnil(gval(n)));
131   if (valiswhite(gkey(n)))
132     setdeadvalue(wgkey(n));  /* unused and unmarked key; remove it */
133 }
134 
135 
136 /*
137 ** tells whether a key or value can be cleared from a weak
138 ** table. Non-collectable objects are never removed from weak
139 ** tables. Strings behave as 'values', so are never removed too. for
140 ** other objects: if really collected, cannot keep them; for objects
141 ** being finalized, keep them in keys, but not in values
142 */
143 static int iscleared (global_State *g, const TValue *o) {
144   if (!iscollectable(o)) return 0;
145   else if (ttisstring(o)) {
146     markobject(g, tsvalue(o));  /* strings are 'values', so are never weak */
147     return 0;
148   }
149   else return iswhite(gcvalue(o));
150 }
151 
152 
153 /*
154 ** barrier that moves collector forward, that is, mark the white object
155 ** being pointed by a black object. (If in sweep phase, clear the black
156 ** object to white [sweep it] to avoid other barrier calls for this
157 ** same object.)
158 */
159 void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
160   global_State *g = G(L);
161   lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
162   if (keepinvariant(g))  /* must keep invariant? */
163     reallymarkobject(g, v);  /* restore invariant */
164   else {  /* sweep phase */
165     lua_assert(issweepphase(g));
166     makewhite(g, o);  /* mark main obj. as white to avoid other barriers */
167   }
168 }
169 
170 
171 /*
172 ** barrier that moves collector backward, that is, mark the black object
173 ** pointing to a white object as gray again.
174 */
175 void luaC_barrierback_ (lua_State *L, Table *t) {
176   global_State *g = G(L);
177   lua_assert(isblack(t) && !isdead(g, t));
178   black2gray(t);  /* make table gray (again) */
179   linkgclist(t, g->grayagain);
180 }
181 
182 
183 /*
184 ** barrier for assignments to closed upvalues. Because upvalues are
185 ** shared among closures, it is impossible to know the color of all
186 ** closures pointing to it. So, we assume that the object being assigned
187 ** must be marked.
188 */
189 void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
190   global_State *g = G(L);
191   GCObject *o = gcvalue(uv->v);
192   lua_assert(!upisopen(uv));  /* ensured by macro luaC_upvalbarrier */
193   if (keepinvariant(g))
194     markobject(g, o);
195 }
196 
197 
198 void luaC_fix (lua_State *L, GCObject *o) {
199   global_State *g = G(L);
200   lua_assert(g->allgc == o);  /* object must be 1st in 'allgc' list! */
201   white2gray(o);  /* they will be gray forever */
202   g->allgc = o->next;  /* remove object from 'allgc' list */
203   o->next = g->fixedgc;  /* link it to 'fixedgc' list */
204   g->fixedgc = o;
205 }
206 
207 
208 /*
209 ** create a new collectable object (with given type and size) and link
210 ** it to 'allgc' list.
211 */
212 GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
213   global_State *g = G(L);
214   GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz));
215   o->marked = luaC_white(g);
216   o->tt = tt;
217   o->next = g->allgc;
218   g->allgc = o;
219   return o;
220 }
221 
222 /* }====================================================== */
223 
224 
225 
226 /*
227 ** {======================================================
228 ** Mark functions
229 ** =======================================================
230 */
231 
232 
233 /*
234 ** mark an object. Userdata, strings, and closed upvalues are visited
235 ** and turned black here. Other objects are marked gray and added
236 ** to appropriate list to be visited (and turned black) later. (Open
237 ** upvalues are already linked in 'headuv' list.)
238 */
239 static void reallymarkobject (global_State *g, GCObject *o) {
240  reentry:
241   white2gray(o);
242   switch (o->tt) {
243     case LUA_TSHRSTR: {
244       gray2black(o);
245       g->GCmemtrav += sizelstring(gco2ts(o)->shrlen);
246       break;
247     }
248     case LUA_TLNGSTR: {
249       gray2black(o);
250       g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen);
251       break;
252     }
253     case LUA_TUSERDATA: {
254       TValue uvalue;
255       markobjectN(g, gco2u(o)->metatable);  /* mark its metatable */
256       gray2black(o);
257       g->GCmemtrav += sizeudata(gco2u(o));
258       getuservalue(g->mainthread, gco2u(o), &uvalue);
259       if (valiswhite(&uvalue)) {  /* markvalue(g, &uvalue); */
260         o = gcvalue(&uvalue);
261         goto reentry;
262       }
263       break;
264     }
265     case LUA_TLCL: {
266       linkgclist(gco2lcl(o), g->gray);
267       break;
268     }
269     case LUA_TCCL: {
270       linkgclist(gco2ccl(o), g->gray);
271       break;
272     }
273     case LUA_TTABLE: {
274       linkgclist(gco2t(o), g->gray);
275       break;
276     }
277     case LUA_TTHREAD: {
278       linkgclist(gco2th(o), g->gray);
279       break;
280     }
281     case LUA_TPROTO: {
282       linkgclist(gco2p(o), g->gray);
283       break;
284     }
285     default: lua_assert(0); break;
286   }
287 }
288 
289 
290 /*
291 ** mark metamethods for basic types
292 */
293 static void markmt (global_State *g) {
294   int i;
295   for (i=0; i < LUA_NUMTAGS; i++)
296     markobjectN(g, g->mt[i]);
297 }
298 
299 
300 /*
301 ** mark all objects in list of being-finalized
302 */
303 static void markbeingfnz (global_State *g) {
304   GCObject *o;
305   for (o = g->tobefnz; o != NULL; o = o->next)
306     markobject(g, o);
307 }
308 
309 
310 /*
311 ** Mark all values stored in marked open upvalues from non-marked threads.
312 ** (Values from marked threads were already marked when traversing the
313 ** thread.) Remove from the list threads that no longer have upvalues and
314 ** not-marked threads.
315 */
316 static void remarkupvals (global_State *g) {
317   lua_State *thread;
318   lua_State **p = &g->twups;
319   while ((thread = *p) != NULL) {
320     lua_assert(!isblack(thread));  /* threads are never black */
321     if (isgray(thread) && thread->openupval != NULL)
322       p = &thread->twups;  /* keep marked thread with upvalues in the list */
323     else {  /* thread is not marked or without upvalues */
324       UpVal *uv;
325       *p = thread->twups;  /* remove thread from the list */
326       thread->twups = thread;  /* mark that it is out of list */
327       for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) {
328         if (uv->u.open.touched) {
329           markvalue(g, uv->v);  /* remark upvalue's value */
330           uv->u.open.touched = 0;
331         }
332       }
333     }
334   }
335 }
336 
337 
338 /*
339 ** mark root set and reset all gray lists, to start a new collection
340 */
341 static void restartcollection (global_State *g) {
342   g->gray = g->grayagain = NULL;
343   g->weak = g->allweak = g->ephemeron = NULL;
344   markobject(g, g->mainthread);
345   markvalue(g, &g->l_registry);
346   markmt(g);
347   markbeingfnz(g);  /* mark any finalizing object left from previous cycle */
348 }
349 
350 /* }====================================================== */
351 
352 
353 /*
354 ** {======================================================
355 ** Traverse functions
356 ** =======================================================
357 */
358 
359 /*
360 ** Traverse a table with weak values and link it to proper list. During
361 ** propagate phase, keep it in 'grayagain' list, to be revisited in the
362 ** atomic phase. In the atomic phase, if table has any white value,
363 ** put it in 'weak' list, to be cleared.
364 */
365 static void traverseweakvalue (global_State *g, Table *h) {
366   Node *n, *limit = gnodelast(h);
367   /* if there is array part, assume it may have white values (it is not
368      worth traversing it now just to check) */
369   int hasclears = (h->sizearray > 0);
370   for (n = gnode(h, 0); n < limit; n++) {  /* traverse hash part */
371     checkdeadkey(n);
372     if (ttisnil(gval(n)))  /* entry is empty? */
373       removeentry(n);  /* remove it */
374     else {
375       lua_assert(!ttisnil(gkey(n)));
376       markvalue(g, gkey(n));  /* mark key */
377       if (!hasclears && iscleared(g, gval(n)))  /* is there a white value? */
378         hasclears = 1;  /* table will have to be cleared */
379     }
380   }
381   if (g->gcstate == GCSpropagate)
382     linkgclist(h, g->grayagain);  /* must retraverse it in atomic phase */
383   else if (hasclears)
384     linkgclist(h, g->weak);  /* has to be cleared later */
385 }
386 
387 
388 /*
389 ** Traverse an ephemeron table and link it to proper list. Returns true
390 ** iff any object was marked during this traversal (which implies that
391 ** convergence has to continue). During propagation phase, keep table
392 ** in 'grayagain' list, to be visited again in the atomic phase. In
393 ** the atomic phase, if table has any white->white entry, it has to
394 ** be revisited during ephemeron convergence (as that key may turn
395 ** black). Otherwise, if it has any white key, table has to be cleared
396 ** (in the atomic phase).
397 */
398 static int traverseephemeron (global_State *g, Table *h) {
399   int marked = 0;  /* true if an object is marked in this traversal */
400   int hasclears = 0;  /* true if table has white keys */
401   int hasww = 0;  /* true if table has entry "white-key -> white-value" */
402   Node *n, *limit = gnodelast(h);
403   unsigned int i;
404   /* traverse array part */
405   for (i = 0; i < h->sizearray; i++) {
406     if (valiswhite(&h->array[i])) {
407       marked = 1;
408       reallymarkobject(g, gcvalue(&h->array[i]));
409     }
410   }
411   /* traverse hash part */
412   for (n = gnode(h, 0); n < limit; n++) {
413     checkdeadkey(n);
414     if (ttisnil(gval(n)))  /* entry is empty? */
415       removeentry(n);  /* remove it */
416     else if (iscleared(g, gkey(n))) {  /* key is not marked (yet)? */
417       hasclears = 1;  /* table must be cleared */
418       if (valiswhite(gval(n)))  /* value not marked yet? */
419         hasww = 1;  /* white-white entry */
420     }
421     else if (valiswhite(gval(n))) {  /* value not marked yet? */
422       marked = 1;
423       reallymarkobject(g, gcvalue(gval(n)));  /* mark it now */
424     }
425   }
426   /* link table into proper list */
427   if (g->gcstate == GCSpropagate)
428     linkgclist(h, g->grayagain);  /* must retraverse it in atomic phase */
429   else if (hasww)  /* table has white->white entries? */
430     linkgclist(h, g->ephemeron);  /* have to propagate again */
431   else if (hasclears)  /* table has white keys? */
432     linkgclist(h, g->allweak);  /* may have to clean white keys */
433   return marked;
434 }
435 
436 
437 static void traversestrongtable (global_State *g, Table *h) {
438   Node *n, *limit = gnodelast(h);
439   unsigned int i;
440   for (i = 0; i < h->sizearray; i++)  /* traverse array part */
441     markvalue(g, &h->array[i]);
442   for (n = gnode(h, 0); n < limit; n++) {  /* traverse hash part */
443     checkdeadkey(n);
444     if (ttisnil(gval(n)))  /* entry is empty? */
445       removeentry(n);  /* remove it */
446     else {
447       lua_assert(!ttisnil(gkey(n)));
448       markvalue(g, gkey(n));  /* mark key */
449       markvalue(g, gval(n));  /* mark value */
450     }
451   }
452 }
453 
454 
455 static lu_mem traversetable (global_State *g, Table *h) {
456   const char *weakkey, *weakvalue;
457   const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
458   markobjectN(g, h->metatable);
459   if (mode && ttisstring(mode) &&  /* is there a weak mode? */
460       ((weakkey = strchr(svalue(mode), 'k')),
461        (weakvalue = strchr(svalue(mode), 'v')),
462        (weakkey || weakvalue))) {  /* is really weak? */
463     black2gray(h);  /* keep table gray */
464     if (!weakkey)  /* strong keys? */
465       traverseweakvalue(g, h);
466     else if (!weakvalue)  /* strong values? */
467       traverseephemeron(g, h);
468     else  /* all weak */
469       linkgclist(h, g->allweak);  /* nothing to traverse now */
470   }
471   else  /* not weak */
472     traversestrongtable(g, h);
473   return sizeof(Table) + sizeof(TValue) * h->sizearray +
474                          sizeof(Node) * cast(size_t, allocsizenode(h));
475 }
476 
477 
478 /*
479 ** Traverse a prototype. (While a prototype is being build, its
480 ** arrays can be larger than needed; the extra slots are filled with
481 ** NULL, so the use of 'markobjectN')
482 */
483 static int traverseproto (global_State *g, Proto *f) {
484   int i;
485   if (f->cache && iswhite(f->cache))
486     f->cache = NULL;  /* allow cache to be collected */
487   markobjectN(g, f->source);
488   for (i = 0; i < f->sizek; i++)  /* mark literals */
489     markvalue(g, &f->k[i]);
490   for (i = 0; i < f->sizeupvalues; i++)  /* mark upvalue names */
491     markobjectN(g, f->upvalues[i].name);
492   for (i = 0; i < f->sizep; i++)  /* mark nested protos */
493     markobjectN(g, f->p[i]);
494   for (i = 0; i < f->sizelocvars; i++)  /* mark local-variable names */
495     markobjectN(g, f->locvars[i].varname);
496   return sizeof(Proto) + sizeof(Instruction) * f->sizecode +
497                          sizeof(Proto *) * f->sizep +
498                          sizeof(TValue) * f->sizek +
499                          sizeof(int) * f->sizelineinfo +
500                          sizeof(LocVar) * f->sizelocvars +
501                          sizeof(Upvaldesc) * f->sizeupvalues;
502 }
503 
504 
505 static lu_mem traverseCclosure (global_State *g, CClosure *cl) {
506   int i;
507   for (i = 0; i < cl->nupvalues; i++)  /* mark its upvalues */
508     markvalue(g, &cl->upvalue[i]);
509   return sizeCclosure(cl->nupvalues);
510 }
511 
512 /*
513 ** open upvalues point to values in a thread, so those values should
514 ** be marked when the thread is traversed except in the atomic phase
515 ** (because then the value cannot be changed by the thread and the
516 ** thread may not be traversed again)
517 */
518 static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
519   int i;
520   markobjectN(g, cl->p);  /* mark its prototype */
521   for (i = 0; i < cl->nupvalues; i++) {  /* mark its upvalues */
522     UpVal *uv = cl->upvals[i];
523     if (uv != NULL) {
524       if (upisopen(uv) && g->gcstate != GCSinsideatomic)
525         uv->u.open.touched = 1;  /* can be marked in 'remarkupvals' */
526       else
527         markvalue(g, uv->v);
528     }
529   }
530   return sizeLclosure(cl->nupvalues);
531 }
532 
533 
534 static lu_mem traversethread (global_State *g, lua_State *th) {
535   StkId o = th->stack;
536   if (o == NULL)
537     return 1;  /* stack not completely built yet */
538   lua_assert(g->gcstate == GCSinsideatomic ||
539              th->openupval == NULL || isintwups(th));
540   for (; o < th->top; o++)  /* mark live elements in the stack */
541     markvalue(g, o);
542   if (g->gcstate == GCSinsideatomic) {  /* final traversal? */
543     StkId lim = th->stack + th->stacksize;  /* real end of stack */
544     for (; o < lim; o++)  /* clear not-marked stack slice */
545       setnilvalue(o);
546     /* 'remarkupvals' may have removed thread from 'twups' list */
547     if (!isintwups(th) && th->openupval != NULL) {
548       th->twups = g->twups;  /* link it back to the list */
549       g->twups = th;
550     }
551   }
552   else if (g->gckind != KGC_EMERGENCY)
553     luaD_shrinkstack(th); /* do not change stack in emergency cycle */
554   return (sizeof(lua_State) + sizeof(TValue) * th->stacksize +
555           sizeof(CallInfo) * th->nci);
556 }
557 
558 
559 /*
560 ** traverse one gray object, turning it to black (except for threads,
561 ** which are always gray).
562 */
563 static void propagatemark (global_State *g) {
564   lu_mem size;
565   GCObject *o = g->gray;
566   lua_assert(isgray(o));
567   gray2black(o);
568   switch (o->tt) {
569     case LUA_TTABLE: {
570       Table *h = gco2t(o);
571       g->gray = h->gclist;  /* remove from 'gray' list */
572       size = traversetable(g, h);
573       break;
574     }
575     case LUA_TLCL: {
576       LClosure *cl = gco2lcl(o);
577       g->gray = cl->gclist;  /* remove from 'gray' list */
578       size = traverseLclosure(g, cl);
579       break;
580     }
581     case LUA_TCCL: {
582       CClosure *cl = gco2ccl(o);
583       g->gray = cl->gclist;  /* remove from 'gray' list */
584       size = traverseCclosure(g, cl);
585       break;
586     }
587     case LUA_TTHREAD: {
588       lua_State *th = gco2th(o);
589       g->gray = th->gclist;  /* remove from 'gray' list */
590       linkgclist(th, g->grayagain);  /* insert into 'grayagain' list */
591       black2gray(o);
592       size = traversethread(g, th);
593       break;
594     }
595     case LUA_TPROTO: {
596       Proto *p = gco2p(o);
597       g->gray = p->gclist;  /* remove from 'gray' list */
598       size = traverseproto(g, p);
599       break;
600     }
601     default: lua_assert(0); return;
602   }
603   g->GCmemtrav += size;
604 }
605 
606 
607 static void propagateall (global_State *g) {
608   while (g->gray) propagatemark(g);
609 }
610 
611 
612 static void convergeephemerons (global_State *g) {
613   int changed;
614   do {
615     GCObject *w;
616     GCObject *next = g->ephemeron;  /* get ephemeron list */
617     g->ephemeron = NULL;  /* tables may return to this list when traversed */
618     changed = 0;
619     while ((w = next) != NULL) {
620       next = gco2t(w)->gclist;
621       if (traverseephemeron(g, gco2t(w))) {  /* traverse marked some value? */
622         propagateall(g);  /* propagate changes */
623         changed = 1;  /* will have to revisit all ephemeron tables */
624       }
625     }
626   } while (changed);
627 }
628 
629 /* }====================================================== */
630 
631 
632 /*
633 ** {======================================================
634 ** Sweep Functions
635 ** =======================================================
636 */
637 
638 
639 /*
640 ** clear entries with unmarked keys from all weaktables in list 'l' up
641 ** to element 'f'
642 */
643 static void clearkeys (global_State *g, GCObject *l, GCObject *f) {
644   for (; l != f; l = gco2t(l)->gclist) {
645     Table *h = gco2t(l);
646     Node *n, *limit = gnodelast(h);
647     for (n = gnode(h, 0); n < limit; n++) {
648       if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) {
649         setnilvalue(gval(n));  /* remove value ... */
650       }
651       if (ttisnil(gval(n)))  /* is entry empty? */
652         removeentry(n);  /* remove entry from table */
653     }
654   }
655 }
656 
657 
658 /*
659 ** clear entries with unmarked values from all weaktables in list 'l' up
660 ** to element 'f'
661 */
662 static void clearvalues (global_State *g, GCObject *l, GCObject *f) {
663   for (; l != f; l = gco2t(l)->gclist) {
664     Table *h = gco2t(l);
665     Node *n, *limit = gnodelast(h);
666     unsigned int i;
667     for (i = 0; i < h->sizearray; i++) {
668       TValue *o = &h->array[i];
669       if (iscleared(g, o))  /* value was collected? */
670         setnilvalue(o);  /* remove value */
671     }
672     for (n = gnode(h, 0); n < limit; n++) {
673       if (!ttisnil(gval(n)) && iscleared(g, gval(n))) {
674         setnilvalue(gval(n));  /* remove value ... */
675         removeentry(n);  /* and remove entry from table */
676       }
677     }
678   }
679 }
680 
681 
682 void luaC_upvdeccount (lua_State *L, UpVal *uv) {
683   lua_assert(uv->refcount > 0);
684   uv->refcount--;
685   if (uv->refcount == 0 && !upisopen(uv))
686     luaM_free(L, uv);
687 }
688 
689 
690 static void freeLclosure (lua_State *L, LClosure *cl) {
691   int i;
692   for (i = 0; i < cl->nupvalues; i++) {
693     UpVal *uv = cl->upvals[i];
694     if (uv)
695       luaC_upvdeccount(L, uv);
696   }
697   luaM_freemem(L, cl, sizeLclosure(cl->nupvalues));
698 }
699 
700 
701 static void freeobj (lua_State *L, GCObject *o) {
702   switch (o->tt) {
703     case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
704     case LUA_TLCL: {
705       freeLclosure(L, gco2lcl(o));
706       break;
707     }
708     case LUA_TCCL: {
709       luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues));
710       break;
711     }
712     case LUA_TTABLE: luaH_free(L, gco2t(o)); break;
713     case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break;
714     case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
715     case LUA_TSHRSTR:
716       luaS_remove(L, gco2ts(o));  /* remove it from hash table */
717       luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen));
718       break;
719     case LUA_TLNGSTR: {
720       luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen));
721       break;
722     }
723     default: lua_assert(0);
724   }
725 }
726 
727 
728 #define sweepwholelist(L,p)	sweeplist(L,p,MAX_LUMEM)
729 static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count);
730 
731 
732 /*
733 ** sweep at most 'count' elements from a list of GCObjects erasing dead
734 ** objects, where a dead object is one marked with the old (non current)
735 ** white; change all non-dead objects back to white, preparing for next
736 ** collection cycle. Return where to continue the traversal or NULL if
737 ** list is finished.
738 */
739 static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
740   global_State *g = G(L);
741   int ow = otherwhite(g);
742   int white = luaC_white(g);  /* current white */
743   while (*p != NULL && count-- > 0) {
744     GCObject *curr = *p;
745     int marked = curr->marked;
746     if (isdeadm(ow, marked)) {  /* is 'curr' dead? */
747       *p = curr->next;  /* remove 'curr' from list */
748       freeobj(L, curr);  /* erase 'curr' */
749     }
750     else {  /* change mark to 'white' */
751       curr->marked = cast_byte((marked & maskcolors) | white);
752       p = &curr->next;  /* go to next element */
753     }
754   }
755   return (*p == NULL) ? NULL : p;
756 }
757 
758 
759 /*
760 ** sweep a list until a live object (or end of list)
761 */
762 static GCObject **sweeptolive (lua_State *L, GCObject **p) {
763   GCObject **old = p;
764   do {
765     p = sweeplist(L, p, 1);
766   } while (p == old);
767   return p;
768 }
769 
770 /* }====================================================== */
771 
772 
773 /*
774 ** {======================================================
775 ** Finalization
776 ** =======================================================
777 */
778 
779 /*
780 ** If possible, shrink string table
781 */
782 static void checkSizes (lua_State *L, global_State *g) {
783   if (g->gckind != KGC_EMERGENCY) {
784     l_mem olddebt = g->GCdebt;
785     if (g->strt.nuse < g->strt.size / 4)  /* string table too big? */
786       luaS_resize(L, g->strt.size / 2);  /* shrink it a little */
787     g->GCestimate += g->GCdebt - olddebt;  /* update estimate */
788   }
789 }
790 
791 
792 static GCObject *udata2finalize (global_State *g) {
793   GCObject *o = g->tobefnz;  /* get first element */
794   lua_assert(tofinalize(o));
795   g->tobefnz = o->next;  /* remove it from 'tobefnz' list */
796   o->next = g->allgc;  /* return it to 'allgc' list */
797   g->allgc = o;
798   resetbit(o->marked, FINALIZEDBIT);  /* object is "normal" again */
799   if (issweepphase(g))
800     makewhite(g, o);  /* "sweep" object */
801   return o;
802 }
803 
804 
805 static void dothecall (lua_State *L, void *ud) {
806   UNUSED(ud);
807   luaD_callnoyield(L, L->top - 2, 0);
808 }
809 
810 
811 static void GCTM (lua_State *L, int propagateerrors) {
812   global_State *g = G(L);
813   const TValue *tm;
814   TValue v;
815   setgcovalue(L, &v, udata2finalize(g));
816   tm = luaT_gettmbyobj(L, &v, TM_GC);
817   if (tm != NULL && ttisfunction(tm)) {  /* is there a finalizer? */
818     int status;
819     lu_byte oldah = L->allowhook;
820     int running  = g->gcrunning;
821     L->allowhook = 0;  /* stop debug hooks during GC metamethod */
822     g->gcrunning = 0;  /* avoid GC steps */
823     setobj2s(L, L->top, tm);  /* push finalizer... */
824     setobj2s(L, L->top + 1, &v);  /* ... and its argument */
825     L->top += 2;  /* and (next line) call the finalizer */
826     L->ci->callstatus |= CIST_FIN;  /* will run a finalizer */
827     status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0);
828     L->ci->callstatus &= ~CIST_FIN;  /* not running a finalizer anymore */
829     L->allowhook = oldah;  /* restore hooks */
830     g->gcrunning = running;  /* restore state */
831     if (status != LUA_OK && propagateerrors) {  /* error while running __gc? */
832       if (status == LUA_ERRRUN) {  /* is there an error object? */
833         const char *msg = (ttisstring(L->top - 1))
834                             ? svalue(L->top - 1)
835                             : "no message";
836         luaO_pushfstring(L, "error in __gc metamethod (%s)", msg);
837         status = LUA_ERRGCMM;  /* error in __gc metamethod */
838       }
839       luaD_throw(L, status);  /* re-throw error */
840     }
841   }
842 }
843 
844 
845 /*
846 ** call a few (up to 'g->gcfinnum') finalizers
847 */
848 static int runafewfinalizers (lua_State *L) {
849   global_State *g = G(L);
850   unsigned int i;
851   lua_assert(!g->tobefnz || g->gcfinnum > 0);
852   for (i = 0; g->tobefnz && i < g->gcfinnum; i++)
853     GCTM(L, 1);  /* call one finalizer */
854   g->gcfinnum = (!g->tobefnz) ? 0  /* nothing more to finalize? */
855                     : g->gcfinnum * 2;  /* else call a few more next time */
856   return i;
857 }
858 
859 
860 /*
861 ** call all pending finalizers
862 */
863 static void callallpendingfinalizers (lua_State *L) {
864   global_State *g = G(L);
865   while (g->tobefnz)
866     GCTM(L, 0);
867 }
868 
869 
870 /*
871 ** find last 'next' field in list 'p' list (to add elements in its end)
872 */
873 static GCObject **findlast (GCObject **p) {
874   while (*p != NULL)
875     p = &(*p)->next;
876   return p;
877 }
878 
879 
880 /*
881 ** move all unreachable objects (or 'all' objects) that need
882 ** finalization from list 'finobj' to list 'tobefnz' (to be finalized)
883 */
884 static void separatetobefnz (global_State *g, int all) {
885   GCObject *curr;
886   GCObject **p = &g->finobj;
887   GCObject **lastnext = findlast(&g->tobefnz);
888   while ((curr = *p) != NULL) {  /* traverse all finalizable objects */
889     lua_assert(tofinalize(curr));
890     if (!(iswhite(curr) || all))  /* not being collected? */
891       p = &curr->next;  /* don't bother with it */
892     else {
893       *p = curr->next;  /* remove 'curr' from 'finobj' list */
894       curr->next = *lastnext;  /* link at the end of 'tobefnz' list */
895       *lastnext = curr;
896       lastnext = &curr->next;
897     }
898   }
899 }
900 
901 
902 /*
903 ** if object 'o' has a finalizer, remove it from 'allgc' list (must
904 ** search the list to find it) and link it in 'finobj' list.
905 */
906 void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
907   global_State *g = G(L);
908   if (tofinalize(o) ||                 /* obj. is already marked... */
909       gfasttm(g, mt, TM_GC) == NULL)   /* or has no finalizer? */
910     return;  /* nothing to be done */
911   else {  /* move 'o' to 'finobj' list */
912     GCObject **p;
913     if (issweepphase(g)) {
914       makewhite(g, o);  /* "sweep" object 'o' */
915       if (g->sweepgc == &o->next)  /* should not remove 'sweepgc' object */
916         g->sweepgc = sweeptolive(L, g->sweepgc);  /* change 'sweepgc' */
917     }
918     /* search for pointer pointing to 'o' */
919     for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ }
920     *p = o->next;  /* remove 'o' from 'allgc' list */
921     o->next = g->finobj;  /* link it in 'finobj' list */
922     g->finobj = o;
923     l_setbit(o->marked, FINALIZEDBIT);  /* mark it as such */
924   }
925 }
926 
927 /* }====================================================== */
928 
929 
930 
931 /*
932 ** {======================================================
933 ** GC control
934 ** =======================================================
935 */
936 
937 
938 /*
939 ** Set a reasonable "time" to wait before starting a new GC cycle; cycle
940 ** will start when memory use hits threshold. (Division by 'estimate'
941 ** should be OK: it cannot be zero (because Lua cannot even start with
942 ** less than PAUSEADJ bytes).
943 */
944 static void setpause (global_State *g) {
945   l_mem threshold, debt;
946   l_mem estimate = g->GCestimate / PAUSEADJ;  /* adjust 'estimate' */
947   lua_assert(estimate > 0);
948   threshold = (g->gcpause < MAX_LMEM / estimate)  /* overflow? */
949             ? estimate * g->gcpause  /* no overflow */
950             : MAX_LMEM;  /* overflow; truncate to maximum */
951   debt = gettotalbytes(g) - threshold;
952   luaE_setdebt(g, debt);
953 }
954 
955 
956 /*
957 ** Enter first sweep phase.
958 ** The call to 'sweeplist' tries to make pointer point to an object
959 ** inside the list (instead of to the header), so that the real sweep do
960 ** not need to skip objects created between "now" and the start of the
961 ** real sweep.
962 */
963 static void entersweep (lua_State *L) {
964   global_State *g = G(L);
965   g->gcstate = GCSswpallgc;
966   lua_assert(g->sweepgc == NULL);
967   g->sweepgc = sweeplist(L, &g->allgc, 1);
968 }
969 
970 
971 void luaC_freeallobjects (lua_State *L) {
972   global_State *g = G(L);
973   separatetobefnz(g, 1);  /* separate all objects with finalizers */
974   lua_assert(g->finobj == NULL);
975   callallpendingfinalizers(L);
976   lua_assert(g->tobefnz == NULL);
977   g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */
978   g->gckind = KGC_NORMAL;
979   sweepwholelist(L, &g->finobj);
980   sweepwholelist(L, &g->allgc);
981   sweepwholelist(L, &g->fixedgc);  /* collect fixed objects */
982   lua_assert(g->strt.nuse == 0);
983 }
984 
985 
986 static l_mem atomic (lua_State *L) {
987   global_State *g = G(L);
988   l_mem work;
989   GCObject *origweak, *origall;
990   GCObject *grayagain = g->grayagain;  /* save original list */
991   lua_assert(g->ephemeron == NULL && g->weak == NULL);
992   lua_assert(!iswhite(g->mainthread));
993   g->gcstate = GCSinsideatomic;
994   g->GCmemtrav = 0;  /* start counting work */
995   markobject(g, L);  /* mark running thread */
996   /* registry and global metatables may be changed by API */
997   markvalue(g, &g->l_registry);
998   markmt(g);  /* mark global metatables */
999   /* remark occasional upvalues of (maybe) dead threads */
1000   remarkupvals(g);
1001   propagateall(g);  /* propagate changes */
1002   work = g->GCmemtrav;  /* stop counting (do not recount 'grayagain') */
1003   g->gray = grayagain;
1004   propagateall(g);  /* traverse 'grayagain' list */
1005   g->GCmemtrav = 0;  /* restart counting */
1006   convergeephemerons(g);
1007   /* at this point, all strongly accessible objects are marked. */
1008   /* Clear values from weak tables, before checking finalizers */
1009   clearvalues(g, g->weak, NULL);
1010   clearvalues(g, g->allweak, NULL);
1011   origweak = g->weak; origall = g->allweak;
1012   work += g->GCmemtrav;  /* stop counting (objects being finalized) */
1013   separatetobefnz(g, 0);  /* separate objects to be finalized */
1014   g->gcfinnum = 1;  /* there may be objects to be finalized */
1015   markbeingfnz(g);  /* mark objects that will be finalized */
1016   propagateall(g);  /* remark, to propagate 'resurrection' */
1017   g->GCmemtrav = 0;  /* restart counting */
1018   convergeephemerons(g);
1019   /* at this point, all resurrected objects are marked. */
1020   /* remove dead objects from weak tables */
1021   clearkeys(g, g->ephemeron, NULL);  /* clear keys from all ephemeron tables */
1022   clearkeys(g, g->allweak, NULL);  /* clear keys from all 'allweak' tables */
1023   /* clear values from resurrected weak tables */
1024   clearvalues(g, g->weak, origweak);
1025   clearvalues(g, g->allweak, origall);
1026   luaS_clearcache(g);
1027   g->currentwhite = cast_byte(otherwhite(g));  /* flip current white */
1028   work += g->GCmemtrav;  /* complete counting */
1029   return work;  /* estimate of memory marked by 'atomic' */
1030 }
1031 
1032 
1033 static lu_mem sweepstep (lua_State *L, global_State *g,
1034                          int nextstate, GCObject **nextlist) {
1035   if (g->sweepgc) {
1036     l_mem olddebt = g->GCdebt;
1037     g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
1038     g->GCestimate += g->GCdebt - olddebt;  /* update estimate */
1039     if (g->sweepgc)  /* is there still something to sweep? */
1040       return (GCSWEEPMAX * GCSWEEPCOST);
1041   }
1042   /* else enter next state */
1043   g->gcstate = nextstate;
1044   g->sweepgc = nextlist;
1045   return 0;
1046 }
1047 
1048 
1049 static lu_mem singlestep (lua_State *L) {
1050   global_State *g = G(L);
1051   switch (g->gcstate) {
1052     case GCSpause: {
1053       g->GCmemtrav = g->strt.size * sizeof(GCObject*);
1054       restartcollection(g);
1055       g->gcstate = GCSpropagate;
1056       return g->GCmemtrav;
1057     }
1058     case GCSpropagate: {
1059       g->GCmemtrav = 0;
1060       lua_assert(g->gray);
1061       propagatemark(g);
1062        if (g->gray == NULL)  /* no more gray objects? */
1063         g->gcstate = GCSatomic;  /* finish propagate phase */
1064       return g->GCmemtrav;  /* memory traversed in this step */
1065     }
1066     case GCSatomic: {
1067       lu_mem work;
1068       propagateall(g);  /* make sure gray list is empty */
1069       work = atomic(L);  /* work is what was traversed by 'atomic' */
1070       entersweep(L);
1071       g->GCestimate = gettotalbytes(g);  /* first estimate */;
1072       return work;
1073     }
1074     case GCSswpallgc: {  /* sweep "regular" objects */
1075       return sweepstep(L, g, GCSswpfinobj, &g->finobj);
1076     }
1077     case GCSswpfinobj: {  /* sweep objects with finalizers */
1078       return sweepstep(L, g, GCSswptobefnz, &g->tobefnz);
1079     }
1080     case GCSswptobefnz: {  /* sweep objects to be finalized */
1081       return sweepstep(L, g, GCSswpend, NULL);
1082     }
1083     case GCSswpend: {  /* finish sweeps */
1084       makewhite(g, g->mainthread);  /* sweep main thread */
1085       checkSizes(L, g);
1086       g->gcstate = GCScallfin;
1087       return 0;
1088     }
1089     case GCScallfin: {  /* call remaining finalizers */
1090       if (g->tobefnz && g->gckind != KGC_EMERGENCY) {
1091         int n = runafewfinalizers(L);
1092         return (n * GCFINALIZECOST);
1093       }
1094       else {  /* emergency mode or no more finalizers */
1095         g->gcstate = GCSpause;  /* finish collection */
1096         return 0;
1097       }
1098     }
1099     default: lua_assert(0); return 0;
1100   }
1101 }
1102 
1103 
1104 /*
1105 ** advances the garbage collector until it reaches a state allowed
1106 ** by 'statemask'
1107 */
1108 void luaC_runtilstate (lua_State *L, int statesmask) {
1109   global_State *g = G(L);
1110   while (!testbit(statesmask, g->gcstate))
1111     singlestep(L);
1112 }
1113 
1114 
1115 /*
1116 ** get GC debt and convert it from Kb to 'work units' (avoid zero debt
1117 ** and overflows)
1118 */
1119 static l_mem getdebt (global_State *g) {
1120   l_mem debt = g->GCdebt;
1121   int stepmul = g->gcstepmul;
1122   if (debt <= 0) return 0;  /* minimal debt */
1123   else {
1124     debt = (debt / STEPMULADJ) + 1;
1125     debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM;
1126     return debt;
1127   }
1128 }
1129 
1130 /*
1131 ** performs a basic GC step when collector is running
1132 */
1133 void luaC_step (lua_State *L) {
1134   global_State *g = G(L);
1135   l_mem debt = getdebt(g);  /* GC deficit (be paid now) */
1136   if (!g->gcrunning) {  /* not running? */
1137     luaE_setdebt(g, -GCSTEPSIZE * 10);  /* avoid being called too often */
1138     return;
1139   }
1140   do {  /* repeat until pause or enough "credit" (negative debt) */
1141     lu_mem work = singlestep(L);  /* perform one single step */
1142     debt -= work;
1143   } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause);
1144   if (g->gcstate == GCSpause)
1145     setpause(g);  /* pause until next cycle */
1146   else {
1147     debt = (debt / g->gcstepmul) * STEPMULADJ;  /* convert 'work units' to Kb */
1148     luaE_setdebt(g, debt);
1149     runafewfinalizers(L);
1150   }
1151 }
1152 
1153 
1154 /*
1155 ** Performs a full GC cycle; if 'isemergency', set a flag to avoid
1156 ** some operations which could change the interpreter state in some
1157 ** unexpected ways (running finalizers and shrinking some structures).
1158 ** Before running the collection, check 'keepinvariant'; if it is true,
1159 ** there may be some objects marked as black, so the collector has
1160 ** to sweep all objects to turn them back to white (as white has not
1161 ** changed, nothing will be collected).
1162 */
1163 void luaC_fullgc (lua_State *L, int isemergency) {
1164   global_State *g = G(L);
1165   lua_assert(g->gckind == KGC_NORMAL);
1166   if (isemergency) g->gckind = KGC_EMERGENCY;  /* set flag */
1167   if (keepinvariant(g)) {  /* black objects? */
1168     entersweep(L); /* sweep everything to turn them back to white */
1169   }
1170   /* finish any pending sweep phase to start a new cycle */
1171   luaC_runtilstate(L, bitmask(GCSpause));
1172   luaC_runtilstate(L, ~bitmask(GCSpause));  /* start new collection */
1173   luaC_runtilstate(L, bitmask(GCScallfin));  /* run up to finalizers */
1174   /* estimate must be correct after a full GC cycle */
1175   lua_assert(g->GCestimate == gettotalbytes(g));
1176   luaC_runtilstate(L, bitmask(GCSpause));  /* finish collection */
1177   g->gckind = KGC_NORMAL;
1178   setpause(g);
1179 }
1180 
1181 /* }====================================================== */
1182 
1183 
1184