diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-02-13 10:11:34 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2014-02-13 10:11:34 -0200 |
commit | 733c58595bb57541e38275103fade1330aeb839d (patch) | |
tree | 313583474068cdde188d72a876c7883d47b9e863 | |
parent | 4a1ed6e6e53f8b208fd21d6ac8b0a34331c43ede (diff) | |
download | lua-733c58595bb57541e38275103fade1330aeb839d.tar.gz lua-733c58595bb57541e38275103fade1330aeb839d.tar.bz2 lua-733c58595bb57541e38275103fade1330aeb839d.zip |
no more local collection
-rw-r--r-- | lapi.c | 9 | ||||
-rw-r--r-- | lbaselib.c | 6 | ||||
-rw-r--r-- | lfunc.c | 3 | ||||
-rw-r--r-- | lgc.c | 184 | ||||
-rw-r--r-- | lgc.h | 31 | ||||
-rw-r--r-- | lstate.c | 18 | ||||
-rw-r--r-- | lstate.h | 8 | ||||
-rw-r--r-- | ltests.c | 67 | ||||
-rw-r--r-- | lua.h | 3 | ||||
-rw-r--r-- | lundump.c | 3 |
10 files changed, 69 insertions, 263 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 2.192 2013/12/30 20:47:58 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.193 2014/01/27 13:34:32 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 | */ |
@@ -589,7 +589,6 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { | |||
589 | while (n--) { | 589 | while (n--) { |
590 | setobj2n(L, &cl->c.upvalue[n], L->top + n); | 590 | setobj2n(L, &cl->c.upvalue[n], L->top + n); |
591 | /* does not need barrier because closure is white */ | 591 | /* does not need barrier because closure is white */ |
592 | valnolocal(L->top + n); /* but needs 'local barrier' */ | ||
593 | } | 592 | } |
594 | setclCvalue(L, L->top, cl); | 593 | setclCvalue(L, L->top, cl); |
595 | } | 594 | } |
@@ -864,7 +863,6 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { | |||
864 | } | 863 | } |
865 | default: { | 864 | default: { |
866 | G(L)->mt[ttnov(obj)] = mt; | 865 | G(L)->mt[ttnov(obj)] = mt; |
867 | if (mt) nolocal(obj2gco(mt)); | ||
868 | break; | 866 | break; |
869 | } | 867 | } |
870 | } | 868 | } |
@@ -1086,11 +1084,6 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { | |||
1086 | g->gcpause = data; | 1084 | g->gcpause = data; |
1087 | break; | 1085 | break; |
1088 | } | 1086 | } |
1089 | case LUA_GCSETLOCALPAUSE: { | ||
1090 | res = g->gclocalpause; | ||
1091 | g->gclocalpause = data; | ||
1092 | break; | ||
1093 | } | ||
1094 | case LUA_GCSETSTEPMUL: { | 1087 | case LUA_GCSETSTEPMUL: { |
1095 | res = g->gcstepmul; | 1088 | res = g->gcstepmul; |
1096 | g->gcstepmul = data; | 1089 | g->gcstepmul = data; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.281 2013/08/05 16:58:28 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.282 2013/09/13 16:21:52 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 | */ |
@@ -175,10 +175,10 @@ static int luaB_rawset (lua_State *L) { | |||
175 | static int luaB_collectgarbage (lua_State *L) { | 175 | static int luaB_collectgarbage (lua_State *L) { |
176 | static const char *const opts[] = {"stop", "restart", "collect", | 176 | static const char *const opts[] = {"stop", "restart", "collect", |
177 | "count", "step", "setpause", "setstepmul", | 177 | "count", "step", "setpause", "setstepmul", |
178 | "setlocalpause", "isrunning", NULL}; | 178 | "isrunning", NULL}; |
179 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, | 179 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, |
180 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, | 180 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, |
181 | LUA_GCSETLOCALPAUSE, LUA_GCISRUNNING}; | 181 | LUA_GCISRUNNING}; |
182 | int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; | 182 | int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; |
183 | int ex = luaL_optint(L, 2, 0); | 183 | int ex = luaL_optint(L, 2, 0); |
184 | int res = lua_gc(L, o, ex); | 184 | int res = lua_gc(L, o, ex); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lfunc.c,v 2.37 2013/08/27 20:04:00 roberto Exp roberto $ | 2 | ** $Id: lfunc.c,v 2.38 2013/09/11 12:26:14 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 | */ |
@@ -86,7 +86,6 @@ void luaF_close (lua_State *L, StkId level) { | |||
86 | 86 | ||
87 | Proto *luaF_newproto (lua_State *L) { | 87 | Proto *luaF_newproto (lua_State *L) { |
88 | Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto))->p; | 88 | Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto))->p; |
89 | nolocal(obj2gco(f)); /* prototypes are never local */ | ||
90 | f->k = NULL; | 89 | f->k = NULL; |
91 | f->sizek = 0; | 90 | f->sizek = 0; |
92 | f->p = NULL; | 91 | f->p = NULL; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.169 2014/02/11 12:18:12 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.170 2014/02/11 12:28:47 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 | */ |
@@ -72,18 +72,11 @@ | |||
72 | lua_longassert(!iscollectable(obj) || righttt(obj)) | 72 | lua_longassert(!iscollectable(obj) || righttt(obj)) |
73 | 73 | ||
74 | 74 | ||
75 | #define marklocalvalue(g,o) { checkconsistency(o); \ | 75 | #define markvalue(g,o) { checkconsistency(o); \ |
76 | if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } | 76 | if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } |
77 | 77 | ||
78 | #define markvalue(g,o) { \ | ||
79 | lua_longassert(!(iscollectable(o) && islocal(gcvalue(o)))); \ | ||
80 | marklocalvalue(g,o); } | ||
81 | |||
82 | #define marklocalobject(g,t) \ | ||
83 | { if ((t) && iswhite(obj2gco(t))) reallymarkobject(g, obj2gco(t)); } | ||
84 | |||
85 | #define markobject(g,t) \ | 78 | #define markobject(g,t) \ |
86 | { lua_assert((t) == NULL || !islocal(obj2gco(t))); marklocalobject(g,t); } | 79 | { if ((t) && iswhite(obj2gco(t))) reallymarkobject(g, obj2gco(t)); } |
87 | 80 | ||
88 | static void reallymarkobject (global_State *g, GCObject *o); | 81 | static void reallymarkobject (global_State *g, GCObject *o); |
89 | 82 | ||
@@ -178,7 +171,6 @@ LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) { | |||
178 | global_State *g = G(L); | 171 | global_State *g = G(L); |
179 | GCObject *o = gcvalue(uv->v); | 172 | GCObject *o = gcvalue(uv->v); |
180 | lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ | 173 | lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ |
181 | nolocal(o); | ||
182 | if (keepinvariant(g)) | 174 | if (keepinvariant(g)) |
183 | markobject(g, o); | 175 | markobject(g, o); |
184 | } | 176 | } |
@@ -186,9 +178,9 @@ LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) { | |||
186 | 178 | ||
187 | void luaC_fix (lua_State *L, GCObject *o) { | 179 | void luaC_fix (lua_State *L, GCObject *o) { |
188 | global_State *g = G(L); | 180 | global_State *g = G(L); |
189 | lua_assert(g->localgc == o); | 181 | lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ |
190 | white2gray(o); | 182 | white2gray(o); /* they will be gray forever */ |
191 | g->localgc = o->gch.next; /* remove object from 'localgc' list */ | 183 | g->allgc = o->gch.next; /* remove object from 'allgc' list */ |
192 | o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */ | 184 | o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */ |
193 | g->fixedgc = o; | 185 | g->fixedgc = o; |
194 | } | 186 | } |
@@ -196,15 +188,15 @@ void luaC_fix (lua_State *L, GCObject *o) { | |||
196 | 188 | ||
197 | /* | 189 | /* |
198 | ** create a new collectable object (with given type and size) and link | 190 | ** create a new collectable object (with given type and size) and link |
199 | ** it to 'localgc' list. | 191 | ** it to 'allgc' list. |
200 | */ | 192 | */ |
201 | GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { | 193 | GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { |
202 | global_State *g = G(L); | 194 | global_State *g = G(L); |
203 | GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); | 195 | GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); |
204 | gch(o)->marked = luaC_white(g); | 196 | gch(o)->marked = luaC_white(g); |
205 | gch(o)->tt = tt; | 197 | gch(o)->tt = tt; |
206 | gch(o)->next = g->localgc; | 198 | gch(o)->next = g->allgc; |
207 | g->localgc = o; | 199 | g->allgc = o; |
208 | return o; | 200 | return o; |
209 | } | 201 | } |
210 | 202 | ||
@@ -289,7 +281,7 @@ static void markmt (global_State *g) { | |||
289 | static void markbeingfnz (global_State *g) { | 281 | static void markbeingfnz (global_State *g) { |
290 | GCObject *o; | 282 | GCObject *o; |
291 | for (o = g->tobefnz; o != NULL; o = gch(o)->next) | 283 | for (o = g->tobefnz; o != NULL; o = gch(o)->next) |
292 | marklocalobject(g, o); | 284 | markobject(g, o); |
293 | } | 285 | } |
294 | 286 | ||
295 | 287 | ||
@@ -306,7 +298,7 @@ static void remarkupvals (global_State *g) { | |||
306 | UpVal *uv = gco2th(thread)->openupval; | 298 | UpVal *uv = gco2th(thread)->openupval; |
307 | for (; uv != NULL; uv = uv->u.op.next) { | 299 | for (; uv != NULL; uv = uv->u.op.next) { |
308 | if (uv->u.op.touched) { | 300 | if (uv->u.op.touched) { |
309 | marklocalvalue(g, uv->v); /* remark upvalue's value */ | 301 | markvalue(g, uv->v); /* remark upvalue's value */ |
310 | uv->u.op.touched = 0; | 302 | uv->u.op.touched = 0; |
311 | } | 303 | } |
312 | } | 304 | } |
@@ -463,7 +455,7 @@ static int traverseproto (global_State *g, Proto *f) { | |||
463 | static lu_mem traverseCclosure (global_State *g, CClosure *cl) { | 455 | static lu_mem traverseCclosure (global_State *g, CClosure *cl) { |
464 | int i; | 456 | int i; |
465 | for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ | 457 | for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ |
466 | marklocalvalue(g, &cl->upvalue[i]); | 458 | markvalue(g, &cl->upvalue[i]); |
467 | return sizeCclosure(cl->nupvalues); | 459 | return sizeCclosure(cl->nupvalues); |
468 | } | 460 | } |
469 | 461 | ||
@@ -489,7 +481,7 @@ static lu_mem traversestack (global_State *g, lua_State *th) { | |||
489 | if (o == NULL) | 481 | if (o == NULL) |
490 | return 1; /* stack not completely built yet */ | 482 | return 1; /* stack not completely built yet */ |
491 | for (; o < th->top; o++) /* mark live elements in the stack */ | 483 | for (; o < th->top; o++) /* mark live elements in the stack */ |
492 | marklocalvalue(g, o); | 484 | markvalue(g, o); |
493 | if (g->gcstate == GCSatomic) { /* final traversal? */ | 485 | if (g->gcstate == GCSatomic) { /* final traversal? */ |
494 | StkId lim = th->stack + th->stacksize; /* real end of stack */ | 486 | StkId lim = th->stack + th->stacksize; /* real end of stack */ |
495 | for (; o < lim; o++) /* clear not-marked stack slice */ | 487 | for (; o < lim; o++) /* clear not-marked stack slice */ |
@@ -769,16 +761,8 @@ static GCObject *udata2finalize (global_State *g) { | |||
769 | GCObject *o = g->tobefnz; /* get first element */ | 761 | GCObject *o = g->tobefnz; /* get first element */ |
770 | lua_assert(tofinalize(o)); | 762 | lua_assert(tofinalize(o)); |
771 | g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ | 763 | g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ |
772 | if (islocal(o)) { | 764 | gch(o)->next = g->allgc; /* return it to 'allgc' list */ |
773 | gch(o)->next = g->localgc; /* return it to 'localgc' list */ | 765 | g->allgc = o; |
774 | g->localgc = o; | ||
775 | resetbit(gch(o)->marked, LOCALMARK); | ||
776 | } | ||
777 | else { /* return it to 'allgc' list */ | ||
778 | gch(o)->next = g->allgc; | ||
779 | g->allgc = o; | ||
780 | l_setbit(gch(o)->marked, LOCALMARK); | ||
781 | } | ||
782 | resetbit(gch(o)->marked, FINALIZEDBIT); /* object is "normal" again */ | 766 | resetbit(gch(o)->marked, FINALIZEDBIT); /* object is "normal" again */ |
783 | if (issweepphase(g)) | 767 | if (issweepphase(g)) |
784 | makewhite(g, o); /* "sweep" object */ | 768 | makewhite(g, o); /* "sweep" object */ |
@@ -882,8 +866,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
882 | g->sweepgc = sweeptolive(L, g->sweepgc, NULL); | 866 | g->sweepgc = sweeptolive(L, g->sweepgc, NULL); |
883 | } | 867 | } |
884 | /* search for pointer pointing to 'o' */ | 868 | /* search for pointer pointing to 'o' */ |
885 | p = (testbit(o->gch.marked, LOCALMARK)) ? &g->allgc : &g->localgc; | 869 | for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ } |
886 | for (; *p != o; p = &gch(*p)->next) { /* empty */ } | ||
887 | *p = o->gch.next; /* remove 'o' from its list */ | 870 | *p = o->gch.next; /* remove 'o' from its list */ |
888 | o->gch.next = g->finobj; /* link it in "fin" list */ | 871 | o->gch.next = g->finobj; /* link it in "fin" list */ |
889 | g->finobj = o; | 872 | g->finobj = o; |
@@ -896,105 +879,6 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
896 | /* }====================================================== */ | 879 | /* }====================================================== */ |
897 | 880 | ||
898 | 881 | ||
899 | /* | ||
900 | ** {====================================================== | ||
901 | ** Local Collection | ||
902 | ** ======================================================= | ||
903 | */ | ||
904 | |||
905 | |||
906 | /* | ||
907 | ** Traverse a thread, local marking all its collectable objects | ||
908 | */ | ||
909 | static void localmarkthread (lua_State *l) { | ||
910 | StkId o = l->stack; | ||
911 | StkId lim = l->stack + l->stacksize; /* real end of stack */ | ||
912 | if (o == NULL) | ||
913 | return; /* stack not completely built yet */ | ||
914 | for (; o < l->top; o++) { /* mark live elements in the stack */ | ||
915 | if (iscollectable(o)) | ||
916 | l_setbit(gcvalue(o)->gch.marked, LOCALMARK); | ||
917 | } | ||
918 | for (; o < lim; o++) /* clear not-marked stack slice */ | ||
919 | setnilvalue(o); | ||
920 | } | ||
921 | |||
922 | |||
923 | /* | ||
924 | ** Mark all that is locally accessible (accessible directly from | ||
925 | ** a thread) | ||
926 | */ | ||
927 | static void localmark (global_State *g) { | ||
928 | GCObject *thread = obj2gco(g->mainthread); | ||
929 | for (; thread != NULL; thread = gch(thread)->next) /* traverse all threads */ | ||
930 | localmarkthread(gco2th(thread)); | ||
931 | } | ||
932 | |||
933 | |||
934 | static void localsweep (lua_State *L, global_State *g) { | ||
935 | GCObject **p = &g->localgc; | ||
936 | while (*p != NULL) { | ||
937 | GCObject *curr = *p; | ||
938 | if (!islocal(curr)) { /* is 'curr' no more local? */ | ||
939 | *p = curr->gch.next; /* remove 'curr' from list */ | ||
940 | curr->gch.next = g->allgc; /* link 'curr' in 'allgc' list */ | ||
941 | g->allgc = curr; | ||
942 | /* mark it as out of local list */ | ||
943 | l_setbit(curr->gch.marked, LOCALMARK); | ||
944 | } | ||
945 | else { /* still local */ | ||
946 | if (testbit(curr->gch.marked, LOCALMARK)) { /* locally alive? */ | ||
947 | resetbit(curr->gch.marked, LOCALMARK); | ||
948 | p = &curr->gch.next; /* go to next element */ | ||
949 | } | ||
950 | else { /* object is dead */ | ||
951 | if (curr->gch.tt == LUA_TLCL) { /* is it a Lua closure? */ | ||
952 | if (gco2lcl(curr)->p->cache == gco2cl(curr)) | ||
953 | gco2lcl(curr)->p->cache = NULL; /* clear cache */ | ||
954 | } | ||
955 | *p = curr->gch.next; /* remove 'curr' from list */ | ||
956 | freeobj(L, curr); /* erase 'curr' */ | ||
957 | } | ||
958 | } | ||
959 | } | ||
960 | } | ||
961 | |||
962 | |||
963 | static void separatelocal (global_State *g) { | ||
964 | GCObject **p = &g->finobj; | ||
965 | GCObject **lastnext = findlast(&g->tobefnz); | ||
966 | while (*p != NULL) { | ||
967 | GCObject *curr = *p; | ||
968 | if (!islocal(curr)) /* is 'curr' no more local? */ | ||
969 | p = &curr->gch.next; /* go to next element */ | ||
970 | else { /* still local */ | ||
971 | if (testbit(curr->gch.marked, LOCALMARK)) { /* locally alive? */ | ||
972 | resetbit(curr->gch.marked, LOCALMARK); | ||
973 | p = &curr->gch.next; /* go to next element */ | ||
974 | } | ||
975 | else { /* object is "dead" */ | ||
976 | *p = curr->gch.next; /* remove 'curr' from list */ | ||
977 | curr->gch.next = *lastnext; /* link at the end of 'tobefnz' list */ | ||
978 | *lastnext = curr; | ||
979 | lastnext = &curr->gch.next; | ||
980 | } | ||
981 | } | ||
982 | } | ||
983 | } | ||
984 | |||
985 | |||
986 | static void luaC_localcollection (lua_State *L) { | ||
987 | global_State *g = G(L); | ||
988 | lua_assert(g->gcstate == GCSpause); | ||
989 | localmark(g); | ||
990 | localsweep(L, g); | ||
991 | separatelocal(g); | ||
992 | callallpendingfinalizers(L, 1); | ||
993 | } | ||
994 | |||
995 | /* }====================================================== */ | ||
996 | |||
997 | |||
998 | 882 | ||
999 | /* | 883 | /* |
1000 | ** {====================================================== | 884 | ** {====================================================== |
@@ -1008,13 +892,13 @@ static void luaC_localcollection (lua_State *L) { | |||
1008 | ** cycle will start when memory use hits threshold | 892 | ** cycle will start when memory use hits threshold |
1009 | */ | 893 | */ |
1010 | static void setpause (global_State *g, l_mem estimate) { | 894 | static void setpause (global_State *g, l_mem estimate) { |
1011 | l_mem threshold; | 895 | l_mem threshold, debt; |
1012 | estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ | 896 | estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ |
1013 | threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ | 897 | threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ |
1014 | ? estimate * g->gcpause /* no overflow */ | 898 | ? estimate * g->gcpause /* no overflow */ |
1015 | : MAX_LMEM; /* overflow; truncate to maximum */ | 899 | : MAX_LMEM; /* overflow; truncate to maximum */ |
1016 | g->GCthreshold = threshold; | 900 | debt = gettotalbytes(g) - threshold; |
1017 | luaE_setdebt(g, -g->gclocalpause); | 901 | luaE_setdebt(g, debt); |
1018 | } | 902 | } |
1019 | 903 | ||
1020 | 904 | ||
@@ -1029,9 +913,9 @@ static void setpause (global_State *g, l_mem estimate) { | |||
1029 | static int entersweep (lua_State *L) { | 913 | static int entersweep (lua_State *L) { |
1030 | global_State *g = G(L); | 914 | global_State *g = G(L); |
1031 | int n = 0; | 915 | int n = 0; |
1032 | g->gcstate = GCSswplocalgc; | 916 | g->gcstate = GCSswpallgc; |
1033 | lua_assert(g->sweepgc == NULL); | 917 | lua_assert(g->sweepgc == NULL); |
1034 | g->sweepgc = sweeptolive(L, &g->localgc, &n); | 918 | g->sweepgc = sweeptolive(L, &g->allgc, &n); |
1035 | return n; | 919 | return n; |
1036 | } | 920 | } |
1037 | 921 | ||
@@ -1044,7 +928,6 @@ void luaC_freeallobjects (lua_State *L) { | |||
1044 | lua_assert(g->tobefnz == NULL); | 928 | lua_assert(g->tobefnz == NULL); |
1045 | g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ | 929 | g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ |
1046 | g->gckind = KGC_NORMAL; | 930 | g->gckind = KGC_NORMAL; |
1047 | sweepwholelist(L, &g->localgc); | ||
1048 | sweepwholelist(L, &g->finobj); | 931 | sweepwholelist(L, &g->finobj); |
1049 | sweepwholelist(L, &g->allgc); | 932 | sweepwholelist(L, &g->allgc); |
1050 | sweepwholelist(L, &g->mainthread->next); | 933 | sweepwholelist(L, &g->mainthread->next); |
@@ -1136,10 +1019,7 @@ static lu_mem singlestep (lua_State *L) { | |||
1136 | sw = entersweep(L); | 1019 | sw = entersweep(L); |
1137 | return work + sw * GCSWEEPCOST; | 1020 | return work + sw * GCSWEEPCOST; |
1138 | } | 1021 | } |
1139 | case GCSswplocalgc: { /* sweep local objects */ | 1022 | case GCSswpallgc: { /* sweep "regular" objects */ |
1140 | return sweepstep(L, g, GCSswpallgc, &g->allgc); | ||
1141 | } | ||
1142 | case GCSswpallgc: { /* sweep non-local objects */ | ||
1143 | return sweepstep(L, g, GCSswpthreads, &g->mainthread->next); | 1023 | return sweepstep(L, g, GCSswpthreads, &g->mainthread->next); |
1144 | } | 1024 | } |
1145 | case GCSswpthreads: { /* sweep threads */ | 1025 | case GCSswpthreads: { /* sweep threads */ |
@@ -1208,23 +1088,13 @@ void luaC_forcestep (lua_State *L) { | |||
1208 | 1088 | ||
1209 | 1089 | ||
1210 | /* | 1090 | /* |
1211 | ** performs a basic GC step or a local collection when collector is running | 1091 | ** performs a basic GC step when collector is running |
1212 | */ | 1092 | */ |
1213 | void luaC_step (lua_State *L) { | 1093 | void luaC_step (lua_State *L) { |
1214 | global_State *g = G(L); | 1094 | if (!G(L)->gcrunning) |
1215 | if (!g->gcrunning) | 1095 | luaE_setdebt(G(L), -GCSTEPSIZE); /* avoid being called too often */ |
1216 | luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */ | 1096 | else |
1217 | else { | 1097 | luaC_forcestep(L); |
1218 | if (g->gcstate != GCSpause) /* in the middle of a cycle? */ | ||
1219 | luaC_forcestep(L); /* continue it */ | ||
1220 | else { | ||
1221 | luaC_localcollection(L); /* try a local collection */ | ||
1222 | if (gettotalbytes(g) <= g->GCthreshold) /* enough? */ | ||
1223 | luaE_setdebt(g, -g->gclocalpause); | ||
1224 | else /* local collection did not collect enough memory */ | ||
1225 | luaC_forcestep(L); /* start a full collection */ | ||
1226 | } | ||
1227 | } | ||
1228 | } | 1098 | } |
1229 | 1099 | ||
1230 | 1100 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.h,v 2.76 2013/09/11 20:15:31 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.77 2014/02/11 12:18:12 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 | */ |
@@ -38,17 +38,16 @@ | |||
38 | */ | 38 | */ |
39 | #define GCSpropagate 0 | 39 | #define GCSpropagate 0 |
40 | #define GCSatomic 1 | 40 | #define GCSatomic 1 |
41 | #define GCSswplocalgc 2 | 41 | #define GCSswpallgc 2 |
42 | #define GCSswpallgc 3 | 42 | #define GCSswpthreads 3 |
43 | #define GCSswpthreads 4 | 43 | #define GCSswpfinobj 4 |
44 | #define GCSswpfinobj 5 | 44 | #define GCSswptobefnz 5 |
45 | #define GCSswptobefnz 6 | 45 | #define GCSswpend 6 |
46 | #define GCSswpend 7 | 46 | #define GCSpause 7 |
47 | #define GCSpause 8 | ||
48 | 47 | ||
49 | 48 | ||
50 | #define issweepphase(g) \ | 49 | #define issweepphase(g) \ |
51 | (GCSswplocalgc <= (g)->gcstate && (g)->gcstate <= GCSswpend) | 50 | (GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend) |
52 | 51 | ||
53 | 52 | ||
54 | /* | 53 | /* |
@@ -80,8 +79,6 @@ | |||
80 | #define WHITE1BIT 1 /* object is white (type 1) */ | 79 | #define WHITE1BIT 1 /* object is white (type 1) */ |
81 | #define BLACKBIT 2 /* object is black */ | 80 | #define BLACKBIT 2 /* object is black */ |
82 | #define FINALIZEDBIT 3 /* object has been marked for finalization */ | 81 | #define FINALIZEDBIT 3 /* object has been marked for finalization */ |
83 | #define NOLOCALBIT 4 /* object is not local */ | ||
84 | #define LOCALMARK 5 /* object is 'locally marked' or out of local list */ | ||
85 | /* bit 7 is currently used by tests (luaL_checkmemory) */ | 82 | /* bit 7 is currently used by tests (luaL_checkmemory) */ |
86 | 83 | ||
87 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) | 84 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) |
@@ -91,7 +88,6 @@ | |||
91 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) | 88 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) |
92 | #define isgray(x) /* neither white nor black */ \ | 89 | #define isgray(x) /* neither white nor black */ \ |
93 | (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) | 90 | (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) |
94 | #define islocal(x) (!testbit((x)->gch.marked, NOLOCALBIT)) | ||
95 | 91 | ||
96 | #define tofinalize(x) testbit((x)->gch.marked, FINALIZEDBIT) | 92 | #define tofinalize(x) testbit((x)->gch.marked, FINALIZEDBIT) |
97 | 93 | ||
@@ -102,9 +98,6 @@ | |||
102 | #define changewhite(x) ((x)->gch.marked ^= WHITEBITS) | 98 | #define changewhite(x) ((x)->gch.marked ^= WHITEBITS) |
103 | #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) | 99 | #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) |
104 | 100 | ||
105 | #define nolocal(x) l_setbit((x)->gch.marked, NOLOCALBIT) | ||
106 | #define valnolocal(v) { if (iscollectable(v)) nolocal(gcvalue(v)); } | ||
107 | |||
108 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) | 101 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) |
109 | 102 | ||
110 | 103 | ||
@@ -114,17 +107,15 @@ | |||
114 | 107 | ||
115 | 108 | ||
116 | #define luaC_barrier(L,p,v) { \ | 109 | #define luaC_barrier(L,p,v) { \ |
117 | if (iscollectable(v) && \ | 110 | if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \ |
118 | (nolocal(gcvalue(v)), isblack(obj2gco(p)) && iswhite(gcvalue(v)))) \ | ||
119 | luaC_barrier_(L,obj2gco(p),gcvalue(v)); } | 111 | luaC_barrier_(L,obj2gco(p),gcvalue(v)); } |
120 | 112 | ||
121 | #define luaC_barrierback(L,p,v) { \ | 113 | #define luaC_barrierback(L,p,v) { \ |
122 | if (iscollectable(v) && \ | 114 | if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \ |
123 | (nolocal(gcvalue(v)), isblack(obj2gco(p)) && iswhite(gcvalue(v)))) \ | ||
124 | luaC_barrierback_(L,obj2gco(p)); } | 115 | luaC_barrierback_(L,obj2gco(p)); } |
125 | 116 | ||
126 | #define luaC_objbarrier(L,p,o) { \ | 117 | #define luaC_objbarrier(L,p,o) { \ |
127 | if (nolocal(obj2gco(o)), isblack(obj2gco(p)) && iswhite(obj2gco(o))) \ | 118 | if (isblack(obj2gco(p)) && iswhite(obj2gco(o))) \ |
128 | luaC_barrier_(L,obj2gco(p),obj2gco(o)); } | 119 | luaC_barrier_(L,obj2gco(p),obj2gco(o)); } |
129 | 120 | ||
130 | #define luaC_upvalbarrier(L,uv) \ | 121 | #define luaC_upvalbarrier(L,uv) \ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.116 2013/11/08 17:34:22 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.117 2014/02/11 12:18:12 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 | */ |
@@ -30,10 +30,6 @@ | |||
30 | #define LUAI_GCPAUSE 200 /* 200% */ | 30 | #define LUAI_GCPAUSE 200 /* 200% */ |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | #if !defined(LUAI_GCLOCALPAUSE) | ||
34 | #define LUAI_GCLOCALPAUSE (1000 * sizeof(TString)) | ||
35 | #endif | ||
36 | |||
37 | #if !defined(LUAI_GCMUL) | 33 | #if !defined(LUAI_GCMUL) |
38 | #define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ | 34 | #define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ |
39 | #endif | 35 | #endif |
@@ -187,14 +183,12 @@ static void init_registry (lua_State *L, global_State *g) { | |||
187 | Table *registry = luaH_new(L); | 183 | Table *registry = luaH_new(L); |
188 | sethvalue(L, &g->l_registry, registry); | 184 | sethvalue(L, &g->l_registry, registry); |
189 | luaH_resize(L, registry, LUA_RIDX_LAST, 0); | 185 | luaH_resize(L, registry, LUA_RIDX_LAST, 0); |
190 | nolocal(obj2gco(registry)); | ||
191 | /* registry[LUA_RIDX_MAINTHREAD] = L */ | 186 | /* registry[LUA_RIDX_MAINTHREAD] = L */ |
192 | setthvalue(L, &temp, L); /* temp = L */ | 187 | setthvalue(L, &temp, L); /* temp = L */ |
193 | luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); | 188 | luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); |
194 | /* registry[LUA_RIDX_GLOBALS] = table of globals */ | 189 | /* registry[LUA_RIDX_GLOBALS] = table of globals */ |
195 | sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */ | 190 | sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */ |
196 | luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp); | 191 | luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp); |
197 | valnolocal(&temp); /* keep local invariant */ | ||
198 | } | 192 | } |
199 | 193 | ||
200 | 194 | ||
@@ -263,7 +257,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) { | |||
263 | luaC_checkGC(L); | 257 | luaC_checkGC(L); |
264 | /* create new thread */ | 258 | /* create new thread */ |
265 | L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; | 259 | L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; |
266 | L1->marked = luaC_white(g) | bit2mask(NOLOCALBIT, LOCALMARK); | 260 | L1->marked = luaC_white(g); |
267 | L1->tt = LUA_TTHREAD; | 261 | L1->tt = LUA_TTHREAD; |
268 | /* link it on list of threads */ | 262 | /* link it on list of threads */ |
269 | L1->next = g->mainthread->next; | 263 | L1->next = g->mainthread->next; |
@@ -303,7 +297,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
303 | L->next = NULL; | 297 | L->next = NULL; |
304 | L->tt = LUA_TTHREAD; | 298 | L->tt = LUA_TTHREAD; |
305 | g->currentwhite = bitmask(WHITE0BIT); | 299 | g->currentwhite = bitmask(WHITE0BIT); |
306 | L->marked = luaC_white(g) | bit2mask(NOLOCALBIT, LOCALMARK); | 300 | L->marked = luaC_white(g); |
307 | g->gckind = KGC_NORMAL; | 301 | g->gckind = KGC_NORMAL; |
308 | preinit_state(L, g); | 302 | preinit_state(L, g); |
309 | g->frealloc = f; | 303 | g->frealloc = f; |
@@ -312,7 +306,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
312 | g->seed = makeseed(L); | 306 | g->seed = makeseed(L); |
313 | g->gcrunning = 0; /* no GC while building state */ | 307 | g->gcrunning = 0; /* no GC while building state */ |
314 | g->GCestimate = 0; | 308 | g->GCestimate = 0; |
315 | g->GCthreshold = 10000; | ||
316 | g->strt.size = g->strt.nuse = 0; | 309 | g->strt.size = g->strt.nuse = 0; |
317 | g->strt.hash = NULL; | 310 | g->strt.hash = NULL; |
318 | setnilvalue(&g->l_registry); | 311 | setnilvalue(&g->l_registry); |
@@ -320,16 +313,13 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
320 | g->panic = NULL; | 313 | g->panic = NULL; |
321 | g->version = NULL; | 314 | g->version = NULL; |
322 | g->gcstate = GCSpause; | 315 | g->gcstate = GCSpause; |
323 | g->localgc = g->allgc = g->finobj = NULL; | 316 | g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL; |
324 | g->tobefnz = NULL; | ||
325 | g->fixedgc = NULL; | ||
326 | g->sweepgc = NULL; | 317 | g->sweepgc = NULL; |
327 | g->gray = g->grayagain = NULL; | 318 | g->gray = g->grayagain = NULL; |
328 | g->weak = g->ephemeron = g->allweak = NULL; | 319 | g->weak = g->ephemeron = g->allweak = NULL; |
329 | g->totalbytes = sizeof(LG); | 320 | g->totalbytes = sizeof(LG); |
330 | g->GCdebt = 0; | 321 | g->GCdebt = 0; |
331 | g->gcpause = LUAI_GCPAUSE; | 322 | g->gcpause = LUAI_GCPAUSE; |
332 | g->gclocalpause = LUAI_GCLOCALPAUSE; | ||
333 | g->gcstepmul = LUAI_GCMUL; | 323 | g->gcstepmul = LUAI_GCMUL; |
334 | for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; | 324 | for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; |
335 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { | 325 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 2.97 2013/09/17 15:40:06 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.98 2014/02/11 12:18:12 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 | */ |
@@ -22,8 +22,7 @@ | |||
22 | ** the 'CommonHeader' for the link: | 22 | ** the 'CommonHeader' for the link: |
23 | ** | 23 | ** |
24 | ** mainthread->next: all threads; | 24 | ** mainthread->next: all threads; |
25 | ** localgc: all local objects not marked for finalization; | 25 | ** allgc: all objects not marked for finalization; |
26 | ** allgc: all non local objects not marked for finalization; | ||
27 | ** finobj: all objects marked for finalization; | 26 | ** finobj: all objects marked for finalization; |
28 | ** tobefnz: all objects ready to be finalized; | 27 | ** tobefnz: all objects ready to be finalized; |
29 | ** fixedgc: all objects that are not to be collected (currently | 28 | ** fixedgc: all objects that are not to be collected (currently |
@@ -108,7 +107,6 @@ typedef struct global_State { | |||
108 | l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ | 107 | l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ |
109 | lu_mem GCmemtrav; /* memory traversed by the GC */ | 108 | lu_mem GCmemtrav; /* memory traversed by the GC */ |
110 | lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ | 109 | lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ |
111 | lu_mem GCthreshold; /* threshold to start a new GC cycle */ | ||
112 | stringtable strt; /* hash table for strings */ | 110 | stringtable strt; /* hash table for strings */ |
113 | TValue l_registry; | 111 | TValue l_registry; |
114 | unsigned int seed; /* randomized seed for hashes */ | 112 | unsigned int seed; /* randomized seed for hashes */ |
@@ -117,7 +115,6 @@ typedef struct global_State { | |||
117 | lu_byte gckind; /* kind of GC running */ | 115 | lu_byte gckind; /* kind of GC running */ |
118 | lu_byte gcrunning; /* true if GC is running */ | 116 | lu_byte gcrunning; /* true if GC is running */ |
119 | GCObject *allgc; /* list of all collectable objects */ | 117 | GCObject *allgc; /* list of all collectable objects */ |
120 | GCObject *localgc; /* list of local objects */ | ||
121 | GCObject **sweepgc; /* current position of sweep in list */ | 118 | GCObject **sweepgc; /* current position of sweep in list */ |
122 | GCObject *finobj; /* list of collectable objects with finalizers */ | 119 | GCObject *finobj; /* list of collectable objects with finalizers */ |
123 | GCObject *gray; /* list of gray objects */ | 120 | GCObject *gray; /* list of gray objects */ |
@@ -129,7 +126,6 @@ typedef struct global_State { | |||
129 | GCObject *fixedgc; /* list of objects not to be collected */ | 126 | GCObject *fixedgc; /* list of objects not to be collected */ |
130 | Mbuffer buff; /* temporary buffer for string concatenation */ | 127 | Mbuffer buff; /* temporary buffer for string concatenation */ |
131 | int gcpause; /* size of pause between successive GCs */ | 128 | int gcpause; /* size of pause between successive GCs */ |
132 | int gclocalpause; /* size of pause between local collections */ | ||
133 | int gcstepmul; /* GC `granularity' */ | 129 | int gcstepmul; /* GC `granularity' */ |
134 | lua_CFunction panic; /* to be called in unprotected errors */ | 130 | lua_CFunction panic; /* to be called in unprotected errors */ |
135 | struct lua_State *mainthread; | 131 | struct lua_State *mainthread; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltests.c,v 2.162 2013/12/30 20:47:58 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.163 2014/02/11 12:18:12 roberto Exp roberto $ |
3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -188,41 +188,23 @@ static int testobjref1 (global_State *g, GCObject *f, GCObject *t) { | |||
188 | } | 188 | } |
189 | 189 | ||
190 | 190 | ||
191 | /* | ||
192 | ** Check locality | ||
193 | */ | ||
194 | static int testobjref2 (GCObject *f, GCObject *t) { | ||
195 | /* not a local or pointed by a thread? */ | ||
196 | if (!islocal(t) || gch(f)->tt == LUA_TTHREAD) | ||
197 | return 1; /* ok */ | ||
198 | if (gch(f)->tt == LUA_TPROTO && gch(t)->tt == LUA_TLCL) | ||
199 | return 1; /* cache from a prototype */ | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | |||
204 | static void printobj (global_State *g, GCObject *o) { | 191 | static void printobj (global_State *g, GCObject *o) { |
205 | printf("||%s(%p)-%s-%c(%02X)||", | 192 | printf("||%s(%p)-%c(%02X)||", |
206 | ttypename(novariant(gch(o)->tt)), (void *)o, | 193 | ttypename(novariant(gch(o)->tt)), (void *)o, |
207 | islocal(o)?"L":"NL", | ||
208 | isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', gch(o)->marked); | 194 | isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', gch(o)->marked); |
209 | } | 195 | } |
210 | 196 | ||
211 | 197 | ||
212 | static int testobjref (global_State *g, GCObject *f, GCObject *t) { | 198 | static int testobjref (global_State *g, GCObject *f, GCObject *t) { |
213 | int r1 = testobjref1(g,f,t); | 199 | int r1 = testobjref1(g, f, t); |
214 | int r2 = testobjref2(f,t); | 200 | if (!r1) { |
215 | if (!r1 || !r2) { | 201 | printf("%d(%02X) - ", g->gcstate, g->currentwhite); |
216 | if (!r1) | ||
217 | printf("%d(%02X) - ", g->gcstate, g->currentwhite); | ||
218 | else | ||
219 | printf("local violation - "); | ||
220 | printobj(g, f); | 202 | printobj(g, f); |
221 | printf(" -> "); | 203 | printf(" -> "); |
222 | printobj(g, t); | 204 | printobj(g, t); |
223 | printf("\n"); | 205 | printf("\n"); |
224 | } | 206 | } |
225 | return r1 && r2; | 207 | return r1; |
226 | } | 208 | } |
227 | 209 | ||
228 | #define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t))) | 210 | #define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t))) |
@@ -349,7 +331,6 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) { | |||
349 | break; | 331 | break; |
350 | } | 332 | } |
351 | case LUA_TTHREAD: { | 333 | case LUA_TTHREAD: { |
352 | lua_assert(!islocal(o)); | ||
353 | checkstack(g, gco2th(o)); | 334 | checkstack(g, gco2th(o)); |
354 | break; | 335 | break; |
355 | } | 336 | } |
@@ -366,7 +347,10 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) { | |||
366 | break; | 347 | break; |
367 | } | 348 | } |
368 | case LUA_TSHRSTR: | 349 | case LUA_TSHRSTR: |
369 | case LUA_TLNGSTR: break; | 350 | case LUA_TLNGSTR: { |
351 | lua_assert(!isgray(o)); /* strings are never gray */ | ||
352 | break; | ||
353 | } | ||
370 | default: lua_assert(0); | 354 | default: lua_assert(0); |
371 | } | 355 | } |
372 | } | 356 | } |
@@ -431,28 +415,23 @@ int lua_checkmemory (lua_State *L) { | |||
431 | resetbit(g->mainthread->marked, TESTGRAYBIT); | 415 | resetbit(g->mainthread->marked, TESTGRAYBIT); |
432 | lua_assert(g->sweepgc == NULL || issweepphase(g)); | 416 | lua_assert(g->sweepgc == NULL || issweepphase(g)); |
433 | markgrays(g); | 417 | markgrays(g); |
434 | /* check 'localgc' list */ | 418 | /* check 'fixedgc' list */ |
435 | checkgray(g, g->localgc); | 419 | for (o = g->fixedgc; o != NULL; o = gch(o)->next) { |
436 | maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswplocalgc); | 420 | lua_assert(gch(o)->tt == LUA_TSHRSTR && isgray(o)); |
437 | for (o = g->localgc; o != NULL; o = gch(o)->next) { | ||
438 | checkobject(g, o, maybedead); | ||
439 | lua_assert(!tofinalize(o) && !testbit(o->gch.marked, LOCALMARK)); | ||
440 | } | 421 | } |
441 | /* check 'allgc' list */ | 422 | /* check 'allgc' list */ |
442 | checkgray(g, g->allgc); | 423 | checkgray(g, g->allgc); |
443 | maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpallgc); | 424 | maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpallgc); |
444 | for (o = g->allgc; o != NULL; o = gch(o)->next) { | 425 | for (o = g->allgc; o != NULL; o = gch(o)->next) { |
445 | checkobject(g, o, maybedead); | 426 | checkobject(g, o, maybedead); |
446 | lua_assert(!tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); | 427 | lua_assert(!tofinalize(o)); |
447 | lua_assert(testbit(o->gch.marked, NOLOCALBIT)); | ||
448 | } | 428 | } |
449 | /* check thread list */ | 429 | /* check thread list */ |
450 | checkgray(g, obj2gco(g->mainthread)); | 430 | checkgray(g, obj2gco(g->mainthread)); |
451 | maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpthreads); | 431 | maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpthreads); |
452 | for (o = obj2gco(g->mainthread); o != NULL; o = gch(o)->next) { | 432 | for (o = obj2gco(g->mainthread); o != NULL; o = gch(o)->next) { |
453 | checkobject(g, o, maybedead); | 433 | checkobject(g, o, maybedead); |
454 | lua_assert(!tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); | 434 | lua_assert(!tofinalize(o)); |
455 | lua_assert(testbit(o->gch.marked, NOLOCALBIT)); | ||
456 | lua_assert(gch(o)->tt == LUA_TTHREAD); | 435 | lua_assert(gch(o)->tt == LUA_TTHREAD); |
457 | } | 436 | } |
458 | /* check 'finobj' list */ | 437 | /* check 'finobj' list */ |
@@ -460,7 +439,6 @@ int lua_checkmemory (lua_State *L) { | |||
460 | for (o = g->finobj; o != NULL; o = gch(o)->next) { | 439 | for (o = g->finobj; o != NULL; o = gch(o)->next) { |
461 | checkobject(g, o, 0); | 440 | checkobject(g, o, 0); |
462 | lua_assert(tofinalize(o)); | 441 | lua_assert(tofinalize(o)); |
463 | lua_assert(!islocal(o) || !testbit(gch(o)->marked, LOCALMARK)); | ||
464 | lua_assert(gch(o)->tt == LUA_TUSERDATA || gch(o)->tt == LUA_TTABLE); | 442 | lua_assert(gch(o)->tt == LUA_TUSERDATA || gch(o)->tt == LUA_TTABLE); |
465 | } | 443 | } |
466 | /* check 'tobefnz' list */ | 444 | /* check 'tobefnz' list */ |
@@ -636,21 +614,12 @@ static int gc_color (lua_State *L) { | |||
636 | } | 614 | } |
637 | 615 | ||
638 | 616 | ||
639 | static int gc_local (lua_State *L) { | ||
640 | TValue *o; | ||
641 | luaL_checkany(L, 1); | ||
642 | o = obj_at(L, 1); | ||
643 | lua_pushboolean(L, !iscollectable(o) || islocal(gcvalue(o))); | ||
644 | return 1; | ||
645 | } | ||
646 | |||
647 | |||
648 | static int gc_state (lua_State *L) { | 617 | static int gc_state (lua_State *L) { |
649 | static const char *statenames[] = {"propagate", "atomic", | 618 | static const char *statenames[] = {"propagate", "atomic", |
650 | "sweeplocalgc", "sweepallgc", "sweepthreads", "sweepfinobj", | 619 | "sweepallgc", "sweepthreads", "sweepfinobj", |
651 | "sweeptobefnz", "sweepend", "pause", ""}; | 620 | "sweeptobefnz", "sweepend", "pause", ""}; |
652 | static const int states[] = {GCSpropagate, GCSatomic, | 621 | static const int states[] = {GCSpropagate, GCSatomic, |
653 | GCSswplocalgc, GCSswpallgc, GCSswpthreads, GCSswpfinobj, | 622 | GCSswpallgc, GCSswpthreads, GCSswpfinobj, |
654 | GCSswptobefnz, GCSswpend, GCSpause, -1}; | 623 | GCSswptobefnz, GCSswpend, GCSpause, -1}; |
655 | int option = states[luaL_checkoption(L, 1, "", statenames)]; | 624 | int option = states[luaL_checkoption(L, 1, "", statenames)]; |
656 | if (option == -1) { | 625 | if (option == -1) { |
@@ -1459,7 +1428,6 @@ static const struct luaL_Reg tests_funcs[] = { | |||
1459 | {"doonnewstack", doonnewstack}, | 1428 | {"doonnewstack", doonnewstack}, |
1460 | {"doremote", doremote}, | 1429 | {"doremote", doremote}, |
1461 | {"gccolor", gc_color}, | 1430 | {"gccolor", gc_color}, |
1462 | {"isgclocal", gc_local}, | ||
1463 | {"gcstate", gc_state}, | 1431 | {"gcstate", gc_state}, |
1464 | {"getref", getref}, | 1432 | {"getref", getref}, |
1465 | {"hash", hash_query}, | 1433 | {"hash", hash_query}, |
@@ -1509,3 +1477,4 @@ int luaB_opentests (lua_State *L) { | |||
1509 | } | 1477 | } |
1510 | 1478 | ||
1511 | #endif | 1479 | #endif |
1480 | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lua.h,v 1.297 2013/12/18 14:12:03 roberto Exp roberto $ | 2 | ** $Id: lua.h,v 1.298 2013/12/30 20:47:58 roberto Exp roberto $ |
3 | ** Lua - A Scripting Language | 3 | ** Lua - A Scripting Language |
4 | ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) | 4 | ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) |
5 | ** See Copyright Notice at the end of this file | 5 | ** See Copyright Notice at the end of this file |
@@ -294,7 +294,6 @@ LUA_API int (lua_status) (lua_State *L); | |||
294 | #define LUA_GCSTEP 5 | 294 | #define LUA_GCSTEP 5 |
295 | #define LUA_GCSETPAUSE 6 | 295 | #define LUA_GCSETPAUSE 6 |
296 | #define LUA_GCSETSTEPMUL 7 | 296 | #define LUA_GCSETSTEPMUL 7 |
297 | #define LUA_GCSETLOCALPAUSE 8 | ||
298 | #define LUA_GCISRUNNING 9 | 297 | #define LUA_GCISRUNNING 9 |
299 | 298 | ||
300 | LUA_API int (lua_gc) (lua_State *L, int what, int data); | 299 | LUA_API int (lua_gc) (lua_State *L, int what, int data); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lundump.c,v 2.23 2013/04/26 18:48:35 roberto Exp roberto $ | 2 | ** $Id: lundump.c,v 2.24 2013/08/16 18:55:49 roberto Exp roberto $ |
3 | ** load precompiled Lua chunks | 3 | ** load precompiled Lua chunks |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -88,7 +88,6 @@ static TString* LoadString(LoadState* S) | |||
88 | char* s=luaZ_openspace(S->L,S->b,size); | 88 | char* s=luaZ_openspace(S->L,S->b,size); |
89 | LoadBlock(S,s,size*sizeof(char)); | 89 | LoadBlock(S,s,size*sizeof(char)); |
90 | ts = luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ | 90 | ts = luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ |
91 | nolocal(obj2gco(ts)); /* all strings here anchored in non-thread objects */ | ||
92 | return ts; | 91 | return ts; |
93 | } | 92 | } |
94 | } | 93 | } |