aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lapi.c10
-rw-r--r--lbaselib.c6
-rw-r--r--lgc.c183
-rw-r--r--lgc.h9
-rw-r--r--lstate.c3
-rw-r--r--lstate.h8
-rw-r--r--ltests.c12
-rw-r--r--lua.h4
8 files changed, 195 insertions, 40 deletions
diff --git a/lapi.c b/lapi.c
index 1c4d07dd..494fce75 100644
--- a/lapi.c
+++ b/lapi.c
@@ -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);
diff --git a/lbaselib.c b/lbaselib.c
index 98602952..04fdd5c2 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -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) {
173static int luaB_collectgarbage (lua_State *L) { 173static 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);
diff --git a/lgc.c b/lgc.c
index de3f2a21..44e5dc31 100644
--- a/lgc.c
+++ b/lgc.c
@@ -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
94static void reallymarkobject (global_State *g, GCObject *o); 93static void reallymarkobject (global_State *g, GCObject *o);
94static 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) {
155void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { 155void 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
938static 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
947static 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
969static void startgencycle (lua_State *L, global_State *g) {
970 propagateall(g);
971 atomic(L);
972}
973
974
975static 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
984static 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);
998lua_checkmemory(L);
999}
1000
1001
1002static void entergen (lua_State *L, global_State *g) {
1003lua_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));
1013lua_checkmemory(L);
1014}
1015
1016
1017void 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 */
1023lua_checkmemory(L);
1024 youngcollection(L, g);
1025 g->old = g->survival = NULL;
1026lua_checkmemory(L);
1027 }
1028 g->gckind = newmode;
1029 }
1030}
1031
1032
1033static 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
1086static 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
966void luaC_freeallobjects (lua_State *L) { 1095void 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*/
1128void luaC_step (lua_State *L) { 1256static 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*/
1274void 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));
diff --git a/lgc.h b/lgc.h
index 75f24bc0..e75ff85c 100644
--- a/lgc.h
+++ b/lgc.h
@@ -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);
142LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv); 144LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv);
143LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); 145LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
144LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv); 146LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv);
147LUAI_FUNC void luaC_changemode (lua_State *L, int newmode);
145 148
146 149
147#endif 150#endif
diff --git a/lstate.c b/lstate.c
index 11299d37..4900d724 100644
--- a/lstate.c
+++ b/lstate.c
@@ -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;
diff --git a/lstate.h b/lstate.h
index 67efa7f2..51128db1 100644
--- a/lstate.h
+++ b/lstate.h
@@ -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
76typedef struct stringtable { 77typedef 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 */
diff --git a/ltests.c b/ltests.c
index 6dba514a..ac177de8 100644
--- a/ltests.c
+++ b/ltests.c
@@ -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
197static void printobj (global_State *g, GCObject *o) { 197static 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
369static void checkgraylist (global_State *g, GCObject *o) { 371static 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) {
diff --git a/lua.h b/lua.h
index fc4e2388..d9962cec 100644
--- a/lua.h
+++ b/lua.h
@@ -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
312LUA_API int (lua_gc) (lua_State *L, int what, int data); 314LUA_API int (lua_gc) (lua_State *L, int what, int data);
313 315