diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-03-09 14:34:35 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-03-09 14:34:35 -0300 |
commit | b876ec61c03e05ea0c4c02d8ad8abb84cf55e87c (patch) | |
tree | 62224cadfc7273beecb092f0e4a761e4c4f634e5 | |
parent | 898e8a67942186d62aa2cd3dc4ef96fe894788ef (diff) | |
download | lua-b876ec61c03e05ea0c4c02d8ad8abb84cf55e87c.tar.gz lua-b876ec61c03e05ea0c4c02d8ad8abb84cf55e87c.tar.bz2 lua-b876ec61c03e05ea0c4c02d8ad8abb84cf55e87c.zip |
new (temporary?) API for garbage collector
-rw-r--r-- | lapi.c | 55 | ||||
-rw-r--r-- | lbaselib.c | 35 | ||||
-rw-r--r-- | lgc.c | 58 | ||||
-rw-r--r-- | lgc.h | 3 | ||||
-rw-r--r-- | lua.h | 17 |
5 files changed, 101 insertions, 67 deletions
@@ -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 */ | 813 | LUA_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; | |
819 | LUA_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); | |
827 | LUA_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 | ||
835 | LUA_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 | /* |
@@ -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 | ||
187 | static int luaB_gcinfo (lua_State *L) { | 187 | static 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 | ||
194 | static int luaB_collectgarbage (lua_State *L) { | 193 | static 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 | ||
312 | static int luaB_dofile (lua_State *L) { | 329 | static 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 | ||
@@ -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 | ||
586 | void luaC_step (lua_State *L) { | 585 | static 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; | ||
589 | luaC_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 | |||
625 | void 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; |
629 | luaC_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 | |||
636 | void 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 | ||
633 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { | 646 | void 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! */ |
@@ -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); | |||
85 | void luaC_callGCTM (lua_State *L); | 85 | void luaC_callGCTM (lua_State *L); |
86 | void luaC_sweepall (lua_State *L); | 86 | void luaC_sweepall (lua_State *L); |
87 | void luaC_step (lua_State *L); | 87 | void luaC_step (lua_State *L); |
88 | void luaC_fullgc (lua_State *L); | ||
88 | void luaC_link (lua_State *L, GCObject *o, lu_byte tt); | 89 | void luaC_link (lua_State *L, GCObject *o, lu_byte tt); |
89 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); | 90 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); |
90 | 91 | ||
@@ -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); | |||
221 | LUA_API int lua_resume (lua_State *L, int narg); | 221 | LUA_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 | */ |
226 | LUA_API int lua_getgcthreshold (lua_State *L); | 226 | |
227 | LUA_API int lua_getgccount (lua_State *L); | 227 | #define LUA_GCSTOP 0 |
228 | LUA_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 | |||
232 | LUA_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 | ||