aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2004-03-15 18:04:33 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2004-03-15 18:04:33 -0300
commita4e1230f95223f2106cf0e118426ba91f1017d89 (patch)
treebc6b67ae14a3381498a203e715d48e8d059b6fef
parent9804467eeb9836bc147adffee411b21e6257da6b (diff)
downloadlua-a4e1230f95223f2106cf0e118426ba91f1017d89.tar.gz
lua-a4e1230f95223f2106cf0e118426ba91f1017d89.tar.bz2
lua-a4e1230f95223f2106cf0e118426ba91f1017d89.zip
better way to control open upvalues
-rw-r--r--lfunc.c22
-rw-r--r--lgc.c236
-rw-r--r--lgc.h5
-rw-r--r--lobject.h3
-rw-r--r--lstate.c27
5 files changed, 159 insertions, 134 deletions
diff --git a/lfunc.c b/lfunc.c
index 36bf3f32..04dfca60 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lfunc.c,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $ 2** $Id: lfunc.c,v 2.2 2004/02/16 19:09:52 roberto Exp roberto $
3** Auxiliary functions to manipulate prototypes and closures 3** Auxiliary functions to manipulate prototypes and closures
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -34,6 +34,7 @@ Closure *luaF_newLclosure (lua_State *L, int nelems, TValue *e) {
34 c->l.isC = 0; 34 c->l.isC = 0;
35 c->l.g = *e; 35 c->l.g = *e;
36 c->l.nupvalues = cast(lu_byte, nelems); 36 c->l.nupvalues = cast(lu_byte, nelems);
37 while (nelems--) c->l.upvals[nelems] = NULL;
37 return c; 38 return c;
38} 39}
39 40
@@ -67,17 +68,18 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
67 68
68void luaF_close (lua_State *L, StkId level) { 69void luaF_close (lua_State *L, StkId level) {
69 UpVal *uv; 70 UpVal *uv;
71 global_State *g = G(L);
70 while ((uv = ngcotouv(L->openupval)) != NULL && uv->v >= level) { 72 while ((uv = ngcotouv(L->openupval)) != NULL && uv->v >= level) {
71 lu_byte mark = uv->marked; 73 GCObject *o = obj2gco(uv);
72 lua_assert(!isblack(obj2gco(uv))); 74 lua_assert(!isblack(o));
73 setobj(L, &uv->value, uv->v);
74 luaC_barrier(L, uv, uv->v);
75 uv->v = &uv->value; /* now current value lives here */
76 L->openupval = uv->next; /* remove from `open' list */ 75 L->openupval = uv->next; /* remove from `open' list */
77 luaC_link(L, obj2gco(uv), LUA_TUPVAL); 76 if (isdead(g, o))
78 if (G(L)->gcstate == GCSpropagate) 77 luaM_freelem(L, uv); /* free upvalue */
79 uv->marked = mark; /* preserve previous mark */ 78 else {
80 lua_assert(!isdead(G(L), obj2gco(uv))); 79 setobj(L, &uv->value, uv->v);
80 uv->v = &uv->value; /* now current value lives here */
81 luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */
82 }
81 } 83 }
82} 84}
83 85
diff --git a/lgc.c b/lgc.c
index 0f34b099..c7d5ad61 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.3 2004/02/16 19:09:52 roberto Exp roberto $ 2** $Id: lgc.c,v 2.4 2004/03/09 17:34:35 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*/
@@ -27,15 +27,16 @@
27#define GCSWEEPCOST sizeof(TValue) 27#define GCSWEEPCOST sizeof(TValue)
28 28
29 29
30#define gray2black(x) setbit((x)->gch.marked, BLACKBIT) 30#define FIXEDMASK bitmask(FIXEDBIT)
31 31
32#define maskmarks \ 32#define maskmarks \
33 cast(lu_byte, ~(bitmask(BLACKBIT)|bit2mask(WHITE0BIT, WHITE1BIT))) 33 cast(lu_byte, ~(bitmask(BLACKBIT)|bit2mask(WHITE0BIT, WHITE1BIT)))
34
34#define makewhite(g,x) \ 35#define makewhite(g,x) \
35 ((x)->gch.marked = ((x)->gch.marked & maskmarks) | g->currentwhite) 36 ((x)->gch.marked = ((x)->gch.marked & maskmarks) | g->currentwhite)
36 37
37#define isgray(x) (!isblack(x) && !iswhite(x))
38#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) 38#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
39#define gray2black(x) setbit((x)->gch.marked, BLACKBIT)
39#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) 40#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT)
40 41
41#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) 42#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)
@@ -58,47 +59,10 @@
58 59
59 60
60 61
61 62static void removeentry (Node *n) {
62/* 63 setnilvalue(gval(n)); /* remove corresponding value ... */
63** computes the size of a collectible object 64 if (iscollectable(gkey(n)))
64*/ 65 setttype(gkey(n), LUA_TNONE); /* dead key; remove it */
65static size_t objsize (GCObject *o) {
66 switch (o->gch.tt) {
67 case LUA_TSTRING: {
68 TString *ts = rawgco2ts(o);
69 return sizestring(ts->tsv.len);
70 }
71 case LUA_TUSERDATA: {
72 Udata *u = rawgco2u(o);
73 return sizeudata(u->uv.len);
74 }
75 case LUA_TTABLE: {
76 Table *h = gco2h(o);
77 return sizeof(Table) + sizeof(TValue) * h->sizearray +
78 sizeof(Node) * sizenode(h);
79 }
80 case LUA_TUPVAL:
81 return sizeof(UpVal);
82 case LUA_TFUNCTION: {
83 Closure *cl = gco2cl(o);
84 return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
85 sizeLclosure(cl->l.nupvalues);
86 }
87 case LUA_TTHREAD: {
88 lua_State *th = gco2th(o);
89 return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
90 sizeof(CallInfo) * th->size_ci;
91 }
92 case LUA_TPROTO: {
93 Proto *p = gco2p(o);
94 return sizeof(Proto) + sizeof(Instruction) * p->sizecode +
95 sizeof(Proto *) * p->sizep + sizeof(TValue) * p->sizek +
96 sizeof(int) * p->sizelineinfo + sizeof(LocVar) * p->sizelocvars +
97 sizeof(TString *) * p->sizeupvalues;
98 }
99 }
100 lua_assert(0);
101 return 0; /* to avoid warnings */
102} 66}
103 67
104 68
@@ -115,29 +79,36 @@ static void reallymarkobject (global_State *g, GCObject *o) {
115 if (mt) markobject(g, mt); 79 if (mt) markobject(g, mt);
116 return; 80 return;
117 } 81 }
82 case LUA_TUPVAL: {
83 UpVal *uv = gco2uv(o);
84 if (uv->v == &uv->value) { /* closed? */
85 markvalue(g, uv->v);
86 gray2black(o);
87 }
88 return;
89 }
118 case LUA_TFUNCTION: { 90 case LUA_TFUNCTION: {
119 gco2cl(o)->c.gclist = g->gray; 91 gco2cl(o)->c.gclist = g->gray;
92 g->gray = o;
120 break; 93 break;
121 } 94 }
122 case LUA_TTABLE: { 95 case LUA_TTABLE: {
123 gco2h(o)->gclist = g->gray; 96 gco2h(o)->gclist = g->gray;
97 g->gray = o;
124 break; 98 break;
125 } 99 }
126 case LUA_TTHREAD: { 100 case LUA_TTHREAD: {
127 gco2th(o)->gclist = g->gray; 101 gco2th(o)->gclist = g->gray;
102 g->gray = o;
128 break; 103 break;
129 } 104 }
130 case LUA_TPROTO: { 105 case LUA_TPROTO: {
131 gco2p(o)->gclist = g->gray; 106 gco2p(o)->gclist = g->gray;
132 break; 107 g->gray = o;
133 }
134 case LUA_TUPVAL: {
135 gco2uv(o)->gclist = g->gray;
136 break; 108 break;
137 } 109 }
138 default: lua_assert(0); 110 default: lua_assert(0);
139 } 111 }
140 g->gray = o; /* finish list linking */
141} 112}
142 113
143 114
@@ -157,8 +128,7 @@ size_t luaC_separateudata (lua_State *L, int all) {
157 GCObject *curr; 128 GCObject *curr;
158 GCObject *collected = NULL; /* to collect udata with gc event */ 129 GCObject *collected = NULL; /* to collect udata with gc event */
159 GCObject **lastcollected = &collected; 130 GCObject **lastcollected = &collected;
160 while ((curr = *p) != NULL) { 131 while ((curr = *p)->gch.tt == LUA_TUSERDATA) {
161 lua_assert(curr->gch.tt == LUA_TUSERDATA);
162 if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) 132 if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
163 p = &curr->gch.next; /* don't bother with them */ 133 p = &curr->gch.next; /* don't bother with them */
164 else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { 134 else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
@@ -174,6 +144,7 @@ size_t luaC_separateudata (lua_State *L, int all) {
174 lastcollected = &curr->gch.next; 144 lastcollected = &curr->gch.next;
175 } 145 }
176 } 146 }
147 lua_assert(curr == obj2gco(G(L)->mainthread));
177 /* insert collected udata with gc event into `tmudata' list */ 148 /* insert collected udata with gc event into `tmudata' list */
178 *lastcollected = G(L)->tmudata; 149 *lastcollected = G(L)->tmudata;
179 G(L)->tmudata = collected; 150 G(L)->tmudata = collected;
@@ -210,7 +181,9 @@ static int traversetable (global_State *g, Table *h) {
210 i = sizenode(h); 181 i = sizenode(h);
211 while (i--) { 182 while (i--) {
212 Node *n = gnode(h, i); 183 Node *n = gnode(h, i);
213 if (!ttisnil(gval(n))) { 184 if (ttisnil(gval(n)))
185 removeentry(n); /* remove empty entries */
186 else {
214 lua_assert(!ttisnil(gkey(n))); 187 lua_assert(!ttisnil(gkey(n)));
215 if (!weakkey) markvalue(g, gkey(n)); 188 if (!weakkey) markvalue(g, gkey(n));
216 if (!weakvalue) markvalue(g, gval(n)); 189 if (!weakvalue) markvalue(g, gval(n));
@@ -274,20 +247,20 @@ static void checkstacksizes (lua_State *L, StkId max) {
274} 247}
275 248
276 249
277static void traversestack (global_State *g, lua_State *L1) { 250static void traversestack (global_State *g, lua_State *l) {
278 StkId o, lim; 251 StkId o, lim;
279 CallInfo *ci; 252 CallInfo *ci;
280 markvalue(g, gt(L1)); 253 markvalue(g, gt(l));
281 lim = L1->top; 254 lim = l->top;
282 for (ci = L1->base_ci; ci <= L1->ci; ci++) { 255 for (ci = l->base_ci; ci <= l->ci; ci++) {
283 lua_assert(ci->top <= L1->stack_last); 256 lua_assert(ci->top <= l->stack_last);
284 if (lim < ci->top) lim = ci->top; 257 if (lim < ci->top) lim = ci->top;
285 } 258 }
286 for (o = L1->stack; o < L1->top; o++) 259 for (o = l->stack; o < l->top; o++)
287 markvalue(g, o); 260 markvalue(g, o);
288 for (; o <= lim; o++) 261 for (; o <= lim; o++)
289 setnilvalue(o); 262 setnilvalue(o);
290 checkstacksizes(L1, lim); 263 checkstacksizes(l, lim);
291} 264}
292 265
293 266
@@ -306,12 +279,16 @@ static l_mem propagatemarks (global_State *g, l_mem lim) {
306 g->gray = h->gclist; 279 g->gray = h->gclist;
307 if (traversetable(g, h)) /* table is weak? */ 280 if (traversetable(g, h)) /* table is weak? */
308 black2gray(o); /* keep it gray */ 281 black2gray(o); /* keep it gray */
282 lim -= sizeof(Table) + sizeof(TValue) * h->sizearray +
283 sizeof(Node) * sizenode(h);
309 break; 284 break;
310 } 285 }
311 case LUA_TFUNCTION: { 286 case LUA_TFUNCTION: {
312 Closure *cl = gco2cl(o); 287 Closure *cl = gco2cl(o);
313 g->gray = cl->c.gclist; 288 g->gray = cl->c.gclist;
314 traverseclosure(g, cl); 289 traverseclosure(g, cl);
290 lim -= (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :
291 sizeLclosure(cl->l.nupvalues);
315 break; 292 break;
316 } 293 }
317 case LUA_TTHREAD: { 294 case LUA_TTHREAD: {
@@ -321,29 +298,24 @@ static l_mem propagatemarks (global_State *g, l_mem lim) {
321 g->grayagain = o; 298 g->grayagain = o;
322 black2gray(o); 299 black2gray(o);
323 traversestack(g, th); 300 traversestack(g, th);
301 lim -= sizeof(lua_State) + sizeof(TValue) * th->stacksize +
302 sizeof(CallInfo) * th->size_ci;
324 break; 303 break;
325 } 304 }
326 case LUA_TPROTO: { 305 case LUA_TPROTO: {
327 Proto *p = gco2p(o); 306 Proto *p = gco2p(o);
328 g->gray = p->gclist; 307 g->gray = p->gclist;
329 traverseproto(g, p); 308 traverseproto(g, p);
330 break; 309 lim -= sizeof(Proto) + sizeof(Instruction) * p->sizecode +
331 } 310 sizeof(Proto *) * p->sizep +
332 case LUA_TUPVAL: { 311 sizeof(TValue) * p->sizek +
333 UpVal *uv = gco2uv(o); 312 sizeof(int) * p->sizelineinfo +
334 g->gray = uv->gclist; 313 sizeof(LocVar) * p->sizelocvars +
335 if (uv->v != &uv->value) { /* open? */ 314 sizeof(TString *) * p->sizeupvalues;
336 uv->gclist = g->grayagain;
337 g->grayagain = o;
338 black2gray(o);
339 }
340 else
341 markvalue(g, &uv->value);
342 break; 315 break;
343 } 316 }
344 default: lua_assert(0); 317 default: lua_assert(0);
345 } 318 }
346 lim -= objsize(o);
347 if (lim <= 0) return lim; 319 if (lim <= 0) return lim;
348 } 320 }
349 return lim; 321 return lim;
@@ -368,13 +340,6 @@ static int iscleared (const TValue *o, int iskey) {
368} 340}
369 341
370 342
371static void removekey (Node *n) {
372 setnilvalue(gval(n)); /* remove corresponding value ... */
373 if (iscollectable(gkey(n)))
374 setttype(gkey(n), LUA_TNONE); /* dead key; remove it */
375}
376
377
378/* 343/*
379** clear collected entries from weaktables 344** clear collected entries from weaktables
380*/ 345*/
@@ -396,7 +361,7 @@ static void cleartable (GCObject *l) {
396 Node *n = gnode(h, i); 361 Node *n = gnode(h, i);
397 if (!ttisnil(gval(n)) && /* non-empty entry? */ 362 if (!ttisnil(gval(n)) && /* non-empty entry? */
398 (iscleared(gkey(n), 1) || iscleared(gval(n), 0))) 363 (iscleared(gkey(n), 1) || iscleared(gval(n), 0)))
399 removekey(n); /* remove entry from table */ 364 removeentry(n); /* remove entry from table */
400 } 365 }
401 l = h->gclist; 366 l = h->gclist;
402 } 367 }
@@ -427,22 +392,28 @@ static void freeobj (lua_State *L, GCObject *o) {
427} 392}
428 393
429 394
430static void sweepupvalues (global_State *g, lua_State *L1) { 395static void sweepupvalues (global_State *g, lua_State *l) {
431 GCObject *curr; 396 GCObject *curr;
432 for (curr = L1->openupval; curr != NULL; curr = curr->gch.next) 397 for (curr = l->openupval; curr != NULL; curr = curr->gch.next)
433 makewhite(g, curr); 398 makewhite(g, curr);
434} 399}
435 400
436 401
437static GCObject **sweeplist (lua_State *L, GCObject **p, int all, 402/*
403** macros to test dead bit and optionally the fix bit
404*/
405#define makedeadmask(g,kf) (otherwhite(g) | ((kf) ? FIXEDMASK : 0))
406#define notdead(mark,mask) ((((mark) ^ FIXEDMASK) & mask) != mask)
407
408
409static GCObject **sweeplist (lua_State *L, GCObject **p, int keepfixed,
438 l_mem *plim) { 410 l_mem *plim) {
439 GCObject *curr; 411 GCObject *curr;
440 global_State *g = G(L); 412 global_State *g = G(L);
441 l_mem lim = *plim; 413 l_mem lim = *plim;
442 int dead = otherwhite(g); 414 int deadmask = makedeadmask(g, keepfixed);
443 while ((curr = *p) != NULL) { 415 while ((curr = *p) != NULL) {
444 int mark = curr->gch.marked; 416 if (notdead(curr->gch.marked, deadmask)) {
445 if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) {
446 makewhite(g, curr); 417 makewhite(g, curr);
447 if (curr->gch.tt == LUA_TTHREAD) 418 if (curr->gch.tt == LUA_TTHREAD)
448 sweepupvalues(g, gco2th(curr)); 419 sweepupvalues(g, gco2th(curr));
@@ -450,6 +421,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
450 lim -= GCSWEEPCOST; 421 lim -= GCSWEEPCOST;
451 } 422 }
452 else { 423 else {
424 lua_assert(iswhite(curr));
453 *p = curr->gch.next; 425 *p = curr->gch.next;
454 if (curr == g->rootgc) /* is the first element of the list? */ 426 if (curr == g->rootgc) /* is the first element of the list? */
455 g->rootgc = curr->gch.next; /* adjust first */ 427 g->rootgc = curr->gch.next; /* adjust first */
@@ -463,22 +435,22 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
463} 435}
464 436
465 437
466static l_mem sweepstrings (lua_State *L, int all, l_mem lim) { 438static l_mem sweepstrings (lua_State *L, int keepfixed, l_mem lim) {
467 int i; 439 int i;
468 global_State *g = G(L); 440 global_State *g = G(L);
469 int dead = otherwhite(g); 441 int deadmask = makedeadmask(g, keepfixed);
470 for (i = g->sweepstrgc; i < g->strt.size; i++) { /* for each list */ 442 for (i = g->sweepstrgc; i < g->strt.size; i++) { /* for each list */
471 GCObject *curr; 443 GCObject *curr;
472 GCObject **p = &G(L)->strt.hash[i]; 444 GCObject **p = &G(L)->strt.hash[i];
473 while ((curr = *p) != NULL) { 445 while ((curr = *p) != NULL) {
474 int mark = curr->gch.marked;
475 lu_mem size = sizestring(gco2ts(curr)->len); 446 lu_mem size = sizestring(gco2ts(curr)->len);
476 if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) { 447 if (notdead(curr->gch.marked, deadmask)) {
477 makewhite(g, curr); 448 makewhite(g, curr);
478 lua_assert(iswhite(curr) && !isdead(g, curr)); 449 lua_assert(iswhite(curr) && !isdead(g, curr));
479 p = &curr->gch.next; 450 p = &curr->gch.next;
480 } 451 }
481 else { 452 else {
453 lua_assert(iswhite(curr));
482 g->strt.nuse--; 454 g->strt.nuse--;
483 *p = curr->gch.next; 455 *p = curr->gch.next;
484 luaM_free(L, curr, size); 456 luaM_free(L, curr, size);
@@ -538,10 +510,19 @@ void luaC_callGCTM (lua_State *L) {
538 510
539 511
540void luaC_sweepall (lua_State *L) { 512void luaC_sweepall (lua_State *L) {
513 global_State *g = G(L);
541 l_mem dummy = MAXLMEM; 514 l_mem dummy = MAXLMEM;
542 G(L)->sweepstrgc = 0; 515 /* finish (occasional) current sweep */
543 sweepstrings(L, 1, dummy); 516 markobject(g, g->mainthread); /* cannot collect main thread */
544 sweeplist(L, &G(L)->rootgc, 1, &dummy); 517 sweepstrings(L, 0, MAXLMEM);
518 sweeplist(L, &g->rootgc, 0, &dummy);
519 /* do a whole new sweep */
520 markobject(g, g->mainthread); /* cannot collect main thread */
521 g->currentwhite = otherwhite(g);
522 g->sweepgc = &g->rootgc;
523 g->sweepstrgc = 0;
524 sweepstrings(L, 0, MAXLMEM);
525 sweeplist(L, &g->rootgc, 0, &dummy);
545} 526}
546 527
547 528
@@ -559,12 +540,30 @@ static void markroot (lua_State *L) {
559} 540}
560 541
561 542
543static void remarkupvals (global_State *g) {
544 GCObject *o;
545 for (o = obj2gco(g->mainthread); o; o = o->gch.next) {
546 if (iswhite(o)) {
547 GCObject *curr;
548 for (curr = gco2th(o)->openupval; curr != NULL; curr = curr->gch.next) {
549 if (isgray(curr))
550 markvalue(g, gco2uv(curr)->v);
551 }
552 }
553 }
554}
555
556
562static void atomic (lua_State *L) { 557static void atomic (lua_State *L) {
563 global_State *g = G(L); 558 global_State *g = G(L);
564 lua_assert(g->gray == NULL); 559 lua_assert(g->gray == NULL);
560 /* remark occasional upvalues of (maybe) dead threads */
561 remarkupvals(g);
565 /* remark weak tables */ 562 /* remark weak tables */
566 g->gray = g->weak; 563 g->gray = g->weak;
567 g->weak = NULL; 564 g->weak = NULL;
565 lua_assert(!iswhite(obj2gco(g->mainthread)));
566 markobject(g, L); /* mark running thread */
568 propagatemarks(g, MAXLMEM); 567 propagatemarks(g, MAXLMEM);
569 /* remark gray again */ 568 /* remark gray again */
570 g->gray = g->grayagain; 569 g->gray = g->grayagain;
@@ -576,8 +575,6 @@ static void atomic (lua_State *L) {
576 cleartable(g->weak); /* remove collected objects from weak tables */ 575 cleartable(g->weak); /* remove collected objects from weak tables */
577 /* flip current white */ 576 /* flip current white */
578 g->currentwhite = otherwhite(g); 577 g->currentwhite = otherwhite(g);
579 g->sweepgc = &g->rootgc;
580 g->sweepstrgc = 0;
581 g->gcstate = GCSsweepstring; 578 g->gcstate = GCSsweepstring;
582} 579}
583 580
@@ -587,38 +584,41 @@ static l_mem singlestep (lua_State *L, l_mem lim) {
587 switch (g->gcstate) { 584 switch (g->gcstate) {
588 case GCSpropagate: { 585 case GCSpropagate: {
589 if (g->gray) 586 if (g->gray)
590 return propagatemarks(g, lim); 587 lim = propagatemarks(g, lim);
591 else { /* no more `gray' objects */ 588 else { /* no more `gray' objects */
592 atomic(L); /* finish mark phase */ 589 atomic(L); /* finish mark phase */
593 return 0; 590 lim = 0;
594 } 591 }
592 break;
595 } 593 }
596 case GCSsweepstring: { 594 case GCSsweepstring: {
597 lim = sweepstrings(L, 0, lim); 595 lim = sweepstrings(L, 1, lim);
598 if (g->sweepstrgc >= g->strt.size) { /* nothing more to sweep? */ 596 if (g->sweepstrgc >= g->strt.size) { /* nothing more to sweep? */
599 g->sweepstrgc = 0; 597 g->sweepstrgc = 0;
600 g->gcstate = GCSsweep; /* end sweep-string phase */ 598 g->gcstate = GCSsweep; /* end sweep-string phase */
601 } 599 }
602 return lim; 600 break;
603 } 601 }
604 case GCSsweep: { 602 case GCSsweep: {
605 g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim); 603 g->sweepgc = sweeplist(L, g->sweepgc, 1, &lim);
606 if (*g->sweepgc == NULL) { /* nothing more to sweep? */ 604 if (*g->sweepgc == NULL) { /* nothing more to sweep? */
607 checkSizes(L); 605 checkSizes(L);
608 sweepupvalues(g, g->mainthread); 606 g->sweepgc = &g->rootgc;
609 g->gcstate = GCSfinalize; /* end sweep phase */ 607 g->gcstate = GCSfinalize; /* end sweep phase */
610 } 608 }
611 return lim; 609 break;
612 } 610 }
613 case GCSfinalize: { 611 case GCSfinalize: {
614 if (g->tmudata) 612 if (g->tmudata)
615 GCTM(L); 613 GCTM(L);
616 else /* no more `udata' to finalize */ 614 else /* no more `udata' to finalize */
617 markroot(L); /* may restart collection */ 615 markroot(L); /* may restart collection */
618 return 0; 616 lim = 0;
617 break;
619 } 618 }
620 default: lua_assert(0); return 0; /* to avoid warnings */ 619 default: lua_assert(0);
621 } 620 }
621 return lim;
622} 622}
623 623
624 624
@@ -635,11 +635,15 @@ void luaC_step (lua_State *L) {
635 635
636void luaC_fullgc (lua_State *L) { 636void luaC_fullgc (lua_State *L) {
637 global_State *g = G(L); 637 global_State *g = G(L);
638 while (g->gcstate != GCSfinalize) singlestep(L, MAXLMEM); 638 while (g->gcstate != GCSfinalize) {
639 singlestep(L, MAXLMEM);
640 }
639 markroot(L); 641 markroot(L);
640 while (g->gcstate != GCSfinalize) singlestep(L, MAXLMEM); 642 while (g->gcstate != GCSfinalize) {
641 luaC_callGCTM(L); /* call finalizers */ 643 singlestep(L, MAXLMEM);
644 }
642 g->GCthreshold = g->nblocks + GCSTEPSIZE; 645 g->GCthreshold = g->nblocks + GCSTEPSIZE;
646 luaC_callGCTM(L); /* call finalizers */
643} 647}
644 648
645 649
@@ -662,3 +666,21 @@ void luaC_link (lua_State *L, GCObject *o, lu_byte tt) {
662 o->gch.tt = tt; 666 o->gch.tt = tt;
663} 667}
664 668
669
670void luaC_linkupval (lua_State *L, UpVal *uv) {
671 global_State *g = G(L);
672 GCObject *o = obj2gco(uv);
673 o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */
674 g->rootgc = o;
675 if (isgray(o)) {
676 if (g->gcstate == GCSpropagate) {
677 gray2black(o); /* closed upvalues need barrier */
678 luaC_barrier(L, uv, uv->v);
679 }
680 else { /* sweep phase: sweep it (turning it into white) */
681 makewhite(g, o);
682 lua_assert(g->gcstate != GCSfinalize);
683 }
684 }
685}
686
diff --git a/lgc.h b/lgc.h
index eae99a98..f80c95d1 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.h,v 2.3 2004/02/16 19:09:52 roberto Exp roberto $ 2** $Id: lgc.h,v 2.4 2004/03/09 17:34:35 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*/
@@ -58,7 +58,7 @@
58 58
59#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) 59#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
60#define isblack(x) testbit((x)->gch.marked, BLACKBIT) 60#define isblack(x) testbit((x)->gch.marked, BLACKBIT)
61 61#define isgray(x) (!isblack(x) && !iswhite(x))
62 62
63#define otherwhite(g) (g->currentwhite ^ bit2mask(WHITE0BIT, WHITE1BIT)) 63#define otherwhite(g) (g->currentwhite ^ bit2mask(WHITE0BIT, WHITE1BIT))
64#define isdead(g,v) ((v)->gch.marked & otherwhite(g)) 64#define isdead(g,v) ((v)->gch.marked & otherwhite(g))
@@ -87,6 +87,7 @@ void luaC_sweepall (lua_State *L);
87void luaC_step (lua_State *L); 87void luaC_step (lua_State *L);
88void luaC_fullgc (lua_State *L); 88void luaC_fullgc (lua_State *L);
89void luaC_link (lua_State *L, GCObject *o, lu_byte tt); 89void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
90void luaC_linkupval (lua_State *L, UpVal *uv);
90void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); 91void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
91 92
92 93
diff --git a/lobject.h b/lobject.h
index f9968a09..ee23f3db 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.h,v 2.2 2004/02/16 19:09:52 roberto Exp roberto $ 2** $Id: lobject.h,v 2.3 2004/02/20 16:01:05 roberto Exp roberto $
3** Type definitions for Lua objects 3** Type definitions for Lua objects
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -263,7 +263,6 @@ typedef struct LocVar {
263 263
264typedef struct UpVal { 264typedef struct UpVal {
265 CommonHeader; 265 CommonHeader;
266 GCObject *gclist;
267 TValue *v; /* points to stack or to its own value */ 266 TValue *v; /* points to stack or to its own value */
268 TValue value; /* the value (when closed) */ 267 TValue value; /* the value (when closed) */
269} UpVal; 268} UpVal;
diff --git a/lstate.c b/lstate.c
index 36e7d9c3..0b38615a 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 2.2 2003/12/12 18:29:34 roberto Exp roberto $ 2** $Id: lstate.c,v 2.3 2004/02/16 19:09:52 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -93,7 +93,10 @@ static void f_luaopen (lua_State *L, void *ud) {
93} 93}
94 94
95 95
96static void preinit_state (lua_State *L) { 96static void preinit_state (lua_State *L, global_State *g) {
97 L->l_G = g;
98 L->tt = LUA_TTHREAD;
99 L->marked = luaC_white(g);
97 L->stack = NULL; 100 L->stack = NULL;
98 L->stacksize = 0; 101 L->stacksize = 0;
99 L->errorJmp = NULL; 102 L->errorJmp = NULL;
@@ -116,7 +119,7 @@ static void close_state (lua_State *L) {
116 global_State *g = G(L); 119 global_State *g = G(L);
117 luaF_close(L, L->stack); /* close all upvalues for this thread */ 120 luaF_close(L, L->stack); /* close all upvalues for this thread */
118 luaC_sweepall(L); /* collect all elements */ 121 luaC_sweepall(L); /* collect all elements */
119 lua_assert(g->rootgc == NULL); 122 lua_assert(g->rootgc == obj2gco(L));
120 luaS_freeall(L); 123 luaS_freeall(L);
121 luaZ_freebuffer(L, &g->buff); 124 luaZ_freebuffer(L, &g->buff);
122 freestack(L, L); 125 freestack(L, L);
@@ -127,9 +130,9 @@ static void close_state (lua_State *L) {
127 130
128lua_State *luaE_newthread (lua_State *L) { 131lua_State *luaE_newthread (lua_State *L) {
129 lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); 132 lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));
130 luaC_link(L, obj2gco(L1), LUA_TTHREAD); 133 L1->next = L->next; /* link new thread after `L' */
131 preinit_state(L1); 134 L->next = obj2gco(L1);
132 L1->l_G = L->l_G; 135 preinit_state(L1, G(L));
133 stack_init(L1, L); /* init stack */ 136 stack_init(L1, L); /* init stack */
134 setobj2n(L, gt(L1), gt(L)); /* share table of globals */ 137 setobj2n(L, gt(L1), gt(L)); /* share table of globals */
135 lua_assert(iswhite(obj2gco(L1))); 138 lua_assert(iswhite(obj2gco(L1)));
@@ -152,11 +155,9 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
152 if (l == NULL) return NULL; 155 if (l == NULL) return NULL;
153 L = tostate(l); 156 L = tostate(l);
154 g = &((LG *)L)->g; 157 g = &((LG *)L)->g;
155 L->tt = LUA_TTHREAD; 158 L->next = NULL;
156 L->marked = 0; 159 g->currentwhite = bitmask(WHITE0BIT);
157 L->next = L->gclist = NULL; 160 preinit_state(L, g);
158 preinit_state(L);
159 L->l_G = g;
160 g->realloc = f; 161 g->realloc = f;
161 g->ud = ud; 162 g->ud = ud;
162 g->mainthread = L; 163 g->mainthread = L;
@@ -168,9 +169,9 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
168 luaZ_initbuffer(L, &g->buff); 169 luaZ_initbuffer(L, &g->buff);
169 g->panic = NULL; 170 g->panic = NULL;
170 g->gcstate = GCSfinalize; 171 g->gcstate = GCSfinalize;
171 g->rootgc = NULL; 172 g->rootgc = obj2gco(L);
172 g->sweepstrgc = 0; 173 g->sweepstrgc = 0;
173 g->currentwhite = bitmask(WHITE0BIT); 174 g->sweepgc = &g->rootgc;
174 g->firstudata = NULL; 175 g->firstudata = NULL;
175 g->gray = NULL; 176 g->gray = NULL;
176 g->grayagain = NULL; 177 g->grayagain = NULL;