diff options
| -rw-r--r-- | lapi.c | 10 | ||||
| -rw-r--r-- | lbaselib.c | 6 | ||||
| -rw-r--r-- | lgc.c | 183 | ||||
| -rw-r--r-- | lgc.h | 9 | ||||
| -rw-r--r-- | lstate.c | 3 | ||||
| -rw-r--r-- | lstate.h | 8 | ||||
| -rw-r--r-- | ltests.c | 12 | ||||
| -rw-r--r-- | lua.h | 4 |
8 files changed, 195 insertions, 40 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lapi.c,v 2.258 2016/01/05 16:07:21 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.259 2016/02/29 14:27:14 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 | */ |
| @@ -1097,6 +1097,14 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { | |||
| 1097 | res = g->gcrunning; | 1097 | res = g->gcrunning; |
| 1098 | break; | 1098 | break; |
| 1099 | } | 1099 | } |
| 1100 | case LUA_GCGEN: { | ||
| 1101 | luaC_changemode(L, KGC_GEN); | ||
| 1102 | break; | ||
| 1103 | } | ||
| 1104 | case LUA_GCINC: { | ||
| 1105 | luaC_changemode(L, KGC_NORMAL); | ||
| 1106 | break; | ||
| 1107 | } | ||
| 1100 | default: res = -1; /* invalid option */ | 1108 | default: res = -1; /* invalid option */ |
| 1101 | } | 1109 | } |
| 1102 | lua_unlock(L); | 1110 | lua_unlock(L); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lbaselib.c,v 1.313 2016/04/11 19:18:40 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.314 2016/09/05 19:06:34 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 | */ |
| @@ -173,10 +173,10 @@ static int luaB_rawset (lua_State *L) { | |||
| 173 | static int luaB_collectgarbage (lua_State *L) { | 173 | static int luaB_collectgarbage (lua_State *L) { |
| 174 | static const char *const opts[] = {"stop", "restart", "collect", | 174 | static const char *const opts[] = {"stop", "restart", "collect", |
| 175 | "count", "step", "setpause", "setstepmul", | 175 | "count", "step", "setpause", "setstepmul", |
| 176 | "isrunning", NULL}; | 176 | "isrunning", "generational", "incremental", NULL}; |
| 177 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, | 177 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, |
| 178 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, | 178 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, |
| 179 | LUA_GCISRUNNING}; | 179 | LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; |
| 180 | int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; | 180 | int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; |
| 181 | int ex = (int)luaL_optinteger(L, 2, 0); | 181 | int ex = (int)luaL_optinteger(L, 2, 0); |
| 182 | int res = lua_gc(L, o, ex); | 182 | int res = lua_gc(L, o, ex); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 2.214 2016/11/07 12:38:35 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.215 2016/12/22 13:08:50 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 | */ |
| @@ -59,11 +59,10 @@ | |||
| 59 | #define PAUSEADJ 100 | 59 | #define PAUSEADJ 100 |
| 60 | 60 | ||
| 61 | 61 | ||
| 62 | /* | 62 | /* mask to erase all color bits */ |
| 63 | ** 'makewhite' erases all color bits then sets only the current white | ||
| 64 | ** bit | ||
| 65 | */ | ||
| 66 | #define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS)) | 63 | #define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS)) |
| 64 | |||
| 65 | /* macro to erase all color bits then sets only the current white bit */ | ||
| 67 | #define makewhite(g,x) \ | 66 | #define makewhite(g,x) \ |
| 68 | (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g))) | 67 | (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g))) |
| 69 | 68 | ||
| @@ -92,6 +91,7 @@ | |||
| 92 | #define markobjectN(g,t) { if (t) markobject(g,t); } | 91 | #define markobjectN(g,t) { if (t) markobject(g,t); } |
| 93 | 92 | ||
| 94 | static void reallymarkobject (global_State *g, GCObject *o); | 93 | static void reallymarkobject (global_State *g, GCObject *o); |
| 94 | static l_mem atomic (lua_State *L); | ||
| 95 | 95 | ||
| 96 | 96 | ||
| 97 | /* | 97 | /* |
| @@ -155,8 +155,11 @@ static int iscleared (global_State *g, const TValue *o) { | |||
| 155 | void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { | 155 | void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { |
| 156 | global_State *g = G(L); | 156 | global_State *g = G(L); |
| 157 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); | 157 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); |
| 158 | if (keepinvariant(g)) /* must keep invariant? */ | 158 | if (keepinvariant(g)) { /* must keep invariant? */ |
| 159 | reallymarkobject(g, v); /* restore invariant */ | 159 | reallymarkobject(g, v); /* restore invariant */ |
| 160 | if (isold(o)) | ||
| 161 | l_setbit((v)->marked, OLDBIT); | ||
| 162 | } | ||
| 160 | else { /* sweep phase */ | 163 | else { /* sweep phase */ |
| 161 | lua_assert(issweepphase(g)); | 164 | lua_assert(issweepphase(g)); |
| 162 | makewhite(g, o); /* mark main obj. as white to avoid other barriers */ | 165 | makewhite(g, o); /* mark main obj. as white to avoid other barriers */ |
| @@ -186,8 +189,10 @@ void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) { | |||
| 186 | global_State *g = G(L); | 189 | global_State *g = G(L); |
| 187 | GCObject *o = gcvalue(uv->v); | 190 | GCObject *o = gcvalue(uv->v); |
| 188 | lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ | 191 | lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ |
| 189 | if (keepinvariant(g)) | 192 | if (keepinvariant(g)) { |
| 190 | markobject(g, o); | 193 | markobject(g, o); |
| 194 | l_setbit((o)->marked, OLDBIT); | ||
| 195 | } | ||
| 191 | } | 196 | } |
| 192 | 197 | ||
| 193 | 198 | ||
| @@ -922,6 +927,121 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
| 922 | /* }====================================================== */ | 927 | /* }====================================================== */ |
| 923 | 928 | ||
| 924 | 929 | ||
| 930 | /* | ||
| 931 | ** {====================================================== | ||
| 932 | ** Generational Collector | ||
| 933 | ** ======================================================= | ||
| 934 | */ | ||
| 935 | |||
| 936 | |||
| 937 | #if 0 | ||
| 938 | static int count (GCObject *p, GCObject *limit) { | ||
| 939 | int res = 0; | ||
| 940 | for (; p != NULL && p != limit; p = p->next) | ||
| 941 | res++; | ||
| 942 | return res; | ||
| 943 | } | ||
| 944 | #endif | ||
| 945 | |||
| 946 | |||
| 947 | static GCObject **sweepgen (lua_State *L, GCObject **p, GCObject *limit, | ||
| 948 | int zeromask, int onemask) { | ||
| 949 | global_State *g = G(L); | ||
| 950 | int ow = otherwhite(g); | ||
| 951 | GCObject *curr; | ||
| 952 | while ((curr = *p) != limit) { | ||
| 953 | int marked = curr->marked; | ||
| 954 | if (isdeadm(ow, marked)) { /* is 'curr' dead? */ | ||
| 955 | lua_assert(!isold(curr)); | ||
| 956 | *p = curr->next; /* remove 'curr' from list */ | ||
| 957 | freeobj(L, curr); /* erase 'curr' */ | ||
| 958 | } | ||
| 959 | else { /* correct mark */ | ||
| 960 | if (!isold(curr)) /* don't change old objects */ | ||
| 961 | curr->marked = cast_byte((marked & zeromask) | onemask); | ||
| 962 | p = &curr->next; /* go to next element */ | ||
| 963 | } | ||
| 964 | } | ||
| 965 | return p; | ||
| 966 | } | ||
| 967 | |||
| 968 | |||
| 969 | static void startgencycle (lua_State *L, global_State *g) { | ||
| 970 | propagateall(g); | ||
| 971 | atomic(L); | ||
| 972 | } | ||
| 973 | |||
| 974 | |||
| 975 | static void finishgencycle (lua_State *L, global_State *g, int mask) { | ||
| 976 | sweepgen(L, &g->finobj, NULL, ~0, mask); | ||
| 977 | sweepgen(L, &g->tobefnz, NULL, ~0, mask); | ||
| 978 | checkSizes(L, g); | ||
| 979 | g->gcstate = GCSpropagate; /* skip restart */ | ||
| 980 | callallpendingfinalizers(L); | ||
| 981 | } | ||
| 982 | |||
| 983 | |||
| 984 | static void youngcollection (lua_State *L, global_State *g) { | ||
| 985 | GCObject **psurvival; | ||
| 986 | lua_assert(g->gcstate == GCSpropagate); | ||
| 987 | startgencycle(L, g); | ||
| 988 | /* sweep nursery */ | ||
| 989 | psurvival = sweepgen(L, &g->allgc, g->survival, maskcolors, luaC_white(g)); | ||
| 990 | lua_assert(*psurvival == g->survival); | ||
| 991 | /* sweep 'survival' list, making elements old */ | ||
| 992 | sweepgen(L, psurvival, g->old, ~0, bitmask(OLDBIT)); | ||
| 993 | /* incorporate 'survival' list into old list */ | ||
| 994 | g->old = *psurvival; | ||
| 995 | /* surviving young objects go to 'survival' list */ | ||
| 996 | g->survival = g->allgc; | ||
| 997 | finishgencycle(L, g, 0); | ||
| 998 | lua_checkmemory(L); | ||
| 999 | } | ||
| 1000 | |||
| 1001 | |||
| 1002 | static void entergen (lua_State *L, global_State *g) { | ||
| 1003 | lua_checkmemory(L); | ||
| 1004 | lua_assert(g->old == NULL && g->survival == NULL); | ||
| 1005 | luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */ | ||
| 1006 | luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ | ||
| 1007 | startgencycle(L, g); | ||
| 1008 | /* sweep all ellements making them old */ | ||
| 1009 | sweepgen(L, &g->allgc, g->survival, ~0, bitmask(OLDBIT)); | ||
| 1010 | /* everything alive now is old; 'survival' is empty */ | ||
| 1011 | g->old = g->survival = g->allgc; | ||
| 1012 | finishgencycle(L, g, bitmask(OLDBIT)); | ||
| 1013 | lua_checkmemory(L); | ||
| 1014 | } | ||
| 1015 | |||
| 1016 | |||
| 1017 | void luaC_changemode (lua_State *L, int newmode) { | ||
| 1018 | global_State *g = G(L); | ||
| 1019 | if (newmode != g->gckind) { /* otherwise, nothing to be done */ | ||
| 1020 | if (newmode == KGC_GEN) /* entering generational mode? */ | ||
| 1021 | entergen(L, g); | ||
| 1022 | else { /* entering incremental mode */ | ||
| 1023 | lua_checkmemory(L); | ||
| 1024 | youngcollection(L, g); | ||
| 1025 | g->old = g->survival = NULL; | ||
| 1026 | lua_checkmemory(L); | ||
| 1027 | } | ||
| 1028 | g->gckind = newmode; | ||
| 1029 | } | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | |||
| 1033 | static void genstep (lua_State *L, global_State *g) { | ||
| 1034 | lu_mem mem; | ||
| 1035 | youngcollection(L, g); | ||
| 1036 | mem = gettotalbytes(g); | ||
| 1037 | luaE_setdebt(g, -((mem / 100) * 20)); | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | |||
| 1041 | |||
| 1042 | |||
| 1043 | /* }====================================================== */ | ||
| 1044 | |||
| 925 | 1045 | ||
| 926 | /* | 1046 | /* |
| 927 | ** {====================================================== | 1047 | ** {====================================================== |
| @@ -963,17 +1083,24 @@ static void entersweep (lua_State *L) { | |||
| 963 | } | 1083 | } |
| 964 | 1084 | ||
| 965 | 1085 | ||
| 1086 | static void deletealllist (lua_State *L, GCObject *p) { | ||
| 1087 | while (p) { | ||
| 1088 | GCObject *next = p->next; | ||
| 1089 | freeobj(L, p); | ||
| 1090 | p = next; | ||
| 1091 | } | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | |||
| 966 | void luaC_freeallobjects (lua_State *L) { | 1095 | void luaC_freeallobjects (lua_State *L) { |
| 967 | global_State *g = G(L); | 1096 | global_State *g = G(L); |
| 968 | separatetobefnz(g, 1); /* separate all objects with finalizers */ | 1097 | separatetobefnz(g, 1); /* separate all objects with finalizers */ |
| 969 | lua_assert(g->finobj == NULL); | 1098 | lua_assert(g->finobj == NULL); |
| 970 | callallpendingfinalizers(L); | 1099 | callallpendingfinalizers(L); |
| 971 | lua_assert(g->tobefnz == NULL); | 1100 | lua_assert(g->tobefnz == NULL); |
| 972 | g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ | 1101 | deletealllist(L, g->finobj); |
| 973 | g->gckind = KGC_NORMAL; | 1102 | deletealllist(L, g->allgc); |
| 974 | sweepwholelist(L, &g->finobj); | 1103 | deletealllist(L, g->fixedgc); /* collect fixed objects */ |
| 975 | sweepwholelist(L, &g->allgc); | ||
| 976 | sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ | ||
| 977 | lua_assert(g->strt.nuse == 0); | 1104 | lua_assert(g->strt.nuse == 0); |
| 978 | } | 1105 | } |
| 979 | 1106 | ||
| @@ -996,6 +1123,7 @@ static l_mem atomic (lua_State *L) { | |||
| 996 | propagateall(g); /* propagate changes */ | 1123 | propagateall(g); /* propagate changes */ |
| 997 | work = g->GCmemtrav; /* stop counting (do not recount 'grayagain') */ | 1124 | work = g->GCmemtrav; /* stop counting (do not recount 'grayagain') */ |
| 998 | g->gray = grayagain; | 1125 | g->gray = grayagain; |
| 1126 | g->grayagain = NULL; | ||
| 999 | propagateall(g); /* traverse 'grayagain' list */ | 1127 | propagateall(g); /* traverse 'grayagain' list */ |
| 1000 | g->GCmemtrav = 0; /* restart counting */ | 1128 | g->GCmemtrav = 0; /* restart counting */ |
| 1001 | convergeephemerons(g); | 1129 | convergeephemerons(g); |
| @@ -1052,10 +1180,10 @@ static lu_mem singlestep (lua_State *L) { | |||
| 1052 | } | 1180 | } |
| 1053 | case GCSpropagate: { | 1181 | case GCSpropagate: { |
| 1054 | g->GCmemtrav = 0; | 1182 | g->GCmemtrav = 0; |
| 1055 | lua_assert(g->gray); | 1183 | if (g->gray == NULL) /* no more gray objects? */ |
| 1056 | propagatemark(g); | ||
| 1057 | if (g->gray == NULL) /* no more gray objects? */ | ||
| 1058 | g->gcstate = GCSatomic; /* finish propagate phase */ | 1184 | g->gcstate = GCSatomic; /* finish propagate phase */ |
| 1185 | else | ||
| 1186 | propagatemark(g); /* traverse one gray object */ | ||
| 1059 | return g->GCmemtrav; /* memory traversed in this step */ | 1187 | return g->GCmemtrav; /* memory traversed in this step */ |
| 1060 | } | 1188 | } |
| 1061 | case GCSatomic: { | 1189 | case GCSatomic: { |
| @@ -1123,15 +1251,10 @@ static l_mem getdebt (global_State *g) { | |||
| 1123 | } | 1251 | } |
| 1124 | 1252 | ||
| 1125 | /* | 1253 | /* |
| 1126 | ** performs a basic GC step when collector is running | 1254 | ** performs a basic incremental step |
| 1127 | */ | 1255 | */ |
| 1128 | void luaC_step (lua_State *L) { | 1256 | static void incstep (lua_State *L, global_State *g) { |
| 1129 | global_State *g = G(L); | 1257 | l_mem debt = getdebt(g); /* GC deficit (to be paid now) */ |
| 1130 | l_mem debt = getdebt(g); /* GC deficit (be paid now) */ | ||
| 1131 | if (!g->gcrunning) { /* not running? */ | ||
| 1132 | luaE_setdebt(g, -GCSTEPSIZE * 10); /* avoid being called too often */ | ||
| 1133 | return; | ||
| 1134 | } | ||
| 1135 | do { /* repeat until pause or enough "credit" (negative debt) */ | 1258 | do { /* repeat until pause or enough "credit" (negative debt) */ |
| 1136 | lu_mem work = singlestep(L); /* perform one single step */ | 1259 | lu_mem work = singlestep(L); /* perform one single step */ |
| 1137 | debt -= work; | 1260 | debt -= work; |
| @@ -1145,6 +1268,19 @@ void luaC_step (lua_State *L) { | |||
| 1145 | } | 1268 | } |
| 1146 | } | 1269 | } |
| 1147 | 1270 | ||
| 1271 | /* | ||
| 1272 | ** performs a basic GC step when collector is running | ||
| 1273 | */ | ||
| 1274 | void luaC_step (lua_State *L) { | ||
| 1275 | global_State *g = G(L); | ||
| 1276 | if (!g->gcrunning) /* not running? */ | ||
| 1277 | luaE_setdebt(g, -GCSTEPSIZE * 10); /* avoid being called too often */ | ||
| 1278 | else if (g->gckind == KGC_NORMAL) | ||
| 1279 | incstep(L, g); | ||
| 1280 | else | ||
| 1281 | genstep(L, g); | ||
| 1282 | } | ||
| 1283 | |||
| 1148 | 1284 | ||
| 1149 | /* | 1285 | /* |
| 1150 | ** Performs a full GC cycle; if 'isemergency', set a flag to avoid | 1286 | ** Performs a full GC cycle; if 'isemergency', set a flag to avoid |
| @@ -1164,7 +1300,6 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
| 1164 | } | 1300 | } |
| 1165 | /* finish any pending sweep phase to start a new cycle */ | 1301 | /* finish any pending sweep phase to start a new cycle */ |
| 1166 | luaC_runtilstate(L, bitmask(GCSpause)); | 1302 | luaC_runtilstate(L, bitmask(GCSpause)); |
| 1167 | luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ | ||
| 1168 | luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ | 1303 | luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ |
| 1169 | /* estimate must be correct after a full GC cycle */ | 1304 | /* estimate must be correct after a full GC cycle */ |
| 1170 | lua_assert(g->GCestimate == gettotalbytes(g)); | 1305 | lua_assert(g->GCestimate == gettotalbytes(g)); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.h,v 2.90 2015/10/21 18:15:15 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.91 2015/12/21 13:02:14 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 | */ |
| @@ -79,7 +79,8 @@ | |||
| 79 | #define WHITE1BIT 1 /* object is white (type 1) */ | 79 | #define WHITE1BIT 1 /* object is white (type 1) */ |
| 80 | #define BLACKBIT 2 /* object is black */ | 80 | #define BLACKBIT 2 /* object is black */ |
| 81 | #define FINALIZEDBIT 3 /* object has been marked for finalization */ | 81 | #define FINALIZEDBIT 3 /* object has been marked for finalization */ |
| 82 | /* bit 7 is currently used by tests (luaL_checkmemory) */ | 82 | #define OLDBIT 4 /* object is old (gen. mode) */ |
| 83 | #define TESTGRAYBIT 7 /* used by tests (luaL_checkmemory) */ | ||
| 83 | 84 | ||
| 84 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) | 85 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) |
| 85 | 86 | ||
| @@ -88,11 +89,12 @@ | |||
| 88 | #define isblack(x) testbit((x)->marked, BLACKBIT) | 89 | #define isblack(x) testbit((x)->marked, BLACKBIT) |
| 89 | #define isgray(x) /* neither white nor black */ \ | 90 | #define isgray(x) /* neither white nor black */ \ |
| 90 | (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT))) | 91 | (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT))) |
| 92 | #define isold(x) testbit((x)->marked, OLDBIT) | ||
| 91 | 93 | ||
| 92 | #define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) | 94 | #define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) |
| 93 | 95 | ||
| 94 | #define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) | 96 | #define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) |
| 95 | #define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) | 97 | #define isdeadm(ow,m) ((m) & (ow)) |
| 96 | #define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) | 98 | #define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) |
| 97 | 99 | ||
| 98 | #define changewhite(x) ((x)->marked ^= WHITEBITS) | 100 | #define changewhite(x) ((x)->marked ^= WHITEBITS) |
| @@ -142,6 +144,7 @@ LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o); | |||
| 142 | LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv); | 144 | LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv); |
| 143 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); | 145 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); |
| 144 | LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv); | 146 | LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv); |
| 147 | LUAI_FUNC void luaC_changemode (lua_State *L, int newmode); | ||
| 145 | 148 | ||
| 146 | 149 | ||
| 147 | #endif | 150 | #endif |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.c,v 2.132 2015/11/02 16:01:41 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.133 2015/11/13 12:16:51 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 | */ |
| @@ -319,6 +319,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
| 319 | g->gcstate = GCSpause; | 319 | g->gcstate = GCSpause; |
| 320 | g->gckind = KGC_NORMAL; | 320 | g->gckind = KGC_NORMAL; |
| 321 | g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL; | 321 | g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL; |
| 322 | g->survival = g->old = NULL; | ||
| 322 | g->sweepgc = NULL; | 323 | g->sweepgc = NULL; |
| 323 | g->gray = g->grayagain = NULL; | 324 | g->gray = g->grayagain = NULL; |
| 324 | g->weak = g->ephemeron = g->allweak = NULL; | 325 | g->weak = g->ephemeron = g->allweak = NULL; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.h,v 2.133 2016/12/22 13:08:50 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.134 2017/02/15 18:52:13 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 | */ |
| @@ -70,7 +70,8 @@ struct lua_longjmp; /* defined in ldo.c */ | |||
| 70 | 70 | ||
| 71 | /* kinds of Garbage Collection */ | 71 | /* kinds of Garbage Collection */ |
| 72 | #define KGC_NORMAL 0 | 72 | #define KGC_NORMAL 0 |
| 73 | #define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ | 73 | #define KGC_GEN 1 /* generational gc */ |
| 74 | #define KGC_EMERGENCY 2 /* gc was forced by an allocation failure */ | ||
| 74 | 75 | ||
| 75 | 76 | ||
| 76 | typedef struct stringtable { | 77 | typedef struct stringtable { |
| @@ -158,6 +159,9 @@ typedef struct global_State { | |||
| 158 | GCObject *allweak; /* list of all-weak tables */ | 159 | GCObject *allweak; /* list of all-weak tables */ |
| 159 | GCObject *tobefnz; /* list of userdata to be GC */ | 160 | GCObject *tobefnz; /* list of userdata to be GC */ |
| 160 | GCObject *fixedgc; /* list of objects not to be collected */ | 161 | GCObject *fixedgc; /* list of objects not to be collected */ |
| 162 | /* fields for generational collector */ | ||
| 163 | GCObject *old; /* start of old objects */ | ||
| 164 | GCObject *survival; /* start of objects that survived one GC cycle */ | ||
| 161 | struct lua_State *twups; /* list of threads with open upvalues */ | 165 | struct lua_State *twups; /* list of threads with open upvalues */ |
| 162 | unsigned int gcfinnum; /* number of finalizers to call in each GC step */ | 166 | unsigned int gcfinnum; /* number of finalizers to call in each GC step */ |
| 163 | int gcpause; /* size of pause between successive GCs */ | 167 | int gcpause; /* size of pause between successive GCs */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltests.c,v 2.210 2016/11/07 12:38:35 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.211 2016/12/04 20:17:24 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 | */ |
| @@ -195,9 +195,13 @@ static int testobjref1 (global_State *g, GCObject *f, GCObject *t) { | |||
| 195 | 195 | ||
| 196 | 196 | ||
| 197 | static void printobj (global_State *g, GCObject *o) { | 197 | static void printobj (global_State *g, GCObject *o) { |
| 198 | printf("||%s(%p)-%c(%02X)||", | 198 | printf("||%s(%p)-%c%c(%02X)||", |
| 199 | ttypename(novariant(o->tt)), (void *)o, | 199 | ttypename(novariant(o->tt)), (void *)o, |
| 200 | isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', o->marked); | 200 | isdead(g,o) ? 'd' : isblack(o) ? 'b' : iswhite(o) ? 'w' : 'g', |
| 201 | testbit(o->marked, OLDBIT) ? 'o' : 'n', | ||
| 202 | o->marked); | ||
| 203 | if (o->tt == LUA_TSHRSTR || o->tt == LUA_TLNGSTR) | ||
| 204 | printf(" '%s'", getstr(gco2ts(o))); | ||
| 201 | } | 205 | } |
| 202 | 206 | ||
| 203 | 207 | ||
| @@ -364,8 +368,6 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) { | |||
| 364 | } | 368 | } |
| 365 | 369 | ||
| 366 | 370 | ||
| 367 | #define TESTGRAYBIT 7 | ||
| 368 | |||
| 369 | static void checkgraylist (global_State *g, GCObject *o) { | 371 | static void checkgraylist (global_State *g, GCObject *o) { |
| 370 | ((void)g); /* better to keep it available if we need to print an object */ | 372 | ((void)g); /* better to keep it available if we need to print an object */ |
| 371 | while (o) { | 373 | while (o) { |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lua.h,v 1.331 2016/05/30 15:53:28 roberto Exp roberto $ | 2 | ** $Id: lua.h,v 1.332 2016/12/22 15:51:20 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 |
| @@ -308,6 +308,8 @@ LUA_API int (lua_isyieldable) (lua_State *L); | |||
| 308 | #define LUA_GCSETPAUSE 6 | 308 | #define LUA_GCSETPAUSE 6 |
| 309 | #define LUA_GCSETSTEPMUL 7 | 309 | #define LUA_GCSETSTEPMUL 7 |
| 310 | #define LUA_GCISRUNNING 9 | 310 | #define LUA_GCISRUNNING 9 |
| 311 | #define LUA_GCGEN 10 | ||
| 312 | #define LUA_GCINC 11 | ||
| 311 | 313 | ||
| 312 | LUA_API int (lua_gc) (lua_State *L, int what, int data); | 314 | LUA_API int (lua_gc) (lua_State *L, int what, int data); |
| 313 | 315 | ||
