diff options
| -rw-r--r-- | lapi.c | 5 | ||||
| -rw-r--r-- | lgc.c | 72 | ||||
| -rw-r--r-- | lgc.h | 4 | ||||
| -rw-r--r-- | lobject.h | 6 | ||||
| -rw-r--r-- | lstate.c | 4 | ||||
| -rw-r--r-- | lstate.h | 8 | ||||
| -rw-r--r-- | ltests.c | 21 |
7 files changed, 63 insertions, 57 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lapi.c,v 2.139 2010/10/25 20:31:11 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.141 2010/11/18 19:15:00 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 | */ |
| @@ -760,13 +760,14 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { | |||
| 760 | hvalue(obj)->metatable = mt; | 760 | hvalue(obj)->metatable = mt; |
| 761 | if (mt) | 761 | if (mt) |
| 762 | luaC_objbarrierback(L, gcvalue(obj), mt); | 762 | luaC_objbarrierback(L, gcvalue(obj), mt); |
| 763 | luaC_checkfinalizer(L, gcvalue(obj), mt); | ||
| 763 | break; | 764 | break; |
| 764 | } | 765 | } |
| 765 | case LUA_TUSERDATA: { | 766 | case LUA_TUSERDATA: { |
| 766 | uvalue(obj)->metatable = mt; | 767 | uvalue(obj)->metatable = mt; |
| 767 | if (mt) { | 768 | if (mt) { |
| 768 | luaC_objbarrier(L, rawuvalue(obj), mt); | 769 | luaC_objbarrier(L, rawuvalue(obj), mt); |
| 769 | luaC_checkfinalizer(L, rawuvalue(obj)); | 770 | luaC_checkfinalizer(L, gcvalue(obj), mt); |
| 770 | } | 771 | } |
| 771 | break; | 772 | break; |
| 772 | } | 773 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 2.102 2010/09/03 14:14:01 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.104 2010/11/18 19:15:00 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 | */ |
| @@ -68,7 +68,7 @@ | |||
| 68 | #define stringmark(s) ((void)((s) && resetbits((s)->tsv.marked, WHITEBITS))) | 68 | #define stringmark(s) ((void)((s) && resetbits((s)->tsv.marked, WHITEBITS))) |
| 69 | 69 | ||
| 70 | 70 | ||
| 71 | #define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) | 71 | #define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT) |
| 72 | 72 | ||
| 73 | #define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) | 73 | #define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) |
| 74 | 74 | ||
| @@ -114,12 +114,11 @@ static void removeentry (Node *n) { | |||
| 114 | */ | 114 | */ |
| 115 | static int iscleared (const TValue *o, int iskey) { | 115 | static int iscleared (const TValue *o, int iskey) { |
| 116 | if (!iscollectable(o)) return 0; | 116 | if (!iscollectable(o)) return 0; |
| 117 | if (ttisstring(o)) { | 117 | else if (ttisstring(o)) { |
| 118 | stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ | 118 | stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ |
| 119 | return 0; | 119 | return 0; |
| 120 | } | 120 | } |
| 121 | return iswhite(gcvalue(o)) || | 121 | else return iswhite(gcvalue(o)) || (!iskey && isfinalized(gcvalue(o))); |
| 122 | (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); | ||
| 123 | } | 122 | } |
| 124 | 123 | ||
| 125 | 124 | ||
| @@ -687,19 +686,18 @@ static void checkSizes (lua_State *L) { | |||
| 687 | } | 686 | } |
| 688 | 687 | ||
| 689 | 688 | ||
| 690 | static Udata *udata2finalize (global_State *g) { | 689 | static GCObject *udata2finalize (global_State *g) { |
| 691 | GCObject *o = g->tobefnz; /* get first element */ | 690 | GCObject *o = g->tobefnz; /* get first element */ |
| 692 | Udata *u = rawgco2u(o); | 691 | lua_assert(isfinalized(o)); |
| 693 | lua_assert(isfinalized(&u->uv)); | ||
| 694 | lua_assert(!isold(o)); | 692 | lua_assert(!isold(o)); |
| 695 | g->tobefnz = u->uv.next; /* remove it from 'tobefnz' list */ | 693 | g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ |
| 696 | u->uv.next = g->allgc; /* return it to 'allgc' list */ | 694 | gch(o)->next = g->allgc; /* return it to 'allgc' list */ |
| 697 | g->allgc = o; | 695 | g->allgc = o; |
| 698 | resetbit(u->uv.marked, SEPARATED); /* mark that it is not in 'tobefnz' */ | 696 | resetbit(gch(o)->marked, SEPARATED); /* mark that it is not in 'tobefnz' */ |
| 699 | resetoldbit(o); /* see MOVE OLD rule */ | 697 | resetoldbit(o); /* see MOVE OLD rule */ |
| 700 | if (!keepinvariant(g)) /* not keeping invariant? */ | 698 | if (!keepinvariant(g)) /* not keeping invariant? */ |
| 701 | makewhite(g, o); /* "sweep" object */ | 699 | makewhite(g, o); /* "sweep" object */ |
| 702 | return u; | 700 | return o; |
| 703 | } | 701 | } |
| 704 | 702 | ||
| 705 | 703 | ||
| @@ -711,8 +709,10 @@ static void dothecall (lua_State *L, void *ud) { | |||
| 711 | 709 | ||
| 712 | static void GCTM (lua_State *L, int propagateerrors) { | 710 | static void GCTM (lua_State *L, int propagateerrors) { |
| 713 | global_State *g = G(L); | 711 | global_State *g = G(L); |
| 714 | Udata *udata = udata2finalize(g); | 712 | const TValue *tm; |
| 715 | const TValue *tm = gfasttm(g, udata->uv.metatable, TM_GC); | 713 | TValue v; |
| 714 | setgcovalue(L, &v, udata2finalize(g)); | ||
| 715 | tm = luaT_gettmbyobj(L, &v, TM_GC); | ||
| 716 | if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ | 716 | if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ |
| 717 | int status; | 717 | int status; |
| 718 | lu_byte oldah = L->allowhook; | 718 | lu_byte oldah = L->allowhook; |
| @@ -720,7 +720,7 @@ static void GCTM (lua_State *L, int propagateerrors) { | |||
| 720 | L->allowhook = 0; /* stop debug hooks during GC tag method */ | 720 | L->allowhook = 0; /* stop debug hooks during GC tag method */ |
| 721 | stopgc(g); /* avoid GC steps */ | 721 | stopgc(g); /* avoid GC steps */ |
| 722 | setobj2s(L, L->top, tm); /* push finalizer... */ | 722 | setobj2s(L, L->top, tm); /* push finalizer... */ |
| 723 | setuvalue(L, L->top+1, udata); /* ... and its argument */ | 723 | setobj2s(L, L->top + 1, &v); /* ... and its argument */ |
| 724 | L->top += 2; /* and (next line) call the finalizer */ | 724 | L->top += 2; /* and (next line) call the finalizer */ |
| 725 | status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); | 725 | status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); |
| 726 | L->allowhook = oldah; /* restore hooks */ | 726 | L->allowhook = oldah; /* restore hooks */ |
| @@ -738,25 +738,25 @@ static void GCTM (lua_State *L, int propagateerrors) { | |||
| 738 | 738 | ||
| 739 | 739 | ||
| 740 | /* | 740 | /* |
| 741 | ** move all unreachable udata that need finalization from list 'udgc' to | 741 | ** move all unreachable objects that need finalization from list 'finobj' |
| 742 | ** list 'tobefnz' | 742 | ** to list 'tobefnz' |
| 743 | */ | 743 | */ |
| 744 | void luaC_separateudata (lua_State *L, int all) { | 744 | void luaC_separateudata (lua_State *L, int all) { |
| 745 | global_State *g = G(L); | 745 | global_State *g = G(L); |
| 746 | GCObject **p = &g->udgc; | 746 | GCObject **p = &g->finobj; |
| 747 | GCObject *curr; | 747 | GCObject *curr; |
| 748 | GCObject **lastnext = &g->tobefnz; | 748 | GCObject **lastnext = &g->tobefnz; |
| 749 | /* find last 'next' field in 'tobefnz' list (to add elements in its end) */ | 749 | /* find last 'next' field in 'tobefnz' list (to add elements in its end) */ |
| 750 | while (*lastnext != NULL) | 750 | while (*lastnext != NULL) |
| 751 | lastnext = &gch(*lastnext)->next; | 751 | lastnext = &gch(*lastnext)->next; |
| 752 | while ((curr = *p) != NULL) { /* traverse all finalizable objects */ | 752 | while ((curr = *p) != NULL) { /* traverse all finalizable objects */ |
| 753 | lua_assert(gch(curr)->tt == LUA_TUSERDATA && !isfinalized(gco2u(curr))); | 753 | lua_assert(!isfinalized(curr)); |
| 754 | lua_assert(testbit(gch(curr)->marked, SEPARATED)); | 754 | lua_assert(testbit(gch(curr)->marked, SEPARATED)); |
| 755 | if (!(all || iswhite(curr))) /* not being collected? */ | 755 | if (!(all || iswhite(curr))) /* not being collected? */ |
| 756 | p = &gch(curr)->next; /* don't bother with it */ | 756 | p = &gch(curr)->next; /* don't bother with it */ |
| 757 | else { | 757 | else { |
| 758 | l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ | 758 | l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ |
| 759 | *p = gch(curr)->next; /* remove 'curr' from 'udgc' list */ | 759 | *p = gch(curr)->next; /* remove 'curr' from 'finobj' list */ |
| 760 | gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ | 760 | gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ |
| 761 | *lastnext = curr; | 761 | *lastnext = curr; |
| 762 | lastnext = &gch(curr)->next; | 762 | lastnext = &gch(curr)->next; |
| @@ -766,23 +766,23 @@ void luaC_separateudata (lua_State *L, int all) { | |||
| 766 | 766 | ||
| 767 | 767 | ||
| 768 | /* | 768 | /* |
| 769 | ** if userdata 'u' has a finalizer, remove it from 'allgc' list (must | 769 | ** if object 'o' has a finalizer, remove it from 'allgc' list (must |
| 770 | ** search the list to find it) and link it in 'udgc' list. | 770 | ** search the list to find it) and link it in 'finobj' list. |
| 771 | */ | 771 | */ |
| 772 | void luaC_checkfinalizer (lua_State *L, Udata *u) { | 772 | void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { |
| 773 | global_State *g = G(L); | 773 | global_State *g = G(L); |
| 774 | if (testbit(u->uv.marked, SEPARATED) || /* udata is already separated... */ | 774 | if (testbit(gch(o)->marked, SEPARATED) || /* obj. is already separated... */ |
| 775 | isfinalized(&u->uv) || /* ... or is finalized... */ | 775 | isfinalized(o) || /* ... or is finalized... */ |
| 776 | gfasttm(g, u->uv.metatable, TM_GC) == NULL) /* or has no finalizer? */ | 776 | gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ |
| 777 | return; /* nothing to be done */ | 777 | return; /* nothing to be done */ |
| 778 | else { /* move 'u' to 'udgc' list */ | 778 | else { /* move 'o' to 'finobj' list */ |
| 779 | GCObject **p; | 779 | GCObject **p; |
| 780 | for (p = &g->allgc; *p != obj2gco(u); p = &gch(*p)->next) ; | 780 | for (p = &g->allgc; *p != o; p = &gch(*p)->next) ; |
| 781 | *p = u->uv.next; /* remove 'u' from root list */ | 781 | *p = gch(o)->next; /* remove 'o' from root list */ |
| 782 | u->uv.next = g->udgc; /* link it in list 'udgc' */ | 782 | gch(o)->next = g->finobj; /* link it in list 'finobj' */ |
| 783 | g->udgc = obj2gco(u); | 783 | g->finobj = o; |
| 784 | l_setbit(u->uv.marked, SEPARATED); /* mark it as such */ | 784 | l_setbit(gch(o)->marked, SEPARATED); /* mark it as such */ |
| 785 | resetoldbit(obj2gco(u)); /* see MOVE OLD rule */ | 785 | resetoldbit(o); /* see MOVE OLD rule */ |
| 786 | } | 786 | } |
| 787 | } | 787 | } |
| 788 | 788 | ||
| @@ -837,8 +837,8 @@ void luaC_freeallobjects (lua_State *L) { | |||
| 837 | /* following "white" makes all objects look dead */ | 837 | /* following "white" makes all objects look dead */ |
| 838 | g->currentwhite = WHITEBITS; | 838 | g->currentwhite = WHITEBITS; |
| 839 | g->gckind = KGC_NORMAL; | 839 | g->gckind = KGC_NORMAL; |
| 840 | sweepwholelist(L, &g->udgc); | 840 | sweepwholelist(L, &g->finobj); |
| 841 | lua_assert(g->udgc == NULL); | 841 | lua_assert(g->finobj == NULL); |
| 842 | sweepwholelist(L, &g->allgc); | 842 | sweepwholelist(L, &g->allgc); |
| 843 | lua_assert(g->allgc == NULL); | 843 | lua_assert(g->allgc == NULL); |
| 844 | for (i = 0; i < g->strt.size; i++) /* free all string lists */ | 844 | for (i = 0; i < g->strt.size; i++) /* free all string lists */ |
| @@ -905,7 +905,7 @@ static l_mem singlestep (lua_State *L) { | |||
| 905 | return GCSWEEPCOST; | 905 | return GCSWEEPCOST; |
| 906 | } | 906 | } |
| 907 | else { /* no more strings to sweep */ | 907 | else { /* no more strings to sweep */ |
| 908 | g->sweepgc = &g->udgc; /* prepare to sweep userdata */ | 908 | g->sweepgc = &g->finobj; /* prepare to sweep finalizable objects */ |
| 909 | g->gcstate = GCSsweepudata; | 909 | g->gcstate = GCSsweepudata; |
| 910 | return 0; | 910 | return 0; |
| 911 | } | 911 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.h,v 2.43 2010/06/07 16:55:34 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.45 2010/11/18 19:15:00 roberto Exp $ |
| 3 | ** Garbage Collector | 3 | ** Garbage Collector |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -137,7 +137,7 @@ LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, | |||
| 137 | LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); | 137 | LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); |
| 138 | LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); | 138 | LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); |
| 139 | LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); | 139 | LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); |
| 140 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, Udata *u); | 140 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); |
| 141 | LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); | 141 | LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); |
| 142 | LUAI_FUNC void luaC_changemode (lua_State *L, int mode); | 142 | LUAI_FUNC void luaC_changemode (lua_State *L, int mode); |
| 143 | 143 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.h,v 2.41 2010/06/04 13:25:10 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 2.42 2010/07/26 15:53:23 roberto Exp roberto $ |
| 3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -153,6 +153,10 @@ typedef struct lua_TValue { | |||
| 153 | #define setbvalue(obj,x) \ | 153 | #define setbvalue(obj,x) \ |
| 154 | { TValue *i_o=(obj); i_o->value_.b=(x); i_o->tt_=LUA_TBOOLEAN; } | 154 | { TValue *i_o=(obj); i_o->value_.b=(x); i_o->tt_=LUA_TBOOLEAN; } |
| 155 | 155 | ||
| 156 | #define setgcovalue(L,obj,x) \ | ||
| 157 | { TValue *i_o=(obj); GCObject *i_g=(x); \ | ||
| 158 | i_o->value_.gc=i_g; i_o->tt_=gch(i_g)->tt; } | ||
| 159 | |||
| 156 | #define setsvalue(L,obj,x) \ | 160 | #define setsvalue(L,obj,x) \ |
| 157 | { TValue *i_o=(obj); \ | 161 | { TValue *i_o=(obj); \ |
| 158 | i_o->value_.gc=cast(GCObject *, (x)); i_o->tt_=LUA_TSTRING; \ | 162 | i_o->value_.gc=cast(GCObject *, (x)); i_o->tt_=LUA_TSTRING; \ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.c,v 2.85 2010/04/30 18:36:22 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.86 2010/09/03 14:14:01 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 | */ |
| @@ -252,7 +252,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
| 252 | g->version = lua_version(NULL); | 252 | g->version = lua_version(NULL); |
| 253 | g->gcstate = GCSpause; | 253 | g->gcstate = GCSpause; |
| 254 | g->allgc = NULL; | 254 | g->allgc = NULL; |
| 255 | g->udgc = NULL; | 255 | g->finobj = NULL; |
| 256 | g->tobefnz = NULL; | 256 | g->tobefnz = NULL; |
| 257 | g->gray = g->grayagain = NULL; | 257 | g->gray = g->grayagain = NULL; |
| 258 | g->weak = g->ephemeron = g->allweak = NULL; | 258 | g->weak = g->ephemeron = g->allweak = NULL; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.h,v 2.67 2010/09/30 17:21:31 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.68 2010/10/29 17:52:46 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 | */ |
| @@ -32,9 +32,9 @@ | |||
| 32 | ** when traversing the respective threads, but the thread may already be | 32 | ** when traversing the respective threads, but the thread may already be |
| 33 | ** dead, while the upvalue is still accessible through closures.) | 33 | ** dead, while the upvalue is still accessible through closures.) |
| 34 | ** | 34 | ** |
| 35 | ** Userdata with finalizers are kept in the list g->udgc. | 35 | ** Objects with finalizers are kept in the list g->finobj. |
| 36 | ** | 36 | ** |
| 37 | ** The list g->tobefnz links all userdata being finalized. | 37 | ** The list g->tobefnz links all objects being finalized. |
| 38 | 38 | ||
| 39 | */ | 39 | */ |
| 40 | 40 | ||
| @@ -125,7 +125,7 @@ typedef struct global_State { | |||
| 125 | lu_byte gckind; /* kind of GC running */ | 125 | lu_byte gckind; /* kind of GC running */ |
| 126 | int sweepstrgc; /* position of sweep in `strt' */ | 126 | int sweepstrgc; /* position of sweep in `strt' */ |
| 127 | GCObject *allgc; /* list of all collectable objects */ | 127 | GCObject *allgc; /* list of all collectable objects */ |
| 128 | GCObject *udgc; /* list of collectable userdata with finalizers */ | 128 | GCObject *finobj; /* list of collectable objects with finalizers */ |
| 129 | GCObject **sweepgc; /* current position of sweep */ | 129 | GCObject **sweepgc; /* current position of sweep */ |
| 130 | GCObject *gray; /* list of gray objects */ | 130 | GCObject *gray; /* list of gray objects */ |
| 131 | GCObject *grayagain; /* list of objects to be traversed atomically */ | 131 | GCObject *grayagain; /* list of objects to be traversed atomically */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltests.c,v 2.112 2010/07/28 15:51:59 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.113 2010/11/16 17:43:29 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 | */ |
| @@ -429,20 +429,21 @@ int lua_checkmemory (lua_State *L) { | |||
| 429 | checkobject(g, o); | 429 | checkobject(g, o); |
| 430 | lua_assert(!testbit(o->gch.marked, SEPARATED)); | 430 | lua_assert(!testbit(o->gch.marked, SEPARATED)); |
| 431 | } | 431 | } |
| 432 | /* check 'udgc' list */ | 432 | /* check 'finobj' list */ |
| 433 | checkold(g, g->udgc); | 433 | checkold(g, g->finobj); |
| 434 | for (o = g->udgc; o != NULL; o = gch(o)->next) { | 434 | for (o = g->finobj; o != NULL; o = gch(o)->next) { |
| 435 | lua_assert(gch(o)->tt == LUA_TUSERDATA && | 435 | lua_assert(!isdead(g, o) && testbit(o->gch.marked, SEPARATED)); |
| 436 | !isdead(g, o) && | 436 | lua_assert(gch(o)->tt == LUA_TUSERDATA || |
| 437 | testbit(o->gch.marked, SEPARATED)); | 437 | gch(o)->tt == LUA_TTABLE); |
| 438 | checkobject(g, o); | 438 | checkobject(g, o); |
| 439 | } | 439 | } |
| 440 | /* check 'tobefnz' list */ | 440 | /* check 'tobefnz' list */ |
| 441 | checkold(g, g->tobefnz); | 441 | checkold(g, g->tobefnz); |
| 442 | for (o = g->tobefnz; o != NULL; o = gch(o)->next) { | 442 | for (o = g->tobefnz; o != NULL; o = gch(o)->next) { |
| 443 | lua_assert(gch(o)->tt == LUA_TUSERDATA); | 443 | lua_assert(!iswhite(o)); |
| 444 | lua_assert(isblack(o)); | 444 | lua_assert(!isdead(g, o) && testbit(o->gch.marked, SEPARATED)); |
| 445 | lua_assert(testbit(o->gch.marked, SEPARATED)); | 445 | lua_assert(gch(o)->tt == LUA_TUSERDATA || |
| 446 | gch(o)->tt == LUA_TTABLE); | ||
| 446 | } | 447 | } |
| 447 | /* check 'uvhead' list */ | 448 | /* check 'uvhead' list */ |
| 448 | for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { | 449 | for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { |
