aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2004-03-09 14:34:35 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2004-03-09 14:34:35 -0300
commitb876ec61c03e05ea0c4c02d8ad8abb84cf55e87c (patch)
tree62224cadfc7273beecb092f0e4a761e4c4f634e5
parent898e8a67942186d62aa2cd3dc4ef96fe894788ef (diff)
downloadlua-b876ec61c03e05ea0c4c02d8ad8abb84cf55e87c.tar.gz
lua-b876ec61c03e05ea0c4c02d8ad8abb84cf55e87c.tar.bz2
lua-b876ec61c03e05ea0c4c02d8ad8abb84cf55e87c.zip
new (temporary?) API for garbage collector
-rw-r--r--lapi.c55
-rw-r--r--lbaselib.c35
-rw-r--r--lgc.c58
-rw-r--r--lgc.h3
-rw-r--r--lua.h17
5 files changed, 101 insertions, 67 deletions
diff --git a/lapi.c b/lapi.c
index 59129f71..48993abf 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.c,v 2.2 2004/01/15 12:40:26 roberto Exp roberto $ 2** $Id: lapi.c,v 2.3 2004/02/20 16:01:05 roberto Exp roberto $
3** Lua API 3** Lua API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -807,39 +807,34 @@ LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) {
807 807
808 808
809/* 809/*
810** Garbage-collection functions 810** Garbage-collection function
811*/ 811*/
812 812
813/* GC values are expressed in Kbytes: #bytes/2^10 */ 813LUA_API int lua_gc (lua_State *L, int what, int data) {
814#define GCscale(x) (cast(int, (x)>>10)) 814 global_State *g = G(L);
815#define GCunscale(x) (cast(lu_mem, x)<<10) 815 switch (what) {
816 816 case LUA_GCSTOP: {
817#define MAX_THRESHOLD (cast(lu_mem, ~0) >> 10) 817 g->GCthreshold = MAXLMEM;
818 818 return 0;
819LUA_API int lua_getgcthreshold (lua_State *L) { 819 }
820 int threshold; 820 case LUA_GCRESTART: {
821 lua_lock(L); 821 g->GCthreshold = g->nblocks;
822 threshold = GCscale(G(L)->GCthreshold); 822 return 0;
823 lua_unlock(L); 823 }
824 return threshold; 824 case LUA_GCCOLLECT: {
825} 825 lua_lock(L);
826 826 luaC_fullgc(L);
827LUA_API int lua_getgccount (lua_State *L) { 827 lua_unlock(L);
828 int count; 828 return 0;
829 lua_lock(L); 829 }
830 count = GCscale(G(L)->nblocks); 830 case LUA_GCCOUNT: {
831 lua_unlock(L); 831 /* GC values are expressed in Kbytes: #bytes/2^10 */
832 return count; 832 return cast(int, g->nblocks >> 10);
833 }
834 default: return -1; /* invalid option */
835 }
833} 836}
834 837
835LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
836 lua_lock(L);
837 if (cast(lu_mem, newthreshold) > MAX_THRESHOLD)
838 newthreshold = cast(int, MAX_THRESHOLD);
839 G(L)->GCthreshold = GCunscale(newthreshold);
840 luaC_checkGC(L);
841 lua_unlock(L);
842}
843 838
844 839
845/* 840/*
diff --git a/lbaselib.c b/lbaselib.c
index f59e6460..009db94b 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lbaselib.c,v 1.138 2003/11/11 16:34:17 roberto Exp roberto $ 2** $Id: lbaselib.c,v 1.139 2003/12/09 16:55:43 roberto Exp roberto $
3** Basic library 3** Basic library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -186,14 +186,31 @@ static int luaB_rawset (lua_State *L) {
186 186
187static int luaB_gcinfo (lua_State *L) { 187static int luaB_gcinfo (lua_State *L) {
188 lua_pushinteger(L, lua_getgccount(L)); 188 lua_pushinteger(L, lua_getgccount(L));
189 lua_pushinteger(L, lua_getgcthreshold(L)); 189 return 1;
190 return 2;
191} 190}
192 191
193 192
194static int luaB_collectgarbage (lua_State *L) { 193static int luaB_collectgarbage (lua_State *L) {
195 lua_setgcthreshold(L, luaL_optint(L, 1, 0)); 194 static const char *const opts[] = {"stop", "restart", "collect", "count",
196 return 0; 195 NULL};
196 static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART,
197 LUA_GCCOLLECT, LUA_GCCOUNT};
198 int o;
199 int ex;
200#if 1
201 if (lua_isnumber(L, 1)) {
202 int v = lua_tointeger(L, 1);
203 lua_settop(L, 0);
204 if (v == 0) lua_pushstring(L, "collect");
205 else if (v >= 10000) lua_pushstring(L, "stop");
206 else lua_pushstring(L, "restart");
207 }
208#endif
209 o = luaL_findstring(luaL_optstring(L, 1, "collect"), opts);
210 ex = luaL_optint(L, 2, 0);
211 luaL_argcheck(L, o >= 0, 1, "invalid option");
212 lua_pushinteger(L, lua_gc(L, optsnum[o], ex));
213 return 1;
197} 214}
198 215
199 216
@@ -311,10 +328,10 @@ static int luaB_load (lua_State *L) {
311 328
312static int luaB_dofile (lua_State *L) { 329static int luaB_dofile (lua_State *L) {
313 const char *fname = luaL_optstring(L, 1, NULL); 330 const char *fname = luaL_optstring(L, 1, NULL);
314 int status = luaL_loadfile(L, fname); 331 int n = lua_gettop(L);
315 if (status != 0) lua_error(L); 332 if (luaL_loadfile(L, fname) != 0) lua_error(L);
316 lua_call(L, 0, LUA_MULTRET); 333 lua_call(L, 0, LUA_MULTRET);
317 return lua_gettop(L) - 1; 334 return lua_gettop(L) - n;
318} 335}
319 336
320 337
@@ -710,6 +727,6 @@ LUALIB_API int luaopen_base (lua_State *L) {
710 luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0); 727 luaL_openlib(L, LUA_COLIBNAME, co_funcs, 0);
711 lua_newtable(L); 728 lua_newtable(L);
712 lua_setglobal(L, REQTAB); 729 lua_setglobal(L, REQTAB);
713 return 0; 730 return 2;
714} 731}
715 732
diff --git a/lgc.c b/lgc.c
index ae5cd686..0f34b099 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.2 2003/12/12 18:29:34 roberto Exp roberto $ 2** $Id: lgc.c,v 2.3 2004/02/16 19:09:52 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,8 @@
23 23
24 24
25#define GCSTEPSIZE (40*sizeof(TValue)) 25#define GCSTEPSIZE (40*sizeof(TValue))
26#define GCFREECOST (sizeof(TValue)/2)
27#define GCSWEEPCOST sizeof(TValue)
26 28
27 29
28#define gray2black(x) setbit((x)->gch.marked, BLACKBIT) 30#define gray2black(x) setbit((x)->gch.marked, BLACKBIT)
@@ -51,10 +53,6 @@
51#define markvalue(g,o) { checkconsistency(o); \ 53#define markvalue(g,o) { checkconsistency(o); \
52 if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } 54 if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
53 55
54#define condmarkobject(g,o,c) { checkconsistency(o); \
55 if (iscollectable(o) && iswhite(gcvalue(o)) && (c)) \
56 reallymarkobject(g,gcvalue(o)); }
57
58#define markobject(g,t) { if (iswhite(obj2gco(t))) \ 56#define markobject(g,t) { if (iswhite(obj2gco(t))) \
59 reallymarkobject(g, obj2gco(t)); } 57 reallymarkobject(g, obj2gco(t)); }
60 58
@@ -214,8 +212,8 @@ static int traversetable (global_State *g, Table *h) {
214 Node *n = gnode(h, i); 212 Node *n = gnode(h, i);
215 if (!ttisnil(gval(n))) { 213 if (!ttisnil(gval(n))) {
216 lua_assert(!ttisnil(gkey(n))); 214 lua_assert(!ttisnil(gkey(n)));
217 condmarkobject(g, gkey(n), !weakkey); 215 if (!weakkey) markvalue(g, gkey(n));
218 condmarkobject(g, gval(n), !weakvalue); 216 if (!weakvalue) markvalue(g, gval(n));
219 } 217 }
220 } 218 }
221 return weakkey || weakvalue; 219 return weakkey || weakvalue;
@@ -444,18 +442,19 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
444 int dead = otherwhite(g); 442 int dead = otherwhite(g);
445 while ((curr = *p) != NULL) { 443 while ((curr = *p) != NULL) {
446 int mark = curr->gch.marked; 444 int mark = curr->gch.marked;
447 lim -= objsize(curr);
448 if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) { 445 if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) {
449 makewhite(g, curr); 446 makewhite(g, curr);
450 if (curr->gch.tt == LUA_TTHREAD) 447 if (curr->gch.tt == LUA_TTHREAD)
451 sweepupvalues(g, gco2th(curr)); 448 sweepupvalues(g, gco2th(curr));
452 p = &curr->gch.next; 449 p = &curr->gch.next;
450 lim -= GCSWEEPCOST;
453 } 451 }
454 else { 452 else {
455 *p = curr->gch.next; 453 *p = curr->gch.next;
456 if (curr == g->rootgc) /* is the first element of the list? */ 454 if (curr == g->rootgc) /* is the first element of the list? */
457 g->rootgc = curr->gch.next; /* adjust first */ 455 g->rootgc = curr->gch.next; /* adjust first */
458 freeobj(L, curr); 456 freeobj(L, curr);
457 lim -= GCFREECOST;
459 } 458 }
460 if (lim <= 0) break; 459 if (lim <= 0) break;
461 } 460 }
@@ -583,19 +582,16 @@ static void atomic (lua_State *L) {
583} 582}
584 583
585 584
586void luaC_step (lua_State *L) { 585static l_mem singlestep (lua_State *L, l_mem lim) {
587 global_State *g = G(L); 586 global_State *g = G(L);
588 l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * 2;
589luaC_checkall(L);
590 switch (g->gcstate) { 587 switch (g->gcstate) {
591 case GCSpropagate: { 588 case GCSpropagate: {
592 if (g->gray) 589 if (g->gray)
593 lim = propagatemarks(g, lim); 590 return propagatemarks(g, lim);
594 else { /* no more `gray' objects */ 591 else { /* no more `gray' objects */
595 atomic(L); /* finish mark phase */ 592 atomic(L); /* finish mark phase */
596 lim = 0; 593 return 0;
597 } 594 }
598 break;
599 } 595 }
600 case GCSsweepstring: { 596 case GCSsweepstring: {
601 lim = sweepstrings(L, 0, lim); 597 lim = sweepstrings(L, 0, lim);
@@ -603,7 +599,7 @@ luaC_checkall(L);
603 g->sweepstrgc = 0; 599 g->sweepstrgc = 0;
604 g->gcstate = GCSsweep; /* end sweep-string phase */ 600 g->gcstate = GCSsweep; /* end sweep-string phase */
605 } 601 }
606 break; 602 return lim;
607 } 603 }
608 case GCSsweep: { 604 case GCSsweep: {
609 g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim); 605 g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim);
@@ -612,27 +608,45 @@ luaC_checkall(L);
612 sweepupvalues(g, g->mainthread); 608 sweepupvalues(g, g->mainthread);
613 g->gcstate = GCSfinalize; /* end sweep phase */ 609 g->gcstate = GCSfinalize; /* end sweep phase */
614 } 610 }
615 break; 611 return lim;
616 } 612 }
617 case GCSfinalize: { 613 case GCSfinalize: {
618 if (g->tmudata) { 614 if (g->tmudata)
619 GCTM(L); 615 GCTM(L);
620 lim = 0;
621 }
622 else /* no more `udata' to finalize */ 616 else /* no more `udata' to finalize */
623 markroot(L); /* may restart collection */ 617 markroot(L); /* may restart collection */
624 break; 618 return 0;
625 } 619 }
626 default: lua_assert(0); 620 default: lua_assert(0); return 0; /* to avoid warnings */
627 } 621 }
622}
623
624
625void luaC_step (lua_State *L) {
626 global_State *g = G(L);
627 l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * 2;
628/*printf("+ %d %lu %lu %ld\n", g->gcstate, g->nblocks, g->GCthreshold, lim);*/
629 while (lim > 0) lim = singlestep(L, lim);
628 g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/2; 630 g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/2;
629luaC_checkall(L); 631/*printf("- %d %lu %lu %ld\n", g->gcstate, g->nblocks, g->GCthreshold, lim);*/
632 lua_assert((long)g->nblocks + (long)GCSTEPSIZE >= lim/2);
633}
634
635
636void luaC_fullgc (lua_State *L) {
637 global_State *g = G(L);
638 while (g->gcstate != GCSfinalize) singlestep(L, MAXLMEM);
639 markroot(L);
640 while (g->gcstate != GCSfinalize) singlestep(L, MAXLMEM);
641 luaC_callGCTM(L); /* call finalizers */
642 g->GCthreshold = g->nblocks + GCSTEPSIZE;
630} 643}
631 644
632 645
633void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { 646void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
634 global_State *g = G(L); 647 global_State *g = G(L);
635 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); 648 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
649 lua_assert(g->gcstate != GCSfinalize);
636 if (g->gcstate != GCSpropagate) /* sweeping phases? */ 650 if (g->gcstate != GCSpropagate) /* sweeping phases? */
637 black2gray(o); /* just mark as gray to avoid other barriers */ 651 black2gray(o); /* just mark as gray to avoid other barriers */
638 else /* breaking invariant! */ 652 else /* breaking invariant! */
diff --git a/lgc.h b/lgc.h
index a6901076..eae99a98 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.h,v 2.2 2003/12/12 18:29:34 roberto Exp roberto $ 2** $Id: lgc.h,v 2.3 2004/02/16 19:09:52 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*/
@@ -85,6 +85,7 @@ size_t luaC_separateudata (lua_State *L, int all);
85void luaC_callGCTM (lua_State *L); 85void luaC_callGCTM (lua_State *L);
86void luaC_sweepall (lua_State *L); 86void 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_link (lua_State *L, GCObject *o, lu_byte tt); 89void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
89void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); 90void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
90 91
diff --git a/lua.h b/lua.h
index 4f2f256d..1bf74610 100644
--- a/lua.h
+++ b/lua.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.h,v 1.185 2003/11/05 11:59:14 roberto Exp roberto $ 2** $Id: lua.h,v 1.186 2003/12/10 11:04:54 roberto Exp roberto $
3** Lua - An Extensible Extension Language 3** Lua - An Extensible Extension Language
4** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil 4** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
5** http://www.lua.org mailto:info@lua.org 5** http://www.lua.org mailto:info@lua.org
@@ -221,11 +221,16 @@ LUA_API int lua_yield (lua_State *L, int nresults);
221LUA_API int lua_resume (lua_State *L, int narg); 221LUA_API int lua_resume (lua_State *L, int narg);
222 222
223/* 223/*
224** garbage-collection functions 224** garbage-collection function and options
225*/ 225*/
226LUA_API int lua_getgcthreshold (lua_State *L); 226
227LUA_API int lua_getgccount (lua_State *L); 227#define LUA_GCSTOP 0
228LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold); 228#define LUA_GCRESTART 1
229#define LUA_GCCOLLECT 2
230#define LUA_GCCOUNT 3
231
232LUA_API int lua_gc (lua_State *L, int what, int data);
233
229 234
230/* 235/*
231** miscellaneous functions 236** miscellaneous functions
@@ -287,6 +292,8 @@ LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud);
287 292
288#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) 293#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
289 294
295#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
296
290 297
291/* compatibility with ref system */ 298/* compatibility with ref system */
292 299