diff options
| -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 | ||
