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 | } |
