aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2010-04-29 14:32:40 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2010-04-29 14:32:40 -0300
commitaaa5d7adab1fd4a2f2d0c1f2996e354445ad163f (patch)
treef11ddbfe31e2e82604e280d9ae5b026bc917429b
parent3eb1788bb4236cd983f1230ee14e2adb1b5b3ff5 (diff)
downloadlua-aaa5d7adab1fd4a2f2d0c1f2996e354445ad163f.tar.gz
lua-aaa5d7adab1fd4a2f2d0c1f2996e354445ad163f.tar.bz2
lua-aaa5d7adab1fd4a2f2d0c1f2996e354445ad163f.zip
'luaC_linkupval' moved into 'lfunc.c' code + new way to control GC speed
-rw-r--r--lgc.c136
-rw-r--r--lgc.h24
2 files changed, 80 insertions, 80 deletions
diff --git a/lgc.c b/lgc.c
index 2081848f..d897d780 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.79 2010/04/20 20:15:30 roberto Exp roberto $ 2** $Id: lgc.c,v 2.80 2010/04/26 17:58:00 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*/
@@ -23,16 +23,19 @@
23#include "ltm.h" 23#include "ltm.h"
24 24
25 25
26#define GCSTEPSIZE 1024u 26#define GCSTEPSIZE 1024
27#define GCSWEEPMAX 40 27#define GCSWEEPMAX 40
28#define GCSWEEPCOST 10 28#define GCSWEEPCOST 1
29#define GCFINALIZECOST 100 29#define GCFINALIZECOST 50
30#define GCROOTCOST 10 30#define GCROOTCOST 10
31#define GCATOMICCOST 1000 31#define GCATOMICCOST 1000
32 32
33 33
34#define issweepphase(g) \ 34/*
35 (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) 35** standard negative debt for GC; a reasonable "time" to wait before
36** starting a new cycle
37*/
38#define stddebt(g) (-cast(l_mem, g->totalbytes/100) * g->gcpause)
36 39
37 40
38/* 41/*
@@ -60,17 +63,6 @@
60#define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \ 63#define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \
61 reallymarkobject(g, obj2gco(t)); } 64 reallymarkobject(g, obj2gco(t)); }
62 65
63
64/*
65** macro to tell when main invariant (white objects cannot point to black
66** ones) must be kept. During a non-generational collection, the sweep
67** phase may brak the invariant, as objects turned white may point to
68** still-black objects. The invariant is restored when sweep ends and
69** all objects are white again. During a generational collection, the
70** invariant must be kept all times.
71*/
72#define keepinvariant(g) (g->gckind == KGC_GEN || g->gcstate == GCSpropagate)
73
74static void reallymarkobject (global_State *g, GCObject *o); 66static void reallymarkobject (global_State *g, GCObject *o);
75 67
76 68
@@ -142,9 +134,15 @@ void luaC_barrierback (lua_State *L, Table *t) {
142 global_State *g = G(L); 134 global_State *g = G(L);
143 GCObject *o = obj2gco(t); 135 GCObject *o = obj2gco(t);
144 lua_assert(isblack(o) && !isdead(g, o)); 136 lua_assert(isblack(o) && !isdead(g, o));
145 black2gray(o); /* make table gray (again) */ 137 if (keepinvariant(g)) {
146 t->gclist = g->grayagain; 138 black2gray(o); /* make table gray (again) */
147 g->grayagain = o; 139 t->gclist = g->grayagain;
140 g->grayagain = o;
141 }
142 else { /* sweep phase */
143 lua_assert(issweepphase(g));
144 makewhite(g, o); /* mark main obj. as white to avoid other barriers */
145 }
148} 146}
149 147
150 148
@@ -166,23 +164,6 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list,
166 return o; 164 return o;
167} 165}
168 166
169
170/*
171** link an upvalue back to the main root list. (It was previously in the
172** list of open upvalues of some thread.)
173*/
174void luaC_linkupval (lua_State *L, UpVal *uv) {
175 global_State *g = G(L);
176 GCObject *o = obj2gco(uv);
177 gch(o)->next = g->allgc; /* link upvalue into `allgc' list */
178 g->allgc = o;
179 lua_assert(!isblack(o)); /* open upvalues are never black */
180 if (isgray(o)) { /* is it marked? */
181 gray2black(o); /* could not be black; now it can */
182 luaC_barrier(L, uv, uv->v);
183 }
184}
185
186/* }====================================================== */ 167/* }====================================================== */
187 168
188 169
@@ -287,9 +268,9 @@ static void remarkupvals (global_State *g) {
287*/ 268*/
288static void markroot (lua_State *L) { 269static void markroot (lua_State *L) {
289 global_State *g = G(L); 270 global_State *g = G(L);
290 g->gray = NULL; 271 lua_assert(g->gckind == KGC_GEN ||
291 g->grayagain = NULL; 272 (g->gray == NULL && g->grayagain == NULL && g->weak == NULL &&
292 g->weak = g->ephemeron = g->allweak = NULL; 273 g->allweak == NULL && g->ephemeron == NULL));
293 markobject(g, g->mainthread); 274 markobject(g, g->mainthread);
294 markvalue(g, &g->l_registry); 275 markvalue(g, &g->l_registry);
295 markmt(g); 276 markmt(g);
@@ -372,7 +353,7 @@ static void traversestrongtable (global_State *g, Table *h) {
372} 353}
373 354
374 355
375static void traversetable (global_State *g, Table *h) { 356static int traversetable (global_State *g, Table *h) {
376 const TValue *mode = gfasttm(g, h->metatable, TM_MODE); 357 const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
377 markobject(g, h->metatable); 358 markobject(g, h->metatable);
378 if (mode && ttisstring(mode)) { /* is there a weak mode? */ 359 if (mode && ttisstring(mode)) { /* is there a weak mode? */
@@ -380,20 +361,26 @@ static void traversetable (global_State *g, Table *h) {
380 int weakvalue = (strchr(svalue(mode), 'v') != NULL); 361 int weakvalue = (strchr(svalue(mode), 'v') != NULL);
381 if (weakkey || weakvalue) { /* is really weak? */ 362 if (weakkey || weakvalue) { /* is really weak? */
382 black2gray(obj2gco(h)); /* keep table gray */ 363 black2gray(obj2gco(h)); /* keep table gray */
383 if (!weakkey) /* strong keys? */ 364 if (!weakkey) { /* strong keys? */
384 traverseweakvalue(g, h); 365 traverseweakvalue(g, h);
385 else if (!weakvalue) /* strong values? */ 366 return 1 + sizenode(h);
367 }
368 else if (!weakvalue) { /* strong values? */
386 traverseephemeron(g, h); 369 traverseephemeron(g, h);
387 else 370 return 1 + h->sizearray + sizenode(h);
371 }
372 else {
388 linktable(h, &g->allweak); /* nothing to traverse now */ 373 linktable(h, &g->allweak); /* nothing to traverse now */
389 return; 374 return 1;
375 }
390 } /* else go through */ 376 } /* else go through */
391 } 377 }
392 traversestrongtable(g, h); 378 traversestrongtable(g, h);
379 return 1 + h->sizearray + (2 * sizenode(h));
393} 380}
394 381
395 382
396static void traverseproto (global_State *g, Proto *f) { 383static int traverseproto (global_State *g, Proto *f) {
397 int i; 384 int i;
398 stringmark(f->source); 385 stringmark(f->source);
399 for (i = 0; i < f->sizek; i++) /* mark literals */ 386 for (i = 0; i < f->sizek; i++) /* mark literals */
@@ -404,6 +391,7 @@ static void traverseproto (global_State *g, Proto *f) {
404 markobject(g, f->p[i]); 391 markobject(g, f->p[i]);
405 for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ 392 for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */
406 stringmark(f->locvars[i].varname); 393 stringmark(f->locvars[i].varname);
394 return 1 + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars;
407} 395}
408 396
409 397
@@ -425,26 +413,27 @@ static l_mem traverseclosure (global_State *g, Closure *cl) {
425} 413}
426 414
427 415
428static void traversestack (global_State *g, lua_State *L) { 416static int traversestack (global_State *g, lua_State *L) {
429 StkId o; 417 StkId o = L->stack;
430 if (L->stack == NULL) 418 if (L->stack == NULL)
431 return; /* stack not completely built yet */ 419 return 1; /* stack not completely built yet */
432 for (o = L->stack; o < L->top; o++) 420 for (; o < L->top; o++)
433 markvalue(g, o); 421 markvalue(g, o);
434 if (g->gcstate == GCSatomic) { /* final traversal? */ 422 if (g->gcstate == GCSatomic) { /* final traversal? */
435 StkId lim = L->stack + L->stacksize; /* real end of stack */ 423 StkId lim = L->stack + L->stacksize; /* real end of stack */
436 for (; o < lim; o++) /* clear not-marked stack slice */ 424 for (; o < lim; o++) /* clear not-marked stack slice */
437 setnilvalue(o); 425 setnilvalue(o);
438 } 426 }
427 return 1 + cast_int(o - L->stack);
439} 428}
440 429
441 430
442/* 431/*
443** traverse one gray object, turning it to black (except for threads, 432** traverse one gray object, turning it to black (except for threads,
444** which are always gray). 433** which are always gray).
445** Returns 'quantity' traversed. 434** Returns number of values traversed.
446*/ 435*/
447static l_mem propagatemark (global_State *g) { 436static int propagatemark (global_State *g) {
448 GCObject *o = g->gray; 437 GCObject *o = g->gray;
449 lua_assert(isgray(o)); 438 lua_assert(isgray(o));
450 gray2black(o); 439 gray2black(o);
@@ -452,9 +441,7 @@ static l_mem propagatemark (global_State *g) {
452 case LUA_TTABLE: { 441 case LUA_TTABLE: {
453 Table *h = gco2t(o); 442 Table *h = gco2t(o);
454 g->gray = h->gclist; 443 g->gray = h->gclist;
455 traversetable(g, h); 444 return traversetable(g, h);
456 return sizeof(Table) + sizeof(TValue) * h->sizearray +
457 sizeof(Node) * sizenode(h);
458 } 445 }
459 case LUA_TFUNCTION: { 446 case LUA_TFUNCTION: {
460 Closure *cl = gco2cl(o); 447 Closure *cl = gco2cl(o);
@@ -467,19 +454,12 @@ static l_mem propagatemark (global_State *g) {
467 th->gclist = g->grayagain; 454 th->gclist = g->grayagain;
468 g->grayagain = o; 455 g->grayagain = o;
469 black2gray(o); 456 black2gray(o);
470 traversestack(g, th); 457 return traversestack(g, th);
471 return sizeof(lua_State) + sizeof(TValue) * th->stacksize;
472 } 458 }
473 case LUA_TPROTO: { 459 case LUA_TPROTO: {
474 Proto *p = gco2p(o); 460 Proto *p = gco2p(o);
475 g->gray = p->gclist; 461 g->gray = p->gclist;
476 traverseproto(g, p); 462 return traverseproto(g, p);
477 return sizeof(Proto) + sizeof(Instruction) * p->sizecode +
478 sizeof(Proto *) * p->sizep +
479 sizeof(TValue) * p->sizek +
480 sizeof(int) * p->sizelineinfo +
481 sizeof(LocVar) * p->sizelocvars +
482 sizeof(TString *) * p->sizeupvalues;
483 } 463 }
484 default: lua_assert(0); return 0; 464 default: lua_assert(0); return 0;
485 } 465 }
@@ -673,15 +653,15 @@ static void GCTM (lua_State *L, int propagateerrors) {
673 if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ 653 if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */
674 int status; 654 int status;
675 lu_byte oldah = L->allowhook; 655 lu_byte oldah = L->allowhook;
676 lu_mem oldt = g->GCthreshold; 656 lu_mem oldd = g->GCdebt;
677 L->allowhook = 0; /* stop debug hooks during GC tag method */ 657 L->allowhook = 0; /* stop debug hooks during GC tag method */
678 g->GCthreshold = 2 * g->totalbytes; /* avoid GC steps */ 658 g->GCdebt = -2 * g->totalbytes; /* avoid GC steps */
679 setobj2s(L, L->top, tm); /* push finalizer... */ 659 setobj2s(L, L->top, tm); /* push finalizer... */
680 setuvalue(L, L->top+1, udata); /* ... and its argument */ 660 setuvalue(L, L->top+1, udata); /* ... and its argument */
681 L->top += 2; /* and (next line) call the finalizer */ 661 L->top += 2; /* and (next line) call the finalizer */
682 status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); 662 status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0);
683 L->allowhook = oldah; /* restore hooks */ 663 L->allowhook = oldah; /* restore hooks */
684 g->GCthreshold = oldt; /* restore threshold */ 664 g->GCdebt = oldd; /* restore threshold */
685 if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ 665 if (status != LUA_OK && propagateerrors) { /* error while running __gc? */
686 if (status == LUA_ERRRUN) { /* is there an error msg.? */ 666 if (status == LUA_ERRRUN) { /* is there an error msg.? */
687 luaO_pushfstring(L, "error in __gc tag method (%s)", 667 luaO_pushfstring(L, "error in __gc tag method (%s)",
@@ -791,7 +771,13 @@ static void atomic (lua_State *L) {
791 cleartable(g->weak); 771 cleartable(g->weak);
792 cleartable(g->ephemeron); 772 cleartable(g->ephemeron);
793 cleartable(g->allweak); 773 cleartable(g->allweak);
774 lua_checkmemory(L);
794 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ 775 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
776 if (g->gckind != KGC_GEN) {
777 g->gray = NULL; /* all gray objects will become white */
778 g->grayagain = NULL;
779 g->weak = g->ephemeron = g->allweak = NULL;
780 }
795} 781}
796 782
797 783
@@ -890,23 +876,18 @@ static void generationalcollection (lua_State *L) {
890 if (g->totalbytes > g->lastmajormem/100 * g->gcpause) 876 if (g->totalbytes > g->lastmajormem/100 * g->gcpause)
891 g->lastmajormem = 0; /* signal for a major collection */ 877 g->lastmajormem = 0; /* signal for a major collection */
892 } 878 }
893 g->GCthreshold = (g->totalbytes/100) * g->gcpause; 879 g->GCdebt = stddebt(g);
894} 880}
895 881
896 882
897static void step (lua_State *L) { 883static void step (lua_State *L) {
898 global_State *g = G(L); 884 global_State *g = G(L);
899 l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; /* how much to work */ 885 l_mem lim = g->gcstepmul; /* how much to work */
900 lu_mem debt = g->totalbytes - g->GCthreshold;
901 lua_assert(g->gckind == KGC_NORMAL); 886 lua_assert(g->gckind == KGC_NORMAL);
902 do { /* always perform at least one single step */ 887 do { /* always perform at least one single step */
903 lim -= singlestep(L); 888 lim -= singlestep(L);
904 } while (lim > 0 && g->gcstate != GCSpause); 889 } while (lim > 0 && g->gcstate != GCSpause);
905 g->GCthreshold = (g->gcstate != GCSpause) 890 g->GCdebt += (g->gcstate != GCSpause) ? -GCSTEPSIZE : stddebt(g);
906 ? g->totalbytes + GCSTEPSIZE
907 : (g->totalbytes/100) * g->gcpause;
908 /* compensate if GC is "behind schedule" (has some debt to pay) */
909 if (g->GCthreshold > debt) g->GCthreshold -= debt;
910} 891}
911 892
912 893
@@ -930,6 +911,9 @@ void luaC_fullgc (lua_State *L, int isemergency) {
930 (as white has not changed, nothing will be collected) */ 911 (as white has not changed, nothing will be collected) */
931 g->sweepstrgc = 0; 912 g->sweepstrgc = 0;
932 g->gcstate = GCSsweepstring; 913 g->gcstate = GCSsweepstring;
914 g->gray = NULL;
915 g->grayagain = NULL;
916 g->weak = g->ephemeron = g->allweak = NULL;
933 } 917 }
934 /* finish any pending sweep phase */ 918 /* finish any pending sweep phase */
935 luaC_runtilstate(L, bit2mask(GCSpause, GCSfinalize)); 919 luaC_runtilstate(L, bit2mask(GCSpause, GCSfinalize));
@@ -943,7 +927,7 @@ void luaC_fullgc (lua_State *L, int isemergency) {
943 g->gcstate = GCSpause; /* collector must be always in... */ 927 g->gcstate = GCSpause; /* collector must be always in... */
944 luaC_runtilstate(L, bitmask(GCSpropagate)); /* ...propagate phase */ 928 luaC_runtilstate(L, bitmask(GCSpropagate)); /* ...propagate phase */
945 } 929 }
946 g->GCthreshold = (g->totalbytes/100) * g->gcpause; 930 g->GCdebt = stddebt(g);
947} 931}
948 932
949/* }====================================================== */ 933/* }====================================================== */
diff --git a/lgc.h b/lgc.h
index 38564849..b7e00b38 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.h,v 2.29 2010/03/24 15:51:10 roberto Exp roberto $ 2** $Id: lgc.h,v 2.30 2010/03/25 13:06:36 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*/
@@ -23,6 +23,24 @@
23#define GCSfinalize 6 23#define GCSfinalize 6
24 24
25 25
26#define issweepphase(g) \
27 (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep)
28
29
30/*
31** macro to tell when main invariant (white objects cannot point to black
32** ones) must be kept. During a non-generational collection, the sweep
33** phase may brak the invariant, as objects turned white may point to
34** still-black objects. The invariant is restored when sweep ends and
35** all objects are white again. During a generational collection, the
36** invariant must be kept all times.
37*/
38#define keepinvariant(g) (g->gckind == KGC_GEN || g->gcstate == GCSpropagate)
39
40
41#define gcstopped(g) ((g)->GCdebt == MIN_LMEM)
42#define stopgc(g) ((g)->GCdebt = MIN_LMEM)
43
26 44
27/* 45/*
28** some useful bit tricks 46** some useful bit tricks
@@ -76,8 +94,7 @@
76#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) 94#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
77 95
78 96
79#define luaC_checkGC(L) \ 97#define luaC_checkGC(L) {condchangemem(L); if (G(L)->GCdebt > 0) luaC_step(L);}
80 {condchangemem(L); if (G(L)->totalbytes >= G(L)->GCthreshold) luaC_step(L);}
81 98
82 99
83#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ 100#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \
@@ -100,7 +117,6 @@ LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask);
100LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); 117LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
101LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, 118LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz,
102 GCObject **list, int offset); 119 GCObject **list, int offset);
103LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);
104LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); 120LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
105LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); 121LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t);
106LUAI_FUNC void luaC_checkfinalizer (lua_State *L, Udata *u); 122LUAI_FUNC void luaC_checkfinalizer (lua_State *L, Udata *u);