aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lua/ldebug.c51
-rw-r--r--src/lua/ldebug.h5
-rw-r--r--src/lua/ldo.c15
-rw-r--r--src/lua/lfunc.c5
-rw-r--r--src/lua/lgc.c349
-rw-r--r--src/lua/lobject.h3
-rw-r--r--src/lua/lstate.c5
-rw-r--r--src/lua/lstate.h39
-rw-r--r--src/lua/lvm.c2
9 files changed, 303 insertions, 171 deletions
diff --git a/src/lua/ldebug.c b/src/lua/ldebug.c
index afdc2b7..8cb00e5 100644
--- a/src/lua/ldebug.c
+++ b/src/lua/ldebug.c
@@ -33,10 +33,8 @@
33 33
34#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL) 34#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL)
35 35
36 36/* inverse of 'pcRel' */
37/* Active Lua function (given call info) */ 37#define invpcRel(pc, p) ((p)->code + (pc) + 1)
38#define ci_func(ci) (clLvalue(s2v((ci)->func)))
39
40 38
41static const char *funcnamefromcode (lua_State *L, CallInfo *ci, 39static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
42 const char **name); 40 const char **name);
@@ -127,20 +125,18 @@ static void settraps (CallInfo *ci) {
127/* 125/*
128** This function can be called during a signal, under "reasonable" 126** This function can be called during a signal, under "reasonable"
129** assumptions. 127** assumptions.
130** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by 128** Fields 'basehookcount' and 'hookcount' (set by 'resethookcount')
131** 'resethookcount') are for debug only, and it is no problem if they 129** are for debug only, and it is no problem if they get arbitrary
132** get arbitrary values (causes at most one wrong hook call). 'hookmask' 130** values (causes at most one wrong hook call). 'hookmask' is an atomic
133** is an atomic value. We assume that pointers are atomic too (e.g., gcc 131** value. We assume that pointers are atomic too (e.g., gcc ensures that
134** ensures that for all platforms where it runs). Moreover, 'hook' is 132** for all platforms where it runs). Moreover, 'hook' is always checked
135** always checked before being called (see 'luaD_hook'). 133** before being called (see 'luaD_hook').
136*/ 134*/
137LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { 135LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {
138 if (func == NULL || mask == 0) { /* turn off hooks? */ 136 if (func == NULL || mask == 0) { /* turn off hooks? */
139 mask = 0; 137 mask = 0;
140 func = NULL; 138 func = NULL;
141 } 139 }
142 if (isLua(L->ci))
143 L->oldpc = L->ci->u.l.savedpc;
144 L->hook = func; 140 L->hook = func;
145 L->basehookcount = count; 141 L->basehookcount = count;
146 resethookcount(L); 142 resethookcount(L);
@@ -192,8 +188,8 @@ static const char *upvalname (const Proto *p, int uv) {
192static const char *findvararg (CallInfo *ci, int n, StkId *pos) { 188static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
193 if (clLvalue(s2v(ci->func))->p->is_vararg) { 189 if (clLvalue(s2v(ci->func))->p->is_vararg) {
194 int nextra = ci->u.l.nextraargs; 190 int nextra = ci->u.l.nextraargs;
195 if (n <= nextra) { 191 if (n >= -nextra) { /* 'n' is negative */
196 *pos = ci->func - nextra + (n - 1); 192 *pos = ci->func - nextra - (n + 1);
197 return "(vararg)"; /* generic name for any vararg */ 193 return "(vararg)"; /* generic name for any vararg */
198 } 194 }
199 } 195 }
@@ -206,7 +202,7 @@ const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) {
206 const char *name = NULL; 202 const char *name = NULL;
207 if (isLua(ci)) { 203 if (isLua(ci)) {
208 if (n < 0) /* access to vararg values? */ 204 if (n < 0) /* access to vararg values? */
209 return findvararg(ci, -n, pos); 205 return findvararg(ci, n, pos);
210 else 206 else
211 name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); 207 name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
212 } 208 }
@@ -787,18 +783,34 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
787** previous instruction 'oldpc'. 783** previous instruction 'oldpc'.
788*/ 784*/
789static int changedline (const Proto *p, int oldpc, int newpc) { 785static int changedline (const Proto *p, int oldpc, int newpc) {
786 if (p->lineinfo == NULL) /* no debug information? */
787 return 0;
790 while (oldpc++ < newpc) { 788 while (oldpc++ < newpc) {
791 if (p->lineinfo[oldpc] != 0) 789 if (p->lineinfo[oldpc] != 0)
792 return (luaG_getfuncline(p, oldpc - 1) != luaG_getfuncline(p, newpc)); 790 return (luaG_getfuncline(p, oldpc - 1) != luaG_getfuncline(p, newpc));
793 } 791 }
794 return 0; /* no line changes in the way */ 792 return 0; /* no line changes between positions */
795} 793}
796 794
797 795
796/*
797** Traces the execution of a Lua function. Called before the execution
798** of each opcode, when debug is on. 'L->oldpc' stores the last
799** instruction traced, to detect line changes. When entering a new
800** function, 'npci' will be zero and will test as a new line without
801** the need for 'oldpc'; so, 'oldpc' does not need to be initialized
802** before. Some exceptional conditions may return to a function without
803** updating 'oldpc'. In that case, 'oldpc' may be invalid; if so, it is
804** reset to zero. (A wrong but valid 'oldpc' at most causes an extra
805** call to a line hook.)
806*/
798int luaG_traceexec (lua_State *L, const Instruction *pc) { 807int luaG_traceexec (lua_State *L, const Instruction *pc) {
799 CallInfo *ci = L->ci; 808 CallInfo *ci = L->ci;
800 lu_byte mask = L->hookmask; 809 lu_byte mask = L->hookmask;
810 const Proto *p = ci_func(ci)->p;
801 int counthook; 811 int counthook;
812 /* 'L->oldpc' may be invalid; reset it in this case */
813 int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0;
802 if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */ 814 if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */
803 ci->u.l.trap = 0; /* don't need to stop again */ 815 ci->u.l.trap = 0; /* don't need to stop again */
804 return 0; /* turn off 'trap' */ 816 return 0; /* turn off 'trap' */
@@ -819,15 +831,14 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) {
819 if (counthook) 831 if (counthook)
820 luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */ 832 luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */
821 if (mask & LUA_MASKLINE) { 833 if (mask & LUA_MASKLINE) {
822 const Proto *p = ci_func(ci)->p;
823 int npci = pcRel(pc, p); 834 int npci = pcRel(pc, p);
824 if (npci == 0 || /* call linehook when enter a new function, */ 835 if (npci == 0 || /* call linehook when enter a new function, */
825 pc <= L->oldpc || /* when jump back (loop), or when */ 836 pc <= invpcRel(oldpc, p) || /* when jump back (loop), or when */
826 changedline(p, pcRel(L->oldpc, p), npci)) { /* enter new line */ 837 changedline(p, oldpc, npci)) { /* enter new line */
827 int newline = luaG_getfuncline(p, npci); 838 int newline = luaG_getfuncline(p, npci);
828 luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */ 839 luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */
829 } 840 }
830 L->oldpc = pc; /* 'pc' of last call to line hook */ 841 L->oldpc = npci; /* 'pc' of last call to line hook */
831 } 842 }
832 if (L->status == LUA_YIELD) { /* did hook yield? */ 843 if (L->status == LUA_YIELD) { /* did hook yield? */
833 if (counthook) 844 if (counthook)
diff --git a/src/lua/ldebug.h b/src/lua/ldebug.h
index 1fe0efa..a0a5848 100644
--- a/src/lua/ldebug.h
+++ b/src/lua/ldebug.h
@@ -13,6 +13,11 @@
13 13
14#define pcRel(pc, p) (cast_int((pc) - (p)->code) - 1) 14#define pcRel(pc, p) (cast_int((pc) - (p)->code) - 1)
15 15
16
17/* Active Lua function (given call info) */
18#define ci_func(ci) (clLvalue(s2v((ci)->func)))
19
20
16#define resethookcount(L) (L->hookcount = L->basehookcount) 21#define resethookcount(L) (L->hookcount = L->basehookcount)
17 22
18/* 23/*
diff --git a/src/lua/ldo.c b/src/lua/ldo.c
index 4c976a1..5473815 100644
--- a/src/lua/ldo.c
+++ b/src/lua/ldo.c
@@ -327,7 +327,7 @@ static StkId rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) {
327 ptrdiff_t oldtop = savestack(L, L->top); /* hook may change top */ 327 ptrdiff_t oldtop = savestack(L, L->top); /* hook may change top */
328 int delta = 0; 328 int delta = 0;
329 if (isLuacode(ci)) { 329 if (isLuacode(ci)) {
330 Proto *p = clLvalue(s2v(ci->func))->p; 330 Proto *p = ci_func(ci)->p;
331 if (p->is_vararg) 331 if (p->is_vararg)
332 delta = ci->u.l.nextraargs + p->numparams + 1; 332 delta = ci->u.l.nextraargs + p->numparams + 1;
333 if (L->top < ci->top) 333 if (L->top < ci->top)
@@ -340,8 +340,8 @@ static StkId rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) {
340 luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */ 340 luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */
341 ci->func -= delta; 341 ci->func -= delta;
342 } 342 }
343 if (isLua(ci->previous)) 343 if (isLua(ci = ci->previous))
344 L->oldpc = ci->previous->u.l.savedpc; /* update 'oldpc' */ 344 L->oldpc = pcRel(ci->u.l.savedpc, ci_func(ci)->p); /* update 'oldpc' */
345 return restorestack(L, oldtop); 345 return restorestack(L, oldtop);
346} 346}
347 347
@@ -515,14 +515,13 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
515 515
516/* 516/*
517** Similar to 'luaD_call', but does not allow yields during the call. 517** Similar to 'luaD_call', but does not allow yields during the call.
518** If there is a stack overflow, freeing all CI structures will
519** force the subsequent call to invoke 'luaE_extendCI', which then
520** will raise any errors.
521*/ 518*/
522void luaD_callnoyield (lua_State *L, StkId func, int nResults) { 519void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
523 incXCcalls(L); 520 incXCcalls(L);
524 if (getCcalls(L) <= CSTACKERR) /* possible stack overflow? */ 521 if (getCcalls(L) <= CSTACKERR) { /* possible C stack overflow? */
525 luaE_freeCI(L); 522 luaE_exitCcall(L); /* to compensate decrement in next call */
523 luaE_enterCcall(L); /* check properly */
524 }
526 luaD_call(L, func, nResults); 525 luaD_call(L, func, nResults);
527 decXCcalls(L); 526 decXCcalls(L);
528} 527}
diff --git a/src/lua/lfunc.c b/src/lua/lfunc.c
index 10100e5..f8c3c44 100644
--- a/src/lua/lfunc.c
+++ b/src/lua/lfunc.c
@@ -234,9 +234,10 @@ int luaF_close (lua_State *L, StkId level, int status) {
234 luaF_unlinkupval(uv); 234 luaF_unlinkupval(uv);
235 setobj(L, slot, uv->v); /* move value to upvalue slot */ 235 setobj(L, slot, uv->v); /* move value to upvalue slot */
236 uv->v = slot; /* now current value lives here */ 236 uv->v = slot; /* now current value lives here */
237 if (!iswhite(uv)) 237 if (!iswhite(uv)) { /* neither white nor dead? */
238 gray2black(uv); /* closed upvalues cannot be gray */ 238 gray2black(uv); /* closed upvalues cannot be gray */
239 luaC_barrier(L, uv, slot); 239 luaC_barrier(L, uv, slot);
240 }
240 } 241 }
241 return status; 242 return status;
242} 243}
diff --git a/src/lua/lgc.c b/src/lua/lgc.c
index f7fd7a5..cb820f9 100644
--- a/src/lua/lgc.c
+++ b/src/lua/lgc.c
@@ -60,13 +60,16 @@
60#define PAUSEADJ 100 60#define PAUSEADJ 100
61 61
62 62
63/* mask to erase all color bits (plus gen. related stuff) */ 63/* mask to erase all color bits */
64#define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS | AGEBITS)) 64#define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS))
65 65
66/* mask to erase all GC bits */
67#define maskgcbits (maskcolors & ~AGEBITS)
66 68
67/* macro to erase all color bits then sets only the current white bit */ 69
70/* macro to erase all color bits then set only the current white bit */
68#define makewhite(g,x) \ 71#define makewhite(g,x) \
69 (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g))) 72 (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g)))
70 73
71#define white2gray(x) resetbits(x->marked, WHITEBITS) 74#define white2gray(x) resetbits(x->marked, WHITEBITS)
72#define black2gray(x) resetbit(x->marked, BLACKBIT) 75#define black2gray(x) resetbit(x->marked, BLACKBIT)
@@ -77,16 +80,13 @@
77#define keyiswhite(n) (keyiscollectable(n) && iswhite(gckey(n))) 80#define keyiswhite(n) (keyiscollectable(n) && iswhite(gckey(n)))
78 81
79 82
80#define checkconsistency(obj) \
81 lua_longassert(!iscollectable(obj) || righttt(obj))
82
83/* 83/*
84** Protected access to objects in values 84** Protected access to objects in values
85*/ 85*/
86#define gcvalueN(o) (iscollectable(o) ? gcvalue(o) : NULL) 86#define gcvalueN(o) (iscollectable(o) ? gcvalue(o) : NULL)
87 87
88 88
89#define markvalue(g,o) { checkconsistency(o); \ 89#define markvalue(g,o) { checkliveness(g->mainthread,o); \
90 if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } 90 if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
91 91
92#define markkey(g, n) { if keyiswhite(n) reallymarkobject(g,gckey(n)); } 92#define markkey(g, n) { if keyiswhite(n) reallymarkobject(g,gckey(n)); }
@@ -181,14 +181,17 @@ static int iscleared (global_State *g, const GCObject *o) {
181 181
182 182
183/* 183/*
184** barrier that moves collector forward, that is, mark the white object 184** Barrier that moves collector forward, that is, marks the white object
185** 'v' being pointed by the black object 'o'. (If in sweep phase, clear 185** 'v' being pointed by the black object 'o'. In the generational
186** the black object to white [sweep it] to avoid other barrier calls for 186** mode, 'v' must also become old, if 'o' is old; however, it cannot
187** this same object.) In the generational mode, 'v' must also become 187** be changed directly to OLD, because it may still point to non-old
188** old, if 'o' is old; however, it cannot be changed directly to OLD, 188** objects. So, it is marked as OLD0. In the next cycle it will become
189** because it may still point to non-old objects. So, it is marked as 189** OLD1, and in the next it will finally become OLD (regular old). By
190** OLD0. In the next cycle it will become OLD1, and in the next it 190** then, any object it points to will also be old. If called in the
191** will finally become OLD (regular old). 191** incremental sweep phase, it clears the black object to white (sweep
192** it) to avoid other barrier calls for this same object. (That cannot
193** be done is generational mode, as its sweep does not distinguish
194** whites from deads.)
192*/ 195*/
193void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { 196void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
194 global_State *g = G(L); 197 global_State *g = G(L);
@@ -202,7 +205,8 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
202 } 205 }
203 else { /* sweep phase */ 206 else { /* sweep phase */
204 lua_assert(issweepphase(g)); 207 lua_assert(issweepphase(g));
205 makewhite(g, o); /* mark main obj. as white to avoid other barriers */ 208 if (g->gckind == KGC_INC) /* incremental mode? */
209 makewhite(g, o); /* mark 'o' as white to avoid other barriers */
206 } 210 }
207} 211}
208 212
@@ -214,11 +218,12 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
214void luaC_barrierback_ (lua_State *L, GCObject *o) { 218void luaC_barrierback_ (lua_State *L, GCObject *o) {
215 global_State *g = G(L); 219 global_State *g = G(L);
216 lua_assert(isblack(o) && !isdead(g, o)); 220 lua_assert(isblack(o) && !isdead(g, o));
217 lua_assert(g->gckind != KGC_GEN || (isold(o) && getage(o) != G_TOUCHED1)); 221 lua_assert((g->gckind == KGC_GEN) == (isold(o) && getage(o) != G_TOUCHED1));
218 if (getage(o) != G_TOUCHED2) /* not already in gray list? */ 222 if (getage(o) != G_TOUCHED2) /* not already in gray list? */
219 linkobjgclist(o, g->grayagain); /* link it in 'grayagain' */ 223 linkobjgclist(o, g->grayagain); /* link it in 'grayagain' */
220 black2gray(o); /* make object gray (again) */ 224 black2gray(o); /* make object gray (again) */
221 setage(o, G_TOUCHED1); /* touched in current cycle */ 225 if (isold(o)) /* generational mode? */
226 setage(o, G_TOUCHED1); /* touched in current cycle */
222} 227}
223 228
224 229
@@ -324,25 +329,31 @@ static lu_mem markbeingfnz (global_State *g) {
324 329
325 330
326/* 331/*
327** Mark all values stored in marked open upvalues from non-marked threads. 332** For each non-marked thread, simulates a barrier between each open
328** (Values from marked threads were already marked when traversing the 333** upvalue and its value. (If the thread is collected, the value will be
329** thread.) Remove from the list threads that no longer have upvalues and 334** assigned to the upvalue, but then it can be too late for the barrier
330** not-marked threads. 335** to act. The "barrier" does not need to check colors: A non-marked
336** thread must be young; upvalues cannot be older than their threads; so
337** any visited upvalue must be young too.) Also removes the thread from
338** the list, as it was already visited. Removes also threads with no
339** upvalues, as they have nothing to be checked. (If the thread gets an
340** upvalue later, it will be linked in the list again.)
331*/ 341*/
332static int remarkupvals (global_State *g) { 342static int remarkupvals (global_State *g) {
333 lua_State *thread; 343 lua_State *thread;
334 lua_State **p = &g->twups; 344 lua_State **p = &g->twups;
335 int work = 0; 345 int work = 0; /* estimate of how much work was done here */
336 while ((thread = *p) != NULL) { 346 while ((thread = *p) != NULL) {
337 work++; 347 work++;
338 lua_assert(!isblack(thread)); /* threads are never black */ 348 if (!iswhite(thread) && thread->openupval != NULL)
339 if (isgray(thread) && thread->openupval != NULL)
340 p = &thread->twups; /* keep marked thread with upvalues in the list */ 349 p = &thread->twups; /* keep marked thread with upvalues in the list */
341 else { /* thread is not marked or without upvalues */ 350 else { /* thread is not marked or without upvalues */
342 UpVal *uv; 351 UpVal *uv;
352 lua_assert(!isold(thread) || thread->openupval == NULL);
343 *p = thread->twups; /* remove thread from the list */ 353 *p = thread->twups; /* remove thread from the list */
344 thread->twups = thread; /* mark that it is out of list */ 354 thread->twups = thread; /* mark that it is out of list */
345 for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { 355 for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) {
356 lua_assert(getage(uv) <= getage(thread));
346 work++; 357 work++;
347 if (!iswhite(uv)) /* upvalue already visited? */ 358 if (!iswhite(uv)) /* upvalue already visited? */
348 markvalue(g, uv->v); /* mark its value */ 359 markvalue(g, uv->v); /* mark its value */
@@ -353,12 +364,17 @@ static int remarkupvals (global_State *g) {
353} 364}
354 365
355 366
367static void cleargraylists (global_State *g) {
368 g->gray = g->grayagain = NULL;
369 g->weak = g->allweak = g->ephemeron = NULL;
370}
371
372
356/* 373/*
357** mark root set and reset all gray lists, to start a new collection 374** mark root set and reset all gray lists, to start a new collection
358*/ 375*/
359static void restartcollection (global_State *g) { 376static void restartcollection (global_State *g) {
360 g->gray = g->grayagain = NULL; 377 cleargraylists(g);
361 g->weak = g->allweak = g->ephemeron = NULL;
362 markobject(g, g->mainthread); 378 markobject(g, g->mainthread);
363 markvalue(g, &g->l_registry); 379 markvalue(g, &g->l_registry);
364 markmt(g); 380 markmt(g);
@@ -374,6 +390,32 @@ static void restartcollection (global_State *g) {
374** ======================================================= 390** =======================================================
375*/ 391*/
376 392
393
394/*
395** Check whether object 'o' should be kept in the 'grayagain' list for
396** post-processing by 'correctgraylist'. (It could put all old objects
397** in the list and leave all the work to 'correctgraylist', but it is
398** more efficient to avoid adding elements that will be removed.) Only
399** TOUCHED1 objects need to be in the list. TOUCHED2 doesn't need to go
400** back to a gray list, but then it must become OLD. (That is what
401** 'correctgraylist' does when it finds a TOUCHED2 object.)
402** It is defined as a macro because 'gclist' is not a unique field in
403** different collectable objects.
404*/
405#define genlink(g,o) genlink_(g, obj2gco(o), &(o)->gclist)
406
407static void genlink_ (global_State *g, GCObject *o, GCObject **pnext) {
408 lua_assert(isblack(o));
409 if (getage(o) == G_TOUCHED1) { /* touched in this cycle? */
410 *pnext = g->grayagain; /* link it back in 'grayagain' */
411 g->grayagain = o;
412 black2gray(o);
413 } /* everything else do not need to be linked back */
414 else if (getage(o) == G_TOUCHED2)
415 changeage(o, G_TOUCHED2, G_OLD); /* advance age */
416}
417
418
377/* 419/*
378** Traverse a table with weak values and link it to proper list. During 420** Traverse a table with weak values and link it to proper list. During
379** propagate phase, keep it in 'grayagain' list, to be revisited in the 421** propagate phase, keep it in 'grayagain' list, to be revisited in the
@@ -410,8 +452,9 @@ static void traverseweakvalue (global_State *g, Table *h) {
410** the atomic phase, if table has any white->white entry, it has to 452** the atomic phase, if table has any white->white entry, it has to
411** be revisited during ephemeron convergence (as that key may turn 453** be revisited during ephemeron convergence (as that key may turn
412** black). Otherwise, if it has any white key, table has to be cleared 454** black). Otherwise, if it has any white key, table has to be cleared
413** (in the atomic phase). In generational mode, it (like all visited 455** (in the atomic phase). In generational mode, some tables
414** tables) must be kept in some gray list for post-processing. 456** must be kept in some gray list for post-processing; this is done
457** by 'genlink'.
415*/ 458*/
416static int traverseephemeron (global_State *g, Table *h, int inv) { 459static int traverseephemeron (global_State *g, Table *h, int inv) {
417 int marked = 0; /* true if an object is marked in this traversal */ 460 int marked = 0; /* true if an object is marked in this traversal */
@@ -450,10 +493,10 @@ static int traverseephemeron (global_State *g, Table *h, int inv) {
450 linkgclist(h, g->ephemeron); /* have to propagate again */ 493 linkgclist(h, g->ephemeron); /* have to propagate again */
451 else if (hasclears) /* table has white keys? */ 494 else if (hasclears) /* table has white keys? */
452 linkgclist(h, g->allweak); /* may have to clean white keys */ 495 linkgclist(h, g->allweak); /* may have to clean white keys */
453 else if (g->gckind == KGC_GEN) 496 else {
454 linkgclist(h, g->grayagain); /* keep it in some list */ 497 gray2black(h); /* 'genlink' expects black objects */
455 else 498 genlink(g, h); /* check whether collector still needs to see it */
456 gray2black(h); 499 }
457 return marked; 500 return marked;
458} 501}
459 502
@@ -473,10 +516,7 @@ static void traversestrongtable (global_State *g, Table *h) {
473 markvalue(g, gval(n)); 516 markvalue(g, gval(n));
474 } 517 }
475 } 518 }
476 if (g->gckind == KGC_GEN) { 519 genlink(g, h);
477 linkgclist(h, g->grayagain); /* keep it in some gray list */
478 black2gray(h);
479 }
480} 520}
481 521
482 522
@@ -488,7 +528,7 @@ static lu_mem traversetable (global_State *g, Table *h) {
488 (cast_void(weakkey = strchr(svalue(mode), 'k')), 528 (cast_void(weakkey = strchr(svalue(mode), 'k')),
489 cast_void(weakvalue = strchr(svalue(mode), 'v')), 529 cast_void(weakvalue = strchr(svalue(mode), 'v')),
490 (weakkey || weakvalue))) { /* is really weak? */ 530 (weakkey || weakvalue))) { /* is really weak? */
491 black2gray(h); /* keep table gray */ 531 black2gray(h); /* turn it back to gray, as it probably goes to a list */
492 if (!weakkey) /* strong keys? */ 532 if (!weakkey) /* strong keys? */
493 traverseweakvalue(g, h); 533 traverseweakvalue(g, h);
494 else if (!weakvalue) /* strong values? */ 534 else if (!weakvalue) /* strong values? */
@@ -507,10 +547,7 @@ static int traverseudata (global_State *g, Udata *u) {
507 markobjectN(g, u->metatable); /* mark its metatable */ 547 markobjectN(g, u->metatable); /* mark its metatable */
508 for (i = 0; i < u->nuvalue; i++) 548 for (i = 0; i < u->nuvalue; i++)
509 markvalue(g, &u->uv[i].uv); 549 markvalue(g, &u->uv[i].uv);
510 if (g->gckind == KGC_GEN) { 550 genlink(g, u);
511 linkgclist(u, g->grayagain); /* keep it in some gray list */
512 black2gray(u);
513 }
514 return 1 + u->nuvalue; 551 return 1 + u->nuvalue;
515} 552}
516 553
@@ -559,12 +596,23 @@ static int traverseLclosure (global_State *g, LClosure *cl) {
559 596
560/* 597/*
561** Traverse a thread, marking the elements in the stack up to its top 598** Traverse a thread, marking the elements in the stack up to its top
562** and cleaning the rest of the stack in the final traversal. 599** and cleaning the rest of the stack in the final traversal. That
563** That ensures that the entire stack have valid (non-dead) objects. 600** ensures that the entire stack have valid (non-dead) objects.
601** Threads have no barriers. In gen. mode, old threads must be visited
602** at every cycle, because they might point to young objects. In inc.
603** mode, the thread can still be modified before the end of the cycle,
604** and therefore it must be visited again in the atomic phase. To ensure
605** these visits, threads must return to a gray list if they are not new
606** (which can only happen in generational mode) or if the traverse is in
607** the propagate phase (which can only happen in incremental mode).
564*/ 608*/
565static int traversethread (global_State *g, lua_State *th) { 609static int traversethread (global_State *g, lua_State *th) {
566 UpVal *uv; 610 UpVal *uv;
567 StkId o = th->stack; 611 StkId o = th->stack;
612 if (isold(th) || g->gcstate == GCSpropagate) {
613 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */
614 black2gray(th);
615 }
568 if (o == NULL) 616 if (o == NULL)
569 return 1; /* stack not completely built yet */ 617 return 1; /* stack not completely built yet */
570 lua_assert(g->gcstate == GCSatomic || 618 lua_assert(g->gcstate == GCSatomic ||
@@ -603,12 +651,7 @@ static lu_mem propagatemark (global_State *g) {
603 case LUA_VLCL: return traverseLclosure(g, gco2lcl(o)); 651 case LUA_VLCL: return traverseLclosure(g, gco2lcl(o));
604 case LUA_VCCL: return traverseCclosure(g, gco2ccl(o)); 652 case LUA_VCCL: return traverseCclosure(g, gco2ccl(o));
605 case LUA_VPROTO: return traverseproto(g, gco2p(o)); 653 case LUA_VPROTO: return traverseproto(g, gco2p(o));
606 case LUA_VTHREAD: { 654 case LUA_VTHREAD: return traversethread(g, gco2th(o));
607 lua_State *th = gco2th(o);
608 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */
609 black2gray(o);
610 return traversethread(g, th);
611 }
612 default: lua_assert(0); return 0; 655 default: lua_assert(0); return 0;
613 } 656 }
614} 657}
@@ -766,7 +809,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int countin,
766 freeobj(L, curr); /* erase 'curr' */ 809 freeobj(L, curr); /* erase 'curr' */
767 } 810 }
768 else { /* change mark to 'white' */ 811 else { /* change mark to 'white' */
769 curr->marked = cast_byte((marked & maskcolors) | white); 812 curr->marked = cast_byte((marked & maskgcbits) | white);
770 p = &curr->next; /* go to next element */ 813 p = &curr->next; /* go to next element */
771 } 814 }
772 } 815 }
@@ -823,6 +866,8 @@ static GCObject *udata2finalize (global_State *g) {
823 resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */ 866 resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */
824 if (issweepphase(g)) 867 if (issweepphase(g))
825 makewhite(g, o); /* "sweep" object */ 868 makewhite(g, o); /* "sweep" object */
869 else if (getage(o) == G_OLD1)
870 g->firstold1 = o; /* it is the first OLD1 object in the list */
826 return o; 871 return o;
827} 872}
828 873
@@ -896,15 +941,15 @@ static GCObject **findlast (GCObject **p) {
896/* 941/*
897** Move all unreachable objects (or 'all' objects) that need 942** Move all unreachable objects (or 'all' objects) that need
898** finalization from list 'finobj' to list 'tobefnz' (to be finalized). 943** finalization from list 'finobj' to list 'tobefnz' (to be finalized).
899** (Note that objects after 'finobjold' cannot be white, so they 944** (Note that objects after 'finobjold1' cannot be white, so they
900** don't need to be traversed. In incremental mode, 'finobjold' is NULL, 945** don't need to be traversed. In incremental mode, 'finobjold1' is NULL,
901** so the whole list is traversed.) 946** so the whole list is traversed.)
902*/ 947*/
903static void separatetobefnz (global_State *g, int all) { 948static void separatetobefnz (global_State *g, int all) {
904 GCObject *curr; 949 GCObject *curr;
905 GCObject **p = &g->finobj; 950 GCObject **p = &g->finobj;
906 GCObject **lastnext = findlast(&g->tobefnz); 951 GCObject **lastnext = findlast(&g->tobefnz);
907 while ((curr = *p) != g->finobjold) { /* traverse all finalizable objects */ 952 while ((curr = *p) != g->finobjold1) { /* traverse all finalizable objects */
908 lua_assert(tofinalize(curr)); 953 lua_assert(tofinalize(curr));
909 if (!(iswhite(curr) || all)) /* not being collected? */ 954 if (!(iswhite(curr) || all)) /* not being collected? */
910 p = &curr->next; /* don't bother with it */ 955 p = &curr->next; /* don't bother with it */
@@ -921,6 +966,27 @@ static void separatetobefnz (global_State *g, int all) {
921 966
922 967
923/* 968/*
969** If pointer 'p' points to 'o', move it to the next element.
970*/
971static void checkpointer (GCObject **p, GCObject *o) {
972 if (o == *p)
973 *p = o->next;
974}
975
976
977/*
978** Correct pointers to objects inside 'allgc' list when
979** object 'o' is being removed from the list.
980*/
981static void correctpointers (global_State *g, GCObject *o) {
982 checkpointer(&g->survival, o);
983 checkpointer(&g->old1, o);
984 checkpointer(&g->reallyold, o);
985 checkpointer(&g->firstold1, o);
986}
987
988
989/*
924** if object 'o' has a finalizer, remove it from 'allgc' list (must 990** if object 'o' has a finalizer, remove it from 'allgc' list (must
925** search the list to find it) and link it in 'finobj' list. 991** search the list to find it) and link it in 'finobj' list.
926*/ 992*/
@@ -936,14 +1002,8 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
936 if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ 1002 if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */
937 g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */ 1003 g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */
938 } 1004 }
939 else { /* correct pointers into 'allgc' list, if needed */ 1005 else
940 if (o == g->survival) 1006 correctpointers(g, o);
941 g->survival = o->next;
942 if (o == g->old)
943 g->old = o->next;
944 if (o == g->reallyold)
945 g->reallyold = o->next;
946 }
947 /* search for pointer pointing to 'o' */ 1007 /* search for pointer pointing to 'o' */
948 for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } 1008 for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ }
949 *p = o->next; /* remove 'o' from 'allgc' list */ 1009 *p = o->next; /* remove 'o' from 'allgc' list */
@@ -965,24 +1025,30 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
965static void setpause (global_State *g); 1025static void setpause (global_State *g);
966 1026
967 1027
968/* mask to erase all color bits, not changing gen-related stuff */
969#define maskgencolors (~(bitmask(BLACKBIT) | WHITEBITS))
970
971
972/* 1028/*
973** Sweep a list of objects, deleting dead ones and turning 1029** Sweep a list of objects to enter generational mode. Deletes dead
974** the non dead to old (without changing their colors). 1030** objects and turns the non dead to old. All non-dead threads---which
1031** are now old---must be in a gray list. Everything else is not in a
1032** gray list.
975*/ 1033*/
976static void sweep2old (lua_State *L, GCObject **p) { 1034static void sweep2old (lua_State *L, GCObject **p) {
977 GCObject *curr; 1035 GCObject *curr;
1036 global_State *g = G(L);
978 while ((curr = *p) != NULL) { 1037 while ((curr = *p) != NULL) {
979 if (iswhite(curr)) { /* is 'curr' dead? */ 1038 if (iswhite(curr)) { /* is 'curr' dead? */
980 lua_assert(isdead(G(L), curr)); 1039 lua_assert(isdead(g, curr));
981 *p = curr->next; /* remove 'curr' from list */ 1040 *p = curr->next; /* remove 'curr' from list */
982 freeobj(L, curr); /* erase 'curr' */ 1041 freeobj(L, curr); /* erase 'curr' */
983 } 1042 }
984 else { /* all surviving objects become old */ 1043 else { /* all surviving objects become old */
985 setage(curr, G_OLD); 1044 setage(curr, G_OLD);
1045 if (curr->tt == LUA_VTHREAD) { /* threads must be watched */
1046 lua_State *th = gco2th(curr);
1047 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */
1048 black2gray(th); /* OK if already gray */
1049 }
1050 else /* everything else is black */
1051 gray2black(curr); /* OK if already black */
986 p = &curr->next; /* go to next element */ 1052 p = &curr->next; /* go to next element */
987 } 1053 }
988 } 1054 }
@@ -995,9 +1061,13 @@ static void sweep2old (lua_State *L, GCObject **p) {
995** during the sweep. So, any white object must be dead.) For 1061** during the sweep. So, any white object must be dead.) For
996** non-dead objects, advance their ages and clear the color of 1062** non-dead objects, advance their ages and clear the color of
997** new objects. (Old objects keep their colors.) 1063** new objects. (Old objects keep their colors.)
1064** The ages of G_TOUCHED1 and G_TOUCHED2 objects cannot be advanced
1065** here, because these old-generation objects are usually not swept
1066** here. They will all be advanced in 'correctgraylist'. That function
1067** will also remove objects turned white here from any gray list.
998*/ 1068*/
999static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, 1069static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p,
1000 GCObject *limit) { 1070 GCObject *limit, GCObject **pfirstold1) {
1001 static const lu_byte nextage[] = { 1071 static const lu_byte nextage[] = {
1002 G_SURVIVAL, /* from G_NEW */ 1072 G_SURVIVAL, /* from G_NEW */
1003 G_OLD1, /* from G_SURVIVAL */ 1073 G_OLD1, /* from G_SURVIVAL */
@@ -1016,9 +1086,15 @@ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p,
1016 freeobj(L, curr); /* erase 'curr' */ 1086 freeobj(L, curr); /* erase 'curr' */
1017 } 1087 }
1018 else { /* correct mark and age */ 1088 else { /* correct mark and age */
1019 if (getage(curr) == G_NEW) 1089 if (getage(curr) == G_NEW) { /* new objects go back to white */
1020 curr->marked = cast_byte((curr->marked & maskgencolors) | white); 1090 int marked = curr->marked & maskgcbits; /* erase GC bits */
1021 setage(curr, nextage[getage(curr)]); 1091 curr->marked = cast_byte(marked | G_SURVIVAL | white);
1092 }
1093 else { /* all other objects will be old, and so keep their color */
1094 setage(curr, nextage[getage(curr)]);
1095 if (getage(curr) == G_OLD1 && *pfirstold1 == NULL)
1096 *pfirstold1 = curr; /* first OLD1 object in the list */
1097 }
1022 p = &curr->next; /* go to next element */ 1098 p = &curr->next; /* go to next element */
1023 } 1099 }
1024 } 1100 }
@@ -1028,58 +1104,56 @@ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p,
1028 1104
1029/* 1105/*
1030** Traverse a list making all its elements white and clearing their 1106** Traverse a list making all its elements white and clearing their
1031** age. 1107** age. In incremental mode, all objects are 'new' all the time,
1108** except for fixed strings (which are always old).
1032*/ 1109*/
1033static void whitelist (global_State *g, GCObject *p) { 1110static void whitelist (global_State *g, GCObject *p) {
1034 int white = luaC_white(g); 1111 int white = luaC_white(g);
1035 for (; p != NULL; p = p->next) 1112 for (; p != NULL; p = p->next)
1036 p->marked = cast_byte((p->marked & maskcolors) | white); 1113 p->marked = cast_byte((p->marked & maskgcbits) | white);
1037} 1114}
1038 1115
1039 1116
1040/* 1117/*
1041** Correct a list of gray objects. 1118** Correct a list of gray objects. Return pointer to where rest of the
1119** list should be linked.
1042** Because this correction is done after sweeping, young objects might 1120** Because this correction is done after sweeping, young objects might
1043** be turned white and still be in the list. They are only removed. 1121** be turned white and still be in the list. They are only removed.
1044** For tables and userdata, advance 'touched1' to 'touched2'; 'touched2' 1122** 'TOUCHED1' objects are advanced to 'TOUCHED2' and remain on the list;
1045** objects become regular old and are removed from the list. 1123** Non-white threads also remain on the list; 'TOUCHED2' objects become
1046** For threads, just remove white ones from the list. 1124** regular old; they and anything else are removed from the list.
1047*/ 1125*/
1048static GCObject **correctgraylist (GCObject **p) { 1126static GCObject **correctgraylist (GCObject **p) {
1049 GCObject *curr; 1127 GCObject *curr;
1050 while ((curr = *p) != NULL) { 1128 while ((curr = *p) != NULL) {
1051 switch (curr->tt) { 1129 GCObject **next = getgclist(curr);
1052 case LUA_VTABLE: case LUA_VUSERDATA: { 1130 if (iswhite(curr))
1053 GCObject **next = getgclist(curr); 1131 goto remove; /* remove all white objects */
1054 if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */ 1132 else if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */
1055 lua_assert(isgray(curr)); 1133 lua_assert(isgray(curr));
1056 gray2black(curr); /* make it black, for next barrier */ 1134 gray2black(curr); /* make it black, for next barrier */
1057 changeage(curr, G_TOUCHED1, G_TOUCHED2); 1135 changeage(curr, G_TOUCHED1, G_TOUCHED2);
1058 p = next; /* go to next element */ 1136 goto remain; /* keep it in the list and go to next element */
1059 } 1137 }
1060 else { /* not touched in this cycle */ 1138 else if (curr->tt == LUA_VTHREAD) {
1061 if (!iswhite(curr)) { /* not white? */ 1139 lua_assert(isgray(curr));
1062 lua_assert(isold(curr)); 1140 goto remain; /* keep non-white threads on the list */
1063 if (getage(curr) == G_TOUCHED2) /* advance from G_TOUCHED2... */ 1141 }
1064 changeage(curr, G_TOUCHED2, G_OLD); /* ... to G_OLD */ 1142 else { /* everything else is removed */
1065 gray2black(curr); /* make it black */ 1143 lua_assert(isold(curr)); /* young objects should be white here */
1066 } 1144 if (getage(curr) == G_TOUCHED2) { /* advance from TOUCHED2... */
1067 /* else, object is white: just remove it from this list */ 1145 changeage(curr, G_TOUCHED2, G_OLD); /* ... to OLD */
1068 *p = *next; /* remove 'curr' from gray list */ 1146 lua_assert(isblack(curr)); /* TOUCHED2 objects are always black */
1069 }
1070 break;
1071 } 1147 }
1072 case LUA_VTHREAD: { 1148 else {
1073 lua_State *th = gco2th(curr); 1149 /* everything else in a gray list should be gray */
1074 lua_assert(!isblack(th)); 1150 lua_assert(isgray(curr));
1075 if (iswhite(th)) /* new object? */ 1151 gray2black(curr); /* make object black (to be removed) */
1076 *p = th->gclist; /* remove from gray list */
1077 else /* old threads remain gray */
1078 p = &th->gclist; /* go to next element */
1079 break;
1080 } 1152 }
1081 default: lua_assert(0); /* nothing more could be gray here */ 1153 goto remove;
1082 } 1154 }
1155 remove: *p = *next; continue;
1156 remain: p = next; continue;
1083 } 1157 }
1084 return p; 1158 return p;
1085} 1159}
@@ -1100,7 +1174,7 @@ static void correctgraylists (global_State *g) {
1100 1174
1101 1175
1102/* 1176/*
1103** Mark 'OLD1' objects when starting a new young collection. 1177** Mark black 'OLD1' objects when starting a new young collection.
1104** Gray objects are already in some gray list, and so will be visited 1178** Gray objects are already in some gray list, and so will be visited
1105** in the atomic step. 1179** in the atomic step.
1106*/ 1180*/
@@ -1109,6 +1183,7 @@ static void markold (global_State *g, GCObject *from, GCObject *to) {
1109 for (p = from; p != to; p = p->next) { 1183 for (p = from; p != to; p = p->next) {
1110 if (getage(p) == G_OLD1) { 1184 if (getage(p) == G_OLD1) {
1111 lua_assert(!iswhite(p)); 1185 lua_assert(!iswhite(p));
1186 changeage(p, G_OLD1, G_OLD); /* now they are old */
1112 if (isblack(p)) { 1187 if (isblack(p)) {
1113 black2gray(p); /* should be '2white', but gray works too */ 1188 black2gray(p); /* should be '2white', but gray works too */
1114 reallymarkobject(g, p); 1189 reallymarkobject(g, p);
@@ -1137,42 +1212,57 @@ static void finishgencycle (lua_State *L, global_State *g) {
1137*/ 1212*/
1138static void youngcollection (lua_State *L, global_State *g) { 1213static void youngcollection (lua_State *L, global_State *g) {
1139 GCObject **psurvival; /* to point to first non-dead survival object */ 1214 GCObject **psurvival; /* to point to first non-dead survival object */
1215 GCObject *dummy; /* dummy out parameter to 'sweepgen' */
1140 lua_assert(g->gcstate == GCSpropagate); 1216 lua_assert(g->gcstate == GCSpropagate);
1141 markold(g, g->allgc, g->reallyold); 1217 if (g->firstold1) { /* are there regular OLD1 objects? */
1218 markold(g, g->firstold1, g->reallyold); /* mark them */
1219 g->firstold1 = NULL; /* no more OLD1 objects (for now) */
1220 }
1142 markold(g, g->finobj, g->finobjrold); 1221 markold(g, g->finobj, g->finobjrold);
1222 markold(g, g->tobefnz, NULL);
1143 atomic(L); 1223 atomic(L);
1144 1224
1145 /* sweep nursery and get a pointer to its last live element */ 1225 /* sweep nursery and get a pointer to its last live element */
1146 psurvival = sweepgen(L, g, &g->allgc, g->survival); 1226 g->gcstate = GCSswpallgc;
1147 /* sweep 'survival' and 'old' */ 1227 psurvival = sweepgen(L, g, &g->allgc, g->survival, &g->firstold1);
1148 sweepgen(L, g, psurvival, g->reallyold); 1228 /* sweep 'survival' */
1149 g->reallyold = g->old; 1229 sweepgen(L, g, psurvival, g->old1, &g->firstold1);
1150 g->old = *psurvival; /* 'survival' survivals are old now */ 1230 g->reallyold = g->old1;
1231 g->old1 = *psurvival; /* 'survival' survivals are old now */
1151 g->survival = g->allgc; /* all news are survivals */ 1232 g->survival = g->allgc; /* all news are survivals */
1152 1233
1153 /* repeat for 'finobj' lists */ 1234 /* repeat for 'finobj' lists */
1154 psurvival = sweepgen(L, g, &g->finobj, g->finobjsur); 1235 dummy = NULL; /* no 'firstold1' optimization for 'finobj' lists */
1155 /* sweep 'survival' and 'old' */ 1236 psurvival = sweepgen(L, g, &g->finobj, g->finobjsur, &dummy);
1156 sweepgen(L, g, psurvival, g->finobjrold); 1237 /* sweep 'survival' */
1157 g->finobjrold = g->finobjold; 1238 sweepgen(L, g, psurvival, g->finobjold1, &dummy);
1158 g->finobjold = *psurvival; /* 'survival' survivals are old now */ 1239 g->finobjrold = g->finobjold1;
1240 g->finobjold1 = *psurvival; /* 'survival' survivals are old now */
1159 g->finobjsur = g->finobj; /* all news are survivals */ 1241 g->finobjsur = g->finobj; /* all news are survivals */
1160 1242
1161 sweepgen(L, g, &g->tobefnz, NULL); 1243 sweepgen(L, g, &g->tobefnz, NULL, &dummy);
1162
1163 finishgencycle(L, g); 1244 finishgencycle(L, g);
1164} 1245}
1165 1246
1166 1247
1248/*
1249** Clears all gray lists, sweeps objects, and prepare sublists to enter
1250** generational mode. The sweeps remove dead objects and turn all
1251** surviving objects to old. Threads go back to 'grayagain'; everything
1252** else is turned black (not in any gray list).
1253*/
1167static void atomic2gen (lua_State *L, global_State *g) { 1254static void atomic2gen (lua_State *L, global_State *g) {
1255 cleargraylists(g);
1168 /* sweep all elements making them old */ 1256 /* sweep all elements making them old */
1257 g->gcstate = GCSswpallgc;
1169 sweep2old(L, &g->allgc); 1258 sweep2old(L, &g->allgc);
1170 /* everything alive now is old */ 1259 /* everything alive now is old */
1171 g->reallyold = g->old = g->survival = g->allgc; 1260 g->reallyold = g->old1 = g->survival = g->allgc;
1261 g->firstold1 = NULL; /* there are no OLD1 objects anywhere */
1172 1262
1173 /* repeat for 'finobj' lists */ 1263 /* repeat for 'finobj' lists */
1174 sweep2old(L, &g->finobj); 1264 sweep2old(L, &g->finobj);
1175 g->finobjrold = g->finobjold = g->finobjsur = g->finobj; 1265 g->finobjrold = g->finobjold1 = g->finobjsur = g->finobj;
1176 1266
1177 sweep2old(L, &g->tobefnz); 1267 sweep2old(L, &g->tobefnz);
1178 1268
@@ -1185,8 +1275,9 @@ static void atomic2gen (lua_State *L, global_State *g) {
1185 1275
1186/* 1276/*
1187** Enter generational mode. Must go until the end of an atomic cycle 1277** Enter generational mode. Must go until the end of an atomic cycle
1188** to ensure that all threads and weak tables are in the gray lists. 1278** to ensure that all objects are correctly marked and weak tables
1189** Then, turn all objects into old and finishes the collection. 1279** are cleared. Then, turn all objects into old and finishes the
1280** collection.
1190*/ 1281*/
1191static lu_mem entergen (lua_State *L, global_State *g) { 1282static lu_mem entergen (lua_State *L, global_State *g) {
1192 lu_mem numobjs; 1283 lu_mem numobjs;
@@ -1205,10 +1296,10 @@ static lu_mem entergen (lua_State *L, global_State *g) {
1205*/ 1296*/
1206static void enterinc (global_State *g) { 1297static void enterinc (global_State *g) {
1207 whitelist(g, g->allgc); 1298 whitelist(g, g->allgc);
1208 g->reallyold = g->old = g->survival = NULL; 1299 g->reallyold = g->old1 = g->survival = NULL;
1209 whitelist(g, g->finobj); 1300 whitelist(g, g->finobj);
1210 whitelist(g, g->tobefnz); 1301 whitelist(g, g->tobefnz);
1211 g->finobjrold = g->finobjold = g->finobjsur = NULL; 1302 g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
1212 g->gcstate = GCSpause; 1303 g->gcstate = GCSpause;
1213 g->gckind = KGC_INC; 1304 g->gckind = KGC_INC;
1214 g->lastatomic = 0; 1305 g->lastatomic = 0;
diff --git a/src/lua/lobject.h b/src/lua/lobject.h
index 04a81d3..1620223 100644
--- a/src/lua/lobject.h
+++ b/src/lua/lobject.h
@@ -96,7 +96,8 @@ typedef struct TValue {
96/* 96/*
97** Any value being manipulated by the program either is non 97** Any value being manipulated by the program either is non
98** collectable, or the collectable object has the right tag 98** collectable, or the collectable object has the right tag
99** and it is not dead. 99** and it is not dead. The option 'L == NULL' allows other
100** macros using this one to be used where L is not available.
100*/ 101*/
101#define checkliveness(L,obj) \ 102#define checkliveness(L,obj) \
102 ((void)L, lua_longassert(!iscollectable(obj) || \ 103 ((void)L, lua_longassert(!iscollectable(obj) || \
diff --git a/src/lua/lstate.c b/src/lua/lstate.c
index 28853dc..86b3761 100644
--- a/src/lua/lstate.c
+++ b/src/lua/lstate.c
@@ -301,6 +301,7 @@ static void preinit_thread (lua_State *L, global_State *g) {
301 L->openupval = NULL; 301 L->openupval = NULL;
302 L->status = LUA_OK; 302 L->status = LUA_OK;
303 L->errfunc = 0; 303 L->errfunc = 0;
304 L->oldpc = 0;
304} 305}
305 306
306 307
@@ -412,8 +413,8 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
412 g->gckind = KGC_INC; 413 g->gckind = KGC_INC;
413 g->gcemergency = 0; 414 g->gcemergency = 0;
414 g->finobj = g->tobefnz = g->fixedgc = NULL; 415 g->finobj = g->tobefnz = g->fixedgc = NULL;
415 g->survival = g->old = g->reallyold = NULL; 416 g->firstold1 = g->survival = g->old1 = g->reallyold = NULL;
416 g->finobjsur = g->finobjold = g->finobjrold = NULL; 417 g->finobjsur = g->finobjold1 = g->finobjrold = NULL;
417 g->sweepgc = NULL; 418 g->sweepgc = NULL;
418 g->gray = g->grayagain = NULL; 419 g->gray = g->grayagain = NULL;
419 g->weak = g->ephemeron = g->allweak = NULL; 420 g->weak = g->ephemeron = g->allweak = NULL;
diff --git a/src/lua/lstate.h b/src/lua/lstate.h
index 2e8bd6c..697d73b 100644
--- a/src/lua/lstate.h
+++ b/src/lua/lstate.h
@@ -32,13 +32,29 @@
32** 32**
33** 'allgc' -> 'survival': new objects; 33** 'allgc' -> 'survival': new objects;
34** 'survival' -> 'old': objects that survived one collection; 34** 'survival' -> 'old': objects that survived one collection;
35** 'old' -> 'reallyold': objects that became old in last collection; 35** 'old1' -> 'reallyold': objects that became old in last collection;
36** 'reallyold' -> NULL: objects old for more than one cycle. 36** 'reallyold' -> NULL: objects old for more than one cycle.
37** 37**
38** 'finobj' -> 'finobjsur': new objects marked for finalization; 38** 'finobj' -> 'finobjsur': new objects marked for finalization;
39** 'finobjsur' -> 'finobjold': survived """"; 39** 'finobjsur' -> 'finobjold1': survived """";
40** 'finobjold' -> 'finobjrold': just old """"; 40** 'finobjold1' -> 'finobjrold': just old """";
41** 'finobjrold' -> NULL: really old """". 41** 'finobjrold' -> NULL: really old """".
42**
43** All lists can contain elements older than their main ages, due
44** to 'luaC_checkfinalizer' and 'udata2finalize', which move
45** objects between the normal lists and the "marked for finalization"
46** lists. Moreover, barriers can age young objects in young lists as
47** OLD0, which then become OLD1. However, a list never contains
48** elements younger than their main ages.
49**
50** The generational collector also uses a pointer 'firstold1', which
51** points to the first OLD1 object in the list. It is used to optimize
52** 'markold'. (Potentially OLD1 objects can be anywhere between 'allgc'
53** and 'reallyold', but often the list has no OLD1 objects or they are
54** after 'old1'.) Note the difference between it and 'old1':
55** 'firstold1': no OLD1 objects before this point; there can be all
56** ages after it.
57** 'old1': no objects younger than OLD1 after this point.
42*/ 58*/
43 59
44/* 60/*
@@ -47,7 +63,7 @@
47** can become gray have such a field. The field is not the same 63** can become gray have such a field. The field is not the same
48** in all objects, but it always has this name.) Any gray object 64** in all objects, but it always has this name.) Any gray object
49** must belong to one of these lists, and all objects in these lists 65** must belong to one of these lists, and all objects in these lists
50** must be gray: 66** must be gray (with one exception explained below):
51** 67**
52** 'gray': regular gray objects, still waiting to be visited. 68** 'gray': regular gray objects, still waiting to be visited.
53** 'grayagain': objects that must be revisited at the atomic phase. 69** 'grayagain': objects that must be revisited at the atomic phase.
@@ -58,6 +74,12 @@
58** 'weak': tables with weak values to be cleared; 74** 'weak': tables with weak values to be cleared;
59** 'ephemeron': ephemeron tables with white->white entries; 75** 'ephemeron': ephemeron tables with white->white entries;
60** 'allweak': tables with weak keys and/or weak values to be cleared. 76** 'allweak': tables with weak keys and/or weak values to be cleared.
77**
78** The exception to that "gray rule" is the TOUCHED2 objects in
79** generational mode. Those objects stay in a gray list (because they
80** must be visited again at the end of the cycle), but they are marked
81** black (because assignments to them must activate barriers, to move
82** them back to TOUCHED1).
61*/ 83*/
62 84
63 85
@@ -257,10 +279,11 @@ typedef struct global_State {
257 GCObject *fixedgc; /* list of objects not to be collected */ 279 GCObject *fixedgc; /* list of objects not to be collected */
258 /* fields for generational collector */ 280 /* fields for generational collector */
259 GCObject *survival; /* start of objects that survived one GC cycle */ 281 GCObject *survival; /* start of objects that survived one GC cycle */
260 GCObject *old; /* start of old objects */ 282 GCObject *old1; /* start of old1 objects */
261 GCObject *reallyold; /* old objects with more than one cycle */ 283 GCObject *reallyold; /* objects more than one cycle old ("really old") */
284 GCObject *firstold1; /* first OLD1 object in the list (if any) */
262 GCObject *finobjsur; /* list of survival objects with finalizers */ 285 GCObject *finobjsur; /* list of survival objects with finalizers */
263 GCObject *finobjold; /* list of old objects with finalizers */ 286 GCObject *finobjold1; /* list of old1 objects with finalizers */
264 GCObject *finobjrold; /* list of really old objects with finalizers */ 287 GCObject *finobjrold; /* list of really old objects with finalizers */
265 struct lua_State *twups; /* list of threads with open upvalues */ 288 struct lua_State *twups; /* list of threads with open upvalues */
266 lua_CFunction panic; /* to be called in unprotected errors */ 289 lua_CFunction panic; /* to be called in unprotected errors */
@@ -286,7 +309,6 @@ struct lua_State {
286 StkId top; /* first free slot in the stack */ 309 StkId top; /* first free slot in the stack */
287 global_State *l_G; 310 global_State *l_G;
288 CallInfo *ci; /* call info for current function */ 311 CallInfo *ci; /* call info for current function */
289 const Instruction *oldpc; /* last pc traced */
290 StkId stack_last; /* last free slot in the stack */ 312 StkId stack_last; /* last free slot in the stack */
291 StkId stack; /* stack base */ 313 StkId stack; /* stack base */
292 UpVal *openupval; /* list of open upvalues in this stack */ 314 UpVal *openupval; /* list of open upvalues in this stack */
@@ -297,6 +319,7 @@ struct lua_State {
297 volatile lua_Hook hook; 319 volatile lua_Hook hook;
298 ptrdiff_t errfunc; /* current error handling function (stack index) */ 320 ptrdiff_t errfunc; /* current error handling function (stack index) */
299 l_uint32 nCcalls; /* number of allowed nested C calls - 'nci' */ 321 l_uint32 nCcalls; /* number of allowed nested C calls - 'nci' */
322 int oldpc; /* last pc traced */
300 int stacksize; 323 int stacksize;
301 int basehookcount; 324 int basehookcount;
302 int hookcount; 325 int hookcount;
diff --git a/src/lua/lvm.c b/src/lua/lvm.c
index 66d451b..08681af 100644
--- a/src/lua/lvm.c
+++ b/src/lua/lvm.c
@@ -1794,7 +1794,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1794 ProtectNT(luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p)); 1794 ProtectNT(luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p));
1795 if (trap) { 1795 if (trap) {
1796 luaD_hookcall(L, ci); 1796 luaD_hookcall(L, ci);
1797 L->oldpc = pc + 1; /* next opcode will be seen as a "new" line */ 1797 L->oldpc = 1; /* next opcode will be seen as a "new" line */
1798 } 1798 }
1799 updatebase(ci); /* function has new base after adjustment */ 1799 updatebase(ci); /* function has new base after adjustment */
1800 vmbreak; 1800 vmbreak;