diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-12-10 10:13:36 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-12-10 10:13:36 -0200 |
commit | 47fc57a2529c83376883f36954082cfe80ae588f (patch) | |
tree | c2e57e2f9f7d78279144bfd9cbd04a3b1b131f12 /lgc.c | |
parent | 4d5fe1f54bc00850f77a7c42f9e95d0ff3f1ab5b (diff) | |
download | lua-47fc57a2529c83376883f36954082cfe80ae588f.tar.gz lua-47fc57a2529c83376883f36954082cfe80ae588f.tar.bz2 lua-47fc57a2529c83376883f36954082cfe80ae588f.zip |
`TObject' renamed to `TValue' + other name changes and better assertions
for incremental garbage collection
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 104 |
1 files changed, 52 insertions, 52 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.186 2003/12/04 18:52:23 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.187 2003/12/09 16:56:11 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -22,7 +22,7 @@ | |||
22 | #include "ltm.h" | 22 | #include "ltm.h" |
23 | 23 | ||
24 | 24 | ||
25 | #define GCSTEPSIZE (20*sizeof(TObject)) | 25 | #define GCSTEPSIZE (20*sizeof(TValue)) |
26 | 26 | ||
27 | 27 | ||
28 | #define gray2black(x) setbit((x)->gch.marked, BLACKBIT) | 28 | #define gray2black(x) setbit((x)->gch.marked, BLACKBIT) |
@@ -39,8 +39,8 @@ | |||
39 | #define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) | 39 | #define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) |
40 | 40 | ||
41 | 41 | ||
42 | #define isfinalized(u) testbit((u)->uv.marked, FINALIZEDBIT) | 42 | #define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) |
43 | #define markfinalized(u) setbit((u)->uv.marked, FINALIZEDBIT) | 43 | #define markfinalized(u) setbit((u)->marked, FINALIZEDBIT) |
44 | 44 | ||
45 | 45 | ||
46 | #define KEYWEAK bitmask(KEYWEAKBIT) | 46 | #define KEYWEAK bitmask(KEYWEAKBIT) |
@@ -55,8 +55,8 @@ | |||
55 | if (iscollectable(o) && iswhite(gcvalue(o)) && (c)) \ | 55 | if (iscollectable(o) && iswhite(gcvalue(o)) && (c)) \ |
56 | reallymarkobject(g,gcvalue(o)); } | 56 | reallymarkobject(g,gcvalue(o)); } |
57 | 57 | ||
58 | #define markobject(g,t) { if (iswhite(valtogco(t))) \ | 58 | #define markobject(g,t) { if (iswhite(obj2gco(t))) \ |
59 | reallymarkobject(g, valtogco(t)); } | 59 | reallymarkobject(g, obj2gco(t)); } |
60 | 60 | ||
61 | 61 | ||
62 | 62 | ||
@@ -66,34 +66,34 @@ | |||
66 | static size_t objsize (GCObject *o) { | 66 | static size_t objsize (GCObject *o) { |
67 | switch (o->gch.tt) { | 67 | switch (o->gch.tt) { |
68 | case LUA_TSTRING: { | 68 | case LUA_TSTRING: { |
69 | TString *ts = gcotots(o); | 69 | TString *ts = rawgco2ts(o); |
70 | return sizestring(ts->tsv.len); | 70 | return sizestring(ts->tsv.len); |
71 | } | 71 | } |
72 | case LUA_TUSERDATA: { | 72 | case LUA_TUSERDATA: { |
73 | Udata *u = gcotou(o); | 73 | Udata *u = rawgco2u(o); |
74 | return sizeudata(u->uv.len); | 74 | return sizeudata(u->uv.len); |
75 | } | 75 | } |
76 | case LUA_TTABLE: { | 76 | case LUA_TTABLE: { |
77 | Table *h = gcotoh(o); | 77 | Table *h = gco2h(o); |
78 | return sizeof(Table) + sizeof(TObject) * h->sizearray + | 78 | return sizeof(Table) + sizeof(TValue) * h->sizearray + |
79 | sizeof(Node) * sizenode(h); | 79 | sizeof(Node) * sizenode(h); |
80 | } | 80 | } |
81 | case LUA_TUPVAL: | 81 | case LUA_TUPVAL: |
82 | return sizeof(UpVal); | 82 | return sizeof(UpVal); |
83 | case LUA_TFUNCTION: { | 83 | case LUA_TFUNCTION: { |
84 | Closure *cl = gcotocl(o); | 84 | Closure *cl = gco2cl(o); |
85 | return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : | 85 | return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : |
86 | sizeLclosure(cl->l.nupvalues); | 86 | sizeLclosure(cl->l.nupvalues); |
87 | } | 87 | } |
88 | case LUA_TTHREAD: { | 88 | case LUA_TTHREAD: { |
89 | lua_State *th = gcototh(o); | 89 | lua_State *th = gco2th(o); |
90 | return sizeof(lua_State) + sizeof(TObject) * th->stacksize + | 90 | return sizeof(lua_State) + sizeof(TValue) * th->stacksize + |
91 | sizeof(CallInfo) * th->size_ci; | 91 | sizeof(CallInfo) * th->size_ci; |
92 | } | 92 | } |
93 | case LUA_TPROTO: { | 93 | case LUA_TPROTO: { |
94 | Proto *p = gcotop(o); | 94 | Proto *p = gco2p(o); |
95 | return sizeof(Proto) + sizeof(Instruction) * p->sizecode + | 95 | return sizeof(Proto) + sizeof(Instruction) * p->sizecode + |
96 | sizeof(Proto *) * p->sizep + sizeof(TObject) * p->sizek + | 96 | sizeof(Proto *) * p->sizep + sizeof(TValue) * p->sizek + |
97 | sizeof(int) * p->sizelineinfo + sizeof(LocVar) * p->sizelocvars + | 97 | sizeof(int) * p->sizelineinfo + sizeof(LocVar) * p->sizelocvars + |
98 | sizeof(TString *) * p->sizeupvalues; | 98 | sizeof(TString *) * p->sizeupvalues; |
99 | } | 99 | } |
@@ -112,29 +112,29 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
112 | return; | 112 | return; |
113 | } | 113 | } |
114 | case LUA_TUSERDATA: { | 114 | case LUA_TUSERDATA: { |
115 | Table *mt = gcotou(o)->uv.metatable; | 115 | Table *mt = gco2u(o)->metatable; |
116 | gray2black(o); /* udata are never gray */ | 116 | gray2black(o); /* udata are never gray */ |
117 | if (mt) markobject(g, mt); | 117 | if (mt) markobject(g, mt); |
118 | return; | 118 | return; |
119 | } | 119 | } |
120 | case LUA_TFUNCTION: { | 120 | case LUA_TFUNCTION: { |
121 | gcotocl(o)->c.gclist = g->gray; | 121 | gco2cl(o)->c.gclist = g->gray; |
122 | break; | 122 | break; |
123 | } | 123 | } |
124 | case LUA_TTABLE: { | 124 | case LUA_TTABLE: { |
125 | gcotoh(o)->gclist = g->gray; | 125 | gco2h(o)->gclist = g->gray; |
126 | break; | 126 | break; |
127 | } | 127 | } |
128 | case LUA_TTHREAD: { | 128 | case LUA_TTHREAD: { |
129 | gcototh(o)->gclist = g->gray; | 129 | gco2th(o)->gclist = g->gray; |
130 | break; | 130 | break; |
131 | } | 131 | } |
132 | case LUA_TPROTO: { | 132 | case LUA_TPROTO: { |
133 | gcotop(o)->gclist = g->gray; | 133 | gco2p(o)->gclist = g->gray; |
134 | break; | 134 | break; |
135 | } | 135 | } |
136 | case LUA_TUPVAL: { | 136 | case LUA_TUPVAL: { |
137 | gcotouv(o)->gclist = g->gray; | 137 | gco2uv(o)->gclist = g->gray; |
138 | break; | 138 | break; |
139 | } | 139 | } |
140 | default: lua_assert(0); | 140 | default: lua_assert(0); |
@@ -161,15 +161,15 @@ size_t luaC_separateudata (lua_State *L) { | |||
161 | GCObject **lastcollected = &collected; | 161 | GCObject **lastcollected = &collected; |
162 | while ((curr = *p) != NULL) { | 162 | while ((curr = *p) != NULL) { |
163 | lua_assert(curr->gch.tt == LUA_TUSERDATA); | 163 | lua_assert(curr->gch.tt == LUA_TUSERDATA); |
164 | if (!iswhite(curr) || isfinalized(gcotou(curr))) | 164 | if (!iswhite(curr) || isfinalized(gco2u(curr))) |
165 | p = &curr->gch.next; /* don't bother with them */ | 165 | p = &curr->gch.next; /* don't bother with them */ |
166 | else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) { | 166 | else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { |
167 | markfinalized(gcotou(curr)); /* don't need finalization */ | 167 | markfinalized(gco2u(curr)); /* don't need finalization */ |
168 | p = &curr->gch.next; | 168 | p = &curr->gch.next; |
169 | } | 169 | } |
170 | else { /* must call its gc method */ | 170 | else { /* must call its gc method */ |
171 | deadmem += sizeudata(gcotou(curr)->uv.len); | 171 | deadmem += sizeudata(gco2u(curr)->len); |
172 | markfinalized(gcotou(curr)); | 172 | markfinalized(gco2u(curr)); |
173 | *p = curr->gch.next; | 173 | *p = curr->gch.next; |
174 | curr->gch.next = NULL; /* link `curr' at the end of `collected' list */ | 174 | curr->gch.next = NULL; /* link `curr' at the end of `collected' list */ |
175 | *lastcollected = curr; | 175 | *lastcollected = curr; |
@@ -187,7 +187,7 @@ static void traversetable (global_State *g, Table *h) { | |||
187 | int i; | 187 | int i; |
188 | int weakkey = 0; | 188 | int weakkey = 0; |
189 | int weakvalue = 0; | 189 | int weakvalue = 0; |
190 | const TObject *mode; | 190 | const TValue *mode; |
191 | if (h->metatable) | 191 | if (h->metatable) |
192 | markobject(g, h->metatable); | 192 | markobject(g, h->metatable); |
193 | lua_assert(h->lsizenode || h->node == g->dummynode); | 193 | lua_assert(h->lsizenode || h->node == g->dummynode); |
@@ -200,7 +200,7 @@ static void traversetable (global_State *g, Table *h) { | |||
200 | h->marked |= cast(lu_byte, (weakkey << KEYWEAKBIT) | | 200 | h->marked |= cast(lu_byte, (weakkey << KEYWEAKBIT) | |
201 | (weakvalue << VALUEWEAKBIT)); | 201 | (weakvalue << VALUEWEAKBIT)); |
202 | h->gclist = g->weak; /* must be cleared after GC, ... */ | 202 | h->gclist = g->weak; /* must be cleared after GC, ... */ |
203 | g->weak = valtogco(h); /* ... so put in the appropriate list */ | 203 | g->weak = obj2gco(h); /* ... so put in the appropriate list */ |
204 | } | 204 | } |
205 | } | 205 | } |
206 | if (weakkey && weakvalue) return; | 206 | if (weakkey && weakvalue) return; |
@@ -230,7 +230,7 @@ static void traverseproto (global_State *g, Proto *f) { | |||
230 | if (f->source) stringmark(f->source); | 230 | if (f->source) stringmark(f->source); |
231 | for (i=0; i<f->sizek; i++) { /* mark literal strings */ | 231 | for (i=0; i<f->sizek; i++) { /* mark literal strings */ |
232 | if (ttisstring(f->k+i)) | 232 | if (ttisstring(f->k+i)) |
233 | stringmark(tsvalue(f->k+i)); | 233 | stringmark(rawtsvalue(f->k+i)); |
234 | } | 234 | } |
235 | for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */ | 235 | for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */ |
236 | if (f->upvalues[i]) | 236 | if (f->upvalues[i]) |
@@ -306,19 +306,19 @@ static l_mem propagatemarks (global_State *g, l_mem lim) { | |||
306 | gray2black(o); | 306 | gray2black(o); |
307 | switch (o->gch.tt) { | 307 | switch (o->gch.tt) { |
308 | case LUA_TTABLE: { | 308 | case LUA_TTABLE: { |
309 | Table *h = gcotoh(o); | 309 | Table *h = gco2h(o); |
310 | g->gray = h->gclist; | 310 | g->gray = h->gclist; |
311 | traversetable(g, h); | 311 | traversetable(g, h); |
312 | break; | 312 | break; |
313 | } | 313 | } |
314 | case LUA_TFUNCTION: { | 314 | case LUA_TFUNCTION: { |
315 | Closure *cl = gcotocl(o); | 315 | Closure *cl = gco2cl(o); |
316 | g->gray = cl->c.gclist; | 316 | g->gray = cl->c.gclist; |
317 | traverseclosure(g, cl); | 317 | traverseclosure(g, cl); |
318 | break; | 318 | break; |
319 | } | 319 | } |
320 | case LUA_TTHREAD: { | 320 | case LUA_TTHREAD: { |
321 | lua_State *th = gcototh(o); | 321 | lua_State *th = gco2th(o); |
322 | g->gray = th->gclist; | 322 | g->gray = th->gclist; |
323 | th->gclist = g->grayagain; | 323 | th->gclist = g->grayagain; |
324 | g->grayagain = o; | 324 | g->grayagain = o; |
@@ -327,13 +327,13 @@ static l_mem propagatemarks (global_State *g, l_mem lim) { | |||
327 | break; | 327 | break; |
328 | } | 328 | } |
329 | case LUA_TPROTO: { | 329 | case LUA_TPROTO: { |
330 | Proto *p = gcotop(o); | 330 | Proto *p = gco2p(o); |
331 | g->gray = p->gclist; | 331 | g->gray = p->gclist; |
332 | traverseproto(g, p); | 332 | traverseproto(g, p); |
333 | break; | 333 | break; |
334 | } | 334 | } |
335 | case LUA_TUPVAL: { | 335 | case LUA_TUPVAL: { |
336 | UpVal *uv = gcotouv(o); | 336 | UpVal *uv = gco2uv(o); |
337 | g->gray = uv->gclist; | 337 | g->gray = uv->gclist; |
338 | if (uv->v != &uv->value) { /* open? */ | 338 | if (uv->v != &uv->value) { /* open? */ |
339 | uv->gclist = g->grayagain; | 339 | uv->gclist = g->grayagain; |
@@ -360,10 +360,10 @@ static l_mem propagatemarks (global_State *g, l_mem lim) { | |||
360 | ** other objects: if really collected, cannot keep them; for userdata | 360 | ** other objects: if really collected, cannot keep them; for userdata |
361 | ** being finalized, keep them in keys, but not in values | 361 | ** being finalized, keep them in keys, but not in values |
362 | */ | 362 | */ |
363 | static int iscleared (const TObject *o, int iskey) { | 363 | static int iscleared (const TValue *o, int iskey) { |
364 | if (!iscollectable(o)) return 0; | 364 | if (!iscollectable(o)) return 0; |
365 | if (ttisstring(o)) { | 365 | if (ttisstring(o)) { |
366 | stringmark(tsvalue(o)); /* strings are `values', so are never weak */ | 366 | stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ |
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
369 | return iswhite(gcvalue(o)) || | 369 | return iswhite(gcvalue(o)) || |
@@ -383,13 +383,13 @@ static void removekey (Node *n) { | |||
383 | */ | 383 | */ |
384 | static void cleartable (GCObject *l) { | 384 | static void cleartable (GCObject *l) { |
385 | while (l) { | 385 | while (l) { |
386 | Table *h = gcotoh(l); | 386 | Table *h = gco2h(l); |
387 | int i = h->sizearray; | 387 | int i = h->sizearray; |
388 | lua_assert(testbit(h->marked, VALUEWEAKBIT) || | 388 | lua_assert(testbit(h->marked, VALUEWEAKBIT) || |
389 | testbit(h->marked, KEYWEAKBIT)); | 389 | testbit(h->marked, KEYWEAKBIT)); |
390 | if (testbit(h->marked, VALUEWEAKBIT)) { | 390 | if (testbit(h->marked, VALUEWEAKBIT)) { |
391 | while (i--) { | 391 | while (i--) { |
392 | TObject *o = &h->array[i]; | 392 | TValue *o = &h->array[i]; |
393 | if (iscleared(o, 0)) /* value was collected? */ | 393 | if (iscleared(o, 0)) /* value was collected? */ |
394 | setnilvalue(o); /* remove value */ | 394 | setnilvalue(o); /* remove value */ |
395 | } | 395 | } |
@@ -408,21 +408,21 @@ static void cleartable (GCObject *l) { | |||
408 | 408 | ||
409 | static void freeobj (lua_State *L, GCObject *o) { | 409 | static void freeobj (lua_State *L, GCObject *o) { |
410 | switch (o->gch.tt) { | 410 | switch (o->gch.tt) { |
411 | case LUA_TPROTO: luaF_freeproto(L, gcotop(o)); break; | 411 | case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; |
412 | case LUA_TFUNCTION: luaF_freeclosure(L, gcotocl(o)); break; | 412 | case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; |
413 | case LUA_TUPVAL: luaM_freelem(L, gcotouv(o)); break; | 413 | case LUA_TUPVAL: luaM_freelem(L, gco2uv(o)); break; |
414 | case LUA_TTABLE: luaH_free(L, gcotoh(o)); break; | 414 | case LUA_TTABLE: luaH_free(L, gco2h(o)); break; |
415 | case LUA_TTHREAD: { | 415 | case LUA_TTHREAD: { |
416 | lua_assert(gcototh(o) != L && gcototh(o) != G(L)->mainthread); | 416 | lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); |
417 | luaE_freethread(L, gcototh(o)); | 417 | luaE_freethread(L, gco2th(o)); |
418 | break; | 418 | break; |
419 | } | 419 | } |
420 | case LUA_TSTRING: { | 420 | case LUA_TSTRING: { |
421 | luaM_free(L, o, sizestring(gcotots(o)->tsv.len)); | 421 | luaM_free(L, o, sizestring(gco2ts(o)->len)); |
422 | break; | 422 | break; |
423 | } | 423 | } |
424 | case LUA_TUSERDATA: { | 424 | case LUA_TUSERDATA: { |
425 | luaM_free(L, o, sizeudata(gcotou(o)->uv.len)); | 425 | luaM_free(L, o, sizeudata(gco2u(o)->len)); |
426 | break; | 426 | break; |
427 | } | 427 | } |
428 | default: lua_assert(0); | 428 | default: lua_assert(0); |
@@ -463,7 +463,7 @@ static l_mem sweepstrings (lua_State *L, int all, l_mem lim) { | |||
463 | GCObject **p = &G(L)->strt.hash[i]; | 463 | GCObject **p = &G(L)->strt.hash[i]; |
464 | while ((curr = *p) != NULL) { | 464 | while ((curr = *p) != NULL) { |
465 | int mark = curr->gch.marked; | 465 | int mark = curr->gch.marked; |
466 | lu_mem size = sizestring(gcotots(curr)->tsv.len); | 466 | lu_mem size = sizestring(gco2ts(curr)->len); |
467 | if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) { | 467 | if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) { |
468 | makewhite(g, curr); | 468 | makewhite(g, curr); |
469 | lua_assert(iswhite(curr) && !isdead(g, curr)); | 469 | lua_assert(iswhite(curr) && !isdead(g, curr)); |
@@ -503,8 +503,8 @@ static void GCTM (lua_State *L) { | |||
503 | g->gcstate = GCSroot; /* will restart GC */ | 503 | g->gcstate = GCSroot; /* will restart GC */ |
504 | else { | 504 | else { |
505 | GCObject *o = g->tmudata; | 505 | GCObject *o = g->tmudata; |
506 | Udata *udata = gcotou(o); | 506 | Udata *udata = rawgco2u(o); |
507 | const TObject *tm; | 507 | const TValue *tm; |
508 | g->tmudata = udata->uv.next; /* remove udata from `tmudata' */ | 508 | g->tmudata = udata->uv.next; /* remove udata from `tmudata' */ |
509 | udata->uv.next = g->firstudata->uv.next; /* return it to `root' list */ | 509 | udata->uv.next = g->firstudata->uv.next; /* return it to `root' list */ |
510 | g->firstudata->uv.next = o; | 510 | g->firstudata->uv.next = o; |
@@ -513,8 +513,8 @@ static void GCTM (lua_State *L) { | |||
513 | if (tm != NULL) { | 513 | if (tm != NULL) { |
514 | lu_byte oldah = L->allowhook; | 514 | lu_byte oldah = L->allowhook; |
515 | L->allowhook = 0; /* stop debug hooks during GC tag method */ | 515 | L->allowhook = 0; /* stop debug hooks during GC tag method */ |
516 | setobj2s(L->top, tm); | 516 | setobj2s(L, L->top, tm); |
517 | setuvalue(L->top+1, udata); | 517 | setuvalue(L, L->top+1, udata); |
518 | L->top += 2; | 518 | L->top += 2; |
519 | luaD_call(L, L->top - 2, 0); | 519 | luaD_call(L, L->top - 2, 0); |
520 | L->allowhook = oldah; /* restore hooks */ | 520 | L->allowhook = oldah; /* restore hooks */ |
@@ -545,7 +545,7 @@ static void markroot (lua_State *L) { | |||
545 | global_State *g = G(L); | 545 | global_State *g = G(L); |
546 | lua_assert(g->gray == NULL); | 546 | lua_assert(g->gray == NULL); |
547 | g->weak = NULL; | 547 | g->weak = NULL; |
548 | makewhite(g, valtogco(g->mainthread)); | 548 | makewhite(g, obj2gco(g->mainthread)); |
549 | markobject(g, g->mainthread); | 549 | markobject(g, g->mainthread); |
550 | markvalue(g, registry(L)); | 550 | markvalue(g, registry(L)); |
551 | markobject(g, L); /* mark running thread */ | 551 | markobject(g, L); /* mark running thread */ |