lgc.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*
  2. ** $Id: lgc.c,v 1.80 2001/01/26 13:18:00 roberto Exp roberto $
  3. ** Garbage Collector
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include "lua.h"
  7. #include "ldo.h"
  8. #include "lfunc.h"
  9. #include "lgc.h"
  10. #include "lmem.h"
  11. #include "lobject.h"
  12. #include "lstate.h"
  13. #include "lstring.h"
  14. #include "ltable.h"
  15. #include "ltm.h"
  16. typedef struct GCState {
  17. Hash *tmark; /* list of marked tables to be visited */
  18. Closure *cmark; /* list of marked closures to be visited */
  19. } GCState;
  20. static void markobject (GCState *st, TObject *o);
  21. /* mark a string; marks larger than 1 cannot be changed */
  22. #define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;}
  23. static void protomark (Proto *f) {
  24. if (!f->marked) {
  25. int i;
  26. f->marked = 1;
  27. strmark(f->source);
  28. for (i=0; i<f->sizekstr; i++)
  29. strmark(f->kstr[i]);
  30. for (i=0; i<f->sizekproto; i++)
  31. protomark(f->kproto[i]);
  32. for (i=0; i<f->sizelocvars; i++) /* mark local-variable names */
  33. strmark(f->locvars[i].varname);
  34. }
  35. }
  36. static void markclosure (GCState *st, Closure *cl) {
  37. if (!ismarked(cl)) {
  38. if (!cl->isC)
  39. protomark(cl->f.l);
  40. cl->mark = st->cmark; /* chain it for later traversal */
  41. st->cmark = cl;
  42. }
  43. }
  44. static void marktable (GCState *st, Hash *h) {
  45. if (!ismarked(h)) {
  46. h->mark = st->tmark; /* chain it in list of marked */
  47. st->tmark = h;
  48. }
  49. }
  50. static void markobject (GCState *st, TObject *o) {
  51. switch (ttype(o)) {
  52. case LUA_TUSERDATA: case LUA_TSTRING:
  53. strmark(tsvalue(o));
  54. break;
  55. case LUA_TMARK:
  56. markclosure(st, infovalue(o)->func);
  57. break;
  58. case LUA_TFUNCTION:
  59. markclosure(st, clvalue(o));
  60. break;
  61. case LUA_TTABLE: {
  62. marktable(st, hvalue(o));
  63. break;
  64. }
  65. default: break; /* numbers, etc */
  66. }
  67. }
  68. static void markstacks (lua_State *L, GCState *st) {
  69. lua_State *L1 = L;
  70. do { /* for each thread */
  71. StkId o;
  72. marktable(st, L1->gt); /* mark table of globals */
  73. for (o=L1->stack; o<L1->top; o++)
  74. markobject(st, o);
  75. lua_assert(L->previous->next == L && L->next->previous == L);
  76. L1 = L1->next;
  77. } while (L1 != L);
  78. }
  79. static void marklock (global_State *G, GCState *st) {
  80. int i;
  81. for (i=0; i<G->nref; i++) {
  82. if (G->refArray[i].st == LOCK)
  83. markobject(st, &G->refArray[i].o);
  84. }
  85. }
  86. static void marktagmethods (global_State *G, GCState *st) {
  87. int t;
  88. for (t=0; t<G->ntag; t++) {
  89. struct TM *tm = &G->TMtable[t];
  90. int e;
  91. if (tm->name) strmark(tm->name);
  92. for (e=0; e<TM_N; e++) {
  93. Closure *cl = tm->method[e];
  94. if (cl) markclosure(st, cl);
  95. }
  96. }
  97. }
  98. static void traverseclosure (GCState *st, Closure *f) {
  99. int i;
  100. for (i=0; i<f->nupvalues; i++) /* mark its upvalues */
  101. markobject(st, &f->upvalue[i]);
  102. }
  103. static void traversetable (GCState *st, Hash *h) {
  104. int i;
  105. for (i=0; i<h->size; i++) {
  106. Node *n = node(h, i);
  107. if (ttype(val(n)) == LUA_TNIL) {
  108. if (ttype(key(n)) != LUA_TNIL)
  109. sethvalue(key(n), NULL); /* dead key; remove it */
  110. }
  111. else {
  112. markobject(st, &n->key);
  113. markobject(st, &n->val);
  114. }
  115. }
  116. }
  117. static void markall (lua_State *L) {
  118. GCState st;
  119. st.cmark = NULL;
  120. st.tmark = NULL;
  121. marktagmethods(G(L), &st); /* mark tag methods */
  122. markstacks(L, &st); /* mark all stacks */
  123. marklock(G(L), &st); /* mark locked objects */
  124. marktable(&st, G(L)->type2tag);
  125. for (;;) { /* mark tables and closures */
  126. if (st.cmark) {
  127. Closure *f = st.cmark; /* get first closure from list */
  128. st.cmark = f->mark; /* remove it from list */
  129. traverseclosure(&st, f);
  130. }
  131. else if (st.tmark) {
  132. Hash *h = st.tmark; /* get first table from list */
  133. st.tmark = h->mark; /* remove it from list */
  134. traversetable(&st, h);
  135. }
  136. else break; /* nothing else to mark */
  137. }
  138. }
  139. static int hasmark (const TObject *o) {
  140. /* valid only for locked objects */
  141. switch (ttype(o)) {
  142. case LUA_TSTRING: case LUA_TUSERDATA:
  143. return tsvalue(o)->marked;
  144. case LUA_TTABLE:
  145. return ismarked(hvalue(o));
  146. case LUA_TFUNCTION:
  147. return ismarked(clvalue(o));
  148. default: /* number */
  149. return 1;
  150. }
  151. }
  152. /* macro for internal debugging; check if a link of free refs is valid */
  153. #define VALIDLINK(L, st,n) (NONEXT <= (st) && (st) < (n))
  154. static void invalidaterefs (global_State *G) {
  155. int n = G->nref;
  156. int i;
  157. for (i=0; i<n; i++) {
  158. struct Ref *r = &G->refArray[i];
  159. if (r->st == HOLD && !hasmark(&r->o))
  160. r->st = COLLECTED;
  161. lua_assert((r->st == LOCK && hasmark(&r->o)) ||
  162. (r->st == HOLD && hasmark(&r->o)) ||
  163. r->st == COLLECTED ||
  164. r->st == NONEXT ||
  165. (r->st < n && VALIDLINK(L, G->refArray[r->st].st, n)));
  166. }
  167. lua_assert(VALIDLINK(L, G->refFree, n));
  168. }
  169. static void collectproto (lua_State *L) {
  170. Proto **p = &G(L)->rootproto;
  171. Proto *next;
  172. while ((next = *p) != NULL) {
  173. if (next->marked) {
  174. next->marked = 0;
  175. p = &next->next;
  176. }
  177. else {
  178. *p = next->next;
  179. luaF_freeproto(L, next);
  180. }
  181. }
  182. }
  183. static void collectclosure (lua_State *L) {
  184. Closure **p = &G(L)->rootcl;
  185. Closure *next;
  186. while ((next = *p) != NULL) {
  187. if (ismarked(next)) {
  188. next->mark = next; /* unmark */
  189. p = &next->next;
  190. }
  191. else {
  192. *p = next->next;
  193. luaF_freeclosure(L, next);
  194. }
  195. }
  196. }
  197. static void collecttable (lua_State *L) {
  198. Hash **p = &G(L)->roottable;
  199. Hash *next;
  200. while ((next = *p) != NULL) {
  201. if (ismarked(next)) {
  202. next->mark = next; /* unmark */
  203. p = &next->next;
  204. }
  205. else {
  206. *p = next->next;
  207. luaH_free(L, next);
  208. }
  209. }
  210. }
  211. static void checktab (lua_State *L, stringtable *tb) {
  212. if (tb->nuse < (luint32)(tb->size/4) && tb->size > MINPOWER2)
  213. luaS_resize(L, tb, tb->size/2); /* table is too big */
  214. }
  215. static void collectstrings (lua_State *L, int all) {
  216. int i;
  217. for (i=0; i<G(L)->strt.size; i++) { /* for each list */
  218. TString **p = &G(L)->strt.hash[i];
  219. TString *next;
  220. while ((next = *p) != NULL) {
  221. if (next->marked && !all) { /* preserve? */
  222. if (next->marked < FIXMARK) /* does not change FIXMARKs */
  223. next->marked = 0;
  224. p = &next->nexthash;
  225. }
  226. else { /* collect */
  227. *p = next->nexthash;
  228. G(L)->strt.nuse--;
  229. luaM_free(L, next, sizestring(next->len));
  230. }
  231. }
  232. }
  233. checktab(L, &G(L)->strt);
  234. }
  235. static void collectudata (lua_State *L, int all) {
  236. int i;
  237. for (i=0; i<G(L)->udt.size; i++) { /* for each list */
  238. TString **p = &G(L)->udt.hash[i];
  239. TString *next;
  240. while ((next = *p) != NULL) {
  241. lua_assert(next->marked <= 1);
  242. if (next->marked && !all) { /* preserve? */
  243. next->marked = 0;
  244. p = &next->nexthash;
  245. }
  246. else { /* collect */
  247. int tag = next->u.d.tag;
  248. *p = next->nexthash;
  249. next->nexthash = G(L)->TMtable[tag].collected; /* chain udata */
  250. G(L)->TMtable[tag].collected = next;
  251. G(L)->udt.nuse--;
  252. }
  253. }
  254. }
  255. checktab(L, &G(L)->udt);
  256. }
  257. #define MINBUFFER 256
  258. static void checkMbuffer (lua_State *L) {
  259. if (G(L)->Mbuffsize > MINBUFFER*2) { /* is buffer too big? */
  260. size_t newsize = G(L)->Mbuffsize/2; /* still larger than MINBUFFER */
  261. luaM_reallocvector(L, G(L)->Mbuffer, G(L)->Mbuffsize, newsize, char);
  262. G(L)->Mbuffsize = newsize;
  263. }
  264. }
  265. static void callgcTM (lua_State *L, const TObject *obj) {
  266. Closure *tm = luaT_gettmbyObj(G(L), obj, TM_GC);
  267. if (tm != NULL) {
  268. int oldah = L->allowhooks;
  269. L->allowhooks = 0; /* stop debug hooks during GC tag methods */
  270. luaD_checkstack(L, 2);
  271. setclvalue(L->top, tm);
  272. setobj(L->top+1, obj);
  273. L->top += 2;
  274. luaD_call(L, L->top-2, 0);
  275. L->allowhooks = oldah; /* restore hooks */
  276. }
  277. }
  278. static void callgcTMudata (lua_State *L) {
  279. int tag;
  280. G(L)->GCthreshold = 2*G(L)->nblocks; /* avoid GC during tag methods */
  281. for (tag=G(L)->ntag-1; tag>=0; tag--) { /* for each tag (in reverse order) */
  282. TString *udata;
  283. while ((udata = G(L)->TMtable[tag].collected) != NULL) {
  284. TObject obj;
  285. G(L)->TMtable[tag].collected = udata->nexthash; /* remove it from list */
  286. setuvalue(&obj, udata);
  287. callgcTM(L, &obj);
  288. luaM_free(L, udata, sizeudata(udata->len));
  289. }
  290. }
  291. }
  292. void luaC_collect (lua_State *L, int all) {
  293. collectudata(L, all);
  294. callgcTMudata(L);
  295. collectstrings(L, all);
  296. collecttable(L);
  297. collectproto(L);
  298. collectclosure(L);
  299. }
  300. static void luaC_collectgarbage (lua_State *L) {
  301. markall(L);
  302. invalidaterefs(G(L)); /* check unlocked references */
  303. luaC_collect(L, 0);
  304. checkMbuffer(L);
  305. G(L)->GCthreshold = 2*G(L)->nblocks; /* set new threshold */
  306. callgcTM(L, &luaO_nilobject);
  307. }
  308. void luaC_checkGC (lua_State *L) {
  309. if (G(L)->nblocks >= G(L)->GCthreshold)
  310. luaC_collectgarbage(L);
  311. }