diff options
| -rw-r--r-- | bugs | 19 | ||||
| -rw-r--r-- | lgc.c | 120 | ||||
| -rw-r--r-- | lgc.h | 11 | ||||
| -rw-r--r-- | lstate.c | 6 | ||||
| -rw-r--r-- | lstate.h | 5 | ||||
| -rw-r--r-- | ltests.c | 63 |
6 files changed, 144 insertions, 80 deletions
| @@ -1880,8 +1880,8 @@ patch = [[ | |||
| 1880 | +++ lundump.c 2008/04/04 19:51:41 2.7.1.4 | 1880 | +++ lundump.c 2008/04/04 19:51:41 2.7.1.4 |
| 1881 | @@ -1,5 +1,5 @@ | 1881 | @@ -1,5 +1,5 @@ |
| 1882 | /* | 1882 | /* |
| 1883 | -** $Id: bugs,v 1.125 2013/07/05 18:02:28 roberto Exp roberto $ | 1883 | -** $Id: bugs,v 1.126 2013/08/30 15:51:12 roberto Exp roberto $ |
| 1884 | +** $Id: bugs,v 1.125 2013/07/05 18:02:28 roberto Exp roberto $ | 1884 | +** $Id: bugs,v 1.126 2013/08/30 15:51:12 roberto Exp roberto $ |
| 1885 | ** load precompiled Lua chunks | 1885 | ** load precompiled Lua chunks |
| 1886 | ** See Copyright Notice in lua.h | 1886 | ** See Copyright Notice in lua.h |
| 1887 | */ | 1887 | */ |
| @@ -3133,7 +3133,20 @@ patch = [[ | |||
| 3133 | return ts; | 3133 | return ts; |
| 3134 | ]] | 3134 | ]] |
| 3135 | } | 3135 | } |
| 3136 | ]=] | 3136 | ] |
| 3137 | |||
| 3138 | |||
| 3139 | Bug{ | ||
| 3140 | what = [[Call to macro 'luai_userstateclose' should be done only | ||
| 3141 | after the calls to __gc methods.]], | ||
| 3142 | report = [[Jean-Luc Jumpertz, 2013/09/02]], | ||
| 3143 | since = [[ ]], | ||
| 3144 | fix = nil, | ||
| 3145 | example = [[No example]], | ||
| 3146 | patch = [[ | ||
| 3147 | ]] | ||
| 3148 | } | ||
| 3149 | ]=]=] | ||
| 3137 | 3150 | ||
| 3138 | 3151 | ||
| 3139 | --[=[ | 3152 | --[=[ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 2.156 2013/08/29 13:34:16 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.157 2013/08/30 19:14:26 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 | */ |
| @@ -777,8 +777,16 @@ static GCObject *udata2finalize (global_State *g) { | |||
| 777 | GCObject *o = g->tobefnz; /* get first element */ | 777 | GCObject *o = g->tobefnz; /* get first element */ |
| 778 | lua_assert(tofinalize(o)); | 778 | lua_assert(tofinalize(o)); |
| 779 | g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ | 779 | g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ |
| 780 | gch(o)->next = g->allgc; /* return it to 'allgc' list */ | 780 | if (islocal(o)) { |
| 781 | g->allgc = o; | 781 | lua_assert(!testbit(gch(o)->marked, LOCALMARK)); |
| 782 | gch(o)->next = g->localgc; /* return it to 'localgc' list */ | ||
| 783 | g->localgc = o; | ||
| 784 | } | ||
| 785 | else { /* return it to 'allgc' list */ | ||
| 786 | gch(o)->next = g->allgc; | ||
| 787 | g->allgc = o; | ||
| 788 | l_setbit(gch(o)->marked, LOCALMARK); | ||
| 789 | } | ||
| 782 | resetbit(gch(o)->marked, FINALIZEDBIT); /* object is back in 'allgc' */ | 790 | resetbit(gch(o)->marked, FINALIZEDBIT); /* object is back in 'allgc' */ |
| 783 | if (!keepinvariant(g)) /* not keeping invariant? */ | 791 | if (!keepinvariant(g)) /* not keeping invariant? */ |
| 784 | makewhite(g, o); /* "sweep" object */ | 792 | makewhite(g, o); /* "sweep" object */ |
| @@ -825,23 +833,38 @@ static void GCTM (lua_State *L, int propagateerrors) { | |||
| 825 | 833 | ||
| 826 | 834 | ||
| 827 | /* | 835 | /* |
| 828 | ** move all unreachable objects (or 'all' objects) that need | 836 | ** call all pending finalizers |
| 829 | ** finalization from list 'finobj' to list 'tobefnz' (to be finalized) | ||
| 830 | */ | 837 | */ |
| 831 | static void separatetobefnz (lua_State *L, int all) { | 838 | static void callallpendingfinalizers (lua_State *L, int propagateerrors) { |
| 832 | global_State *g = G(L); | 839 | global_State *g = G(L); |
| 833 | GCObject **p = &g->finobj; | 840 | while (g->tobefnz) |
| 841 | GCTM(L, propagateerrors); | ||
| 842 | } | ||
| 843 | |||
| 844 | |||
| 845 | /* | ||
| 846 | ** find last 'next' field in list 'p' list (to add elements in its end) | ||
| 847 | */ | ||
| 848 | static GCObject **findlast (GCObject **p) { | ||
| 849 | while (*p != NULL) | ||
| 850 | p = &gch(*p)->next; | ||
| 851 | return p; | ||
| 852 | } | ||
| 853 | |||
| 854 | |||
| 855 | /* | ||
| 856 | ** move all unreachable objects (or 'all' objects) that need | ||
| 857 | ** finalization from list 'p' to list 'tobefnz' (to be finalized) | ||
| 858 | */ | ||
| 859 | static void separatetobefnz_aux (global_State *g, GCObject **p, int all) { | ||
| 834 | GCObject *curr; | 860 | GCObject *curr; |
| 835 | GCObject **lastnext = &g->tobefnz; | 861 | GCObject **lastnext = findlast(&g->tobefnz); |
| 836 | /* find last 'next' field in 'tobefnz' list (to add elements in its end) */ | ||
| 837 | while (*lastnext != NULL) | ||
| 838 | lastnext = &gch(*lastnext)->next; | ||
| 839 | while ((curr = *p) != NULL) { /* traverse all finalizable objects */ | 862 | while ((curr = *p) != NULL) { /* traverse all finalizable objects */ |
| 840 | lua_assert(tofinalize(curr)); | 863 | lua_assert(tofinalize(curr)); |
| 841 | if (!(iswhite(curr) || all)) /* not being collected? */ | 864 | if (!(iswhite(curr) || all)) /* not being collected? */ |
| 842 | p = &gch(curr)->next; /* don't bother with it */ | 865 | p = &gch(curr)->next; /* don't bother with it */ |
| 843 | else { | 866 | else { |
| 844 | *p = gch(curr)->next; /* remove 'curr' from 'finobj' list */ | 867 | *p = gch(curr)->next; /* remove 'curr' from "fin" list */ |
| 845 | gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ | 868 | gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ |
| 846 | *lastnext = curr; | 869 | *lastnext = curr; |
| 847 | lastnext = &gch(curr)->next; | 870 | lastnext = &gch(curr)->next; |
| @@ -850,9 +873,15 @@ static void separatetobefnz (lua_State *L, int all) { | |||
| 850 | } | 873 | } |
| 851 | 874 | ||
| 852 | 875 | ||
| 876 | static void separatetobefnz (global_State *g, int all) { | ||
| 877 | separatetobefnz_aux(g, &g->localfin, all); | ||
| 878 | separatetobefnz_aux(g, &g->finobj, all); | ||
| 879 | } | ||
| 880 | |||
| 881 | |||
| 853 | /* | 882 | /* |
| 854 | ** if object 'o' has a finalizer, remove it from 'allgc' list (must | 883 | ** if object 'o' has a finalizer, remove it from 'allgc' list (must |
| 855 | ** search the list to find it) and link it in 'finobj' list. | 884 | ** search the list to find it) and link it in 'localfin' or 'finobj' list. |
| 856 | */ | 885 | */ |
| 857 | void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | 886 | void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { |
| 858 | global_State *g = G(L); | 887 | global_State *g = G(L); |
| @@ -869,11 +898,11 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
| 869 | /* search for pointer pointing to 'o' */ | 898 | /* search for pointer pointing to 'o' */ |
| 870 | p = (testbit(ho->marked, LOCALMARK)) ? &g->allgc : &g->localgc; | 899 | p = (testbit(ho->marked, LOCALMARK)) ? &g->allgc : &g->localgc; |
| 871 | for (; *p != o; p = &gch(*p)->next) { /* empty */ } | 900 | for (; *p != o; p = &gch(*p)->next) { /* empty */ } |
| 872 | *p = ho->next; /* remove 'o' from 'allgc' list */ | 901 | *p = ho->next; /* remove 'o' from its list */ |
| 873 | ho->next = g->finobj; /* link it in list 'finobj' */ | 902 | p = (testbit(ho->marked, LOCALMARK)) ? &g->finobj : &g->localfin; |
| 874 | g->finobj = o; | 903 | ho->next = *p; /* link it in a "fin" list */ |
| 904 | *p = o; | ||
| 875 | l_setbit(ho->marked, FINALIZEDBIT); /* mark it as such */ | 905 | l_setbit(ho->marked, FINALIZEDBIT); /* mark it as such */ |
| 876 | l_setbit(ho->marked, LOCALMARK); /* not in 'localgc' anymore */ | ||
| 877 | if (!keepinvariant(g)) /* not keeping invariant? */ | 906 | if (!keepinvariant(g)) /* not keeping invariant? */ |
| 878 | makewhite(g, o); /* "sweep" object */ | 907 | makewhite(g, o); /* "sweep" object */ |
| 879 | } | 908 | } |
| @@ -918,7 +947,8 @@ static void localmark (global_State *g) { | |||
| 918 | } | 947 | } |
| 919 | 948 | ||
| 920 | 949 | ||
| 921 | static void localsweep (lua_State *L, global_State *g, GCObject **p) { | 950 | static void localsweep (lua_State *L, global_State *g) { |
| 951 | GCObject **p = &g->localgc; | ||
| 922 | while (*p != NULL) { | 952 | while (*p != NULL) { |
| 923 | GCObject *curr = *p; | 953 | GCObject *curr = *p; |
| 924 | if (!islocal(curr)) { /* is 'curr' no more local? */ | 954 | if (!islocal(curr)) { /* is 'curr' no more local? */ |
| @@ -946,11 +976,41 @@ static void localsweep (lua_State *L, global_State *g, GCObject **p) { | |||
| 946 | } | 976 | } |
| 947 | 977 | ||
| 948 | 978 | ||
| 979 | static void separatelocal (global_State *g, int all) { | ||
| 980 | GCObject **p = &g->localfin; | ||
| 981 | GCObject **lastnext = findlast(&g->tobefnz); | ||
| 982 | while (*p != NULL) { | ||
| 983 | GCObject *curr = *p; | ||
| 984 | if (!islocal(curr)) { /* is 'curr' no more local? */ | ||
| 985 | *p = curr->gch.next; /* remove 'curr' from list */ | ||
| 986 | curr->gch.next = g->finobj; /* link 'curr' in 'finobj' list */ | ||
| 987 | g->finobj = curr; | ||
| 988 | /* mark it as out of local list */ | ||
| 989 | l_setbit(curr->gch.marked, LOCALMARK); | ||
| 990 | } | ||
| 991 | else { /* still local */ | ||
| 992 | if (testbit(curr->gch.marked, LOCALMARK) && !all) { /* locally alive? */ | ||
| 993 | resetbit(curr->gch.marked, LOCALMARK); | ||
| 994 | p = &curr->gch.next; /* go to next element */ | ||
| 995 | } | ||
| 996 | else { /* object is "dead" */ | ||
| 997 | *p = curr->gch.next; /* remove 'curr' from list */ | ||
| 998 | curr->gch.next = *lastnext; /* link at the end of 'tobefnz' list */ | ||
| 999 | *lastnext = curr; | ||
| 1000 | lastnext = &curr->gch.next; | ||
| 1001 | } | ||
| 1002 | } | ||
| 1003 | } | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | |||
| 949 | static void luaC_localcollection (lua_State *L) { | 1007 | static void luaC_localcollection (lua_State *L) { |
| 950 | global_State *g = G(L); | 1008 | global_State *g = G(L); |
| 951 | lua_assert(g->gcstate == GCSpause); | 1009 | lua_assert(g->gcstate == GCSpause); |
| 952 | localmark(g); | 1010 | localmark(g); |
| 953 | localsweep(L, g, &g->localgc); | 1011 | localsweep(L, g); |
| 1012 | separatelocal(g, 0); | ||
| 1013 | callallpendingfinalizers(L, 1); | ||
| 954 | } | 1014 | } |
| 955 | 1015 | ||
| 956 | /* }====================================================== */ | 1016 | /* }====================================================== */ |
| @@ -997,24 +1057,15 @@ static int entersweep (lua_State *L) { | |||
| 997 | } | 1057 | } |
| 998 | 1058 | ||
| 999 | 1059 | ||
| 1000 | /* | ||
| 1001 | ** call all pending finalizers | ||
| 1002 | */ | ||
| 1003 | static void callallpendingfinalizers (lua_State *L, int propagateerrors) { | ||
| 1004 | global_State *g = G(L); | ||
| 1005 | while (g->tobefnz) | ||
| 1006 | GCTM(L, propagateerrors); | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | |||
| 1010 | void luaC_freeallobjects (lua_State *L) { | 1060 | void luaC_freeallobjects (lua_State *L) { |
| 1011 | global_State *g = G(L); | 1061 | global_State *g = G(L); |
| 1012 | separatetobefnz(L, 1); /* separate all objects with finalizers */ | 1062 | separatetobefnz(g, 1); /* separate all objects with finalizers */ |
| 1013 | lua_assert(g->finobj == NULL); | 1063 | lua_assert(g->finobj == NULL && g->localfin == NULL); |
| 1014 | callallpendingfinalizers(L, 0); | 1064 | callallpendingfinalizers(L, 0); |
| 1015 | g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ | 1065 | g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ |
| 1016 | g->gckind = KGC_NORMAL; | 1066 | g->gckind = KGC_NORMAL; |
| 1017 | sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ | 1067 | sweepwholelist(L, &g->localfin); /* finalizers can create objs. with fins. */ |
| 1068 | sweepwholelist(L, &g->finobj); | ||
| 1018 | sweepwholelist(L, &g->localgc); | 1069 | sweepwholelist(L, &g->localgc); |
| 1019 | sweepwholelist(L, &g->allgc); | 1070 | sweepwholelist(L, &g->allgc); |
| 1020 | sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ | 1071 | sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ |
| @@ -1045,7 +1096,7 @@ static l_mem atomic (lua_State *L) { | |||
| 1045 | clearvalues(g, g->allweak, NULL); | 1096 | clearvalues(g, g->allweak, NULL); |
| 1046 | origweak = g->weak; origall = g->allweak; | 1097 | origweak = g->weak; origall = g->allweak; |
| 1047 | work += g->GCmemtrav; /* stop counting (objects being finalized) */ | 1098 | work += g->GCmemtrav; /* stop counting (objects being finalized) */ |
| 1048 | separatetobefnz(L, 0); /* separate objects to be finalized */ | 1099 | separatetobefnz(g, 0); /* separate objects to be finalized */ |
| 1049 | markbeingfnz(g); /* mark objects that will be finalized */ | 1100 | markbeingfnz(g); /* mark objects that will be finalized */ |
| 1050 | propagateall(g); /* remark, to propagate `preserveness' */ | 1101 | propagateall(g); /* remark, to propagate `preserveness' */ |
| 1051 | work -= g->GCmemtrav; /* restart counting */ | 1102 | work -= g->GCmemtrav; /* restart counting */ |
| @@ -1106,6 +1157,9 @@ static lu_mem singlestep (lua_State *L) { | |||
| 1106 | return work + sw * GCSWEEPCOST; | 1157 | return work + sw * GCSWEEPCOST; |
| 1107 | } | 1158 | } |
| 1108 | case GCSsweeplocal: { | 1159 | case GCSsweeplocal: { |
| 1160 | return sweepstep(L, g, GCSsweeplocfin, &g->localfin); | ||
| 1161 | } | ||
| 1162 | case GCSsweeplocfin: { | ||
| 1109 | return sweepstep(L, g, GCSsweepfin, &g->finobj); | 1163 | return sweepstep(L, g, GCSsweepfin, &g->finobj); |
| 1110 | } | 1164 | } |
| 1111 | case GCSsweepfin: { | 1165 | case GCSsweepfin: { |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.h,v 2.69 2013/08/29 13:49:57 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.70 2013/08/30 19:14:26 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 | */ |
| @@ -39,10 +39,11 @@ | |||
| 39 | #define GCSpropagate 0 | 39 | #define GCSpropagate 0 |
| 40 | #define GCSatomic 1 | 40 | #define GCSatomic 1 |
| 41 | #define GCSsweeplocal 2 | 41 | #define GCSsweeplocal 2 |
| 42 | #define GCSsweepfin 3 | 42 | #define GCSsweeplocfin 3 |
| 43 | #define GCSsweepall 4 | 43 | #define GCSsweepfin 4 |
| 44 | #define GCSsweepmainth 5 | 44 | #define GCSsweepall 5 |
| 45 | #define GCSpause 6 | 45 | #define GCSsweepmainth 6 |
| 46 | #define GCSpause 7 | ||
| 46 | 47 | ||
| 47 | 48 | ||
| 48 | #define issweepphase(g) \ | 49 | #define issweepphase(g) \ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.c,v 2.108 2013/08/28 18:30:26 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.109 2013/08/30 19:14:26 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 | */ |
| @@ -296,9 +296,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
| 296 | g->panic = NULL; | 296 | g->panic = NULL; |
| 297 | g->version = lua_version(NULL); | 297 | g->version = lua_version(NULL); |
| 298 | g->gcstate = GCSpause; | 298 | g->gcstate = GCSpause; |
| 299 | g->allgc = NULL; | 299 | g->localgc = g->localfin = g->allgc = g->finobj = NULL; |
| 300 | g->localgc = NULL; | ||
| 301 | g->finobj = NULL; | ||
| 302 | g->tobefnz = NULL; | 300 | g->tobefnz = NULL; |
| 303 | g->fixedgc = NULL; | 301 | g->fixedgc = NULL; |
| 304 | g->sweepgc = NULL; | 302 | g->sweepgc = NULL; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.h,v 2.91 2013/08/27 18:53:35 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.92 2013/08/30 19:14:26 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 | */ |
| @@ -121,8 +121,9 @@ typedef struct global_State { | |||
| 121 | lu_byte gcrunning; /* true if GC is running */ | 121 | lu_byte gcrunning; /* true if GC is running */ |
| 122 | GCObject *allgc; /* list of all collectable objects */ | 122 | GCObject *allgc; /* list of all collectable objects */ |
| 123 | GCObject *localgc; /* list of local objects */ | 123 | GCObject *localgc; /* list of local objects */ |
| 124 | GCObject *finobj; /* list of collectable objects with finalizers */ | 124 | GCObject *localfin; /* list of local objects with finalizers */ |
| 125 | GCObject **sweepgc; /* current position of sweep in list */ | 125 | GCObject **sweepgc; /* current position of sweep in list */ |
| 126 | GCObject *finobj; /* list of collectable objects with finalizers */ | ||
| 126 | GCObject *gray; /* list of gray objects */ | 127 | GCObject *gray; /* list of gray objects */ |
| 127 | GCObject *grayagain; /* list of objects to be traversed atomically */ | 128 | GCObject *grayagain; /* list of objects to be traversed atomically */ |
| 128 | GCObject *weak; /* list of tables with weak values */ | 129 | GCObject *weak; /* list of tables with weak values */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltests.c,v 2.151 2013/08/27 20:04:00 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.152 2013/08/30 19:14:26 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 | */ |
| @@ -202,17 +202,8 @@ static int testobjref2 (GCObject *f, GCObject *t) { | |||
| 202 | 202 | ||
| 203 | 203 | ||
| 204 | static void printobj (global_State *g, GCObject *o) { | 204 | static void printobj (global_State *g, GCObject *o) { |
| 205 | int i = 1; | 205 | printf("||%s(%p)-%s-%c(%02X)||", |
| 206 | GCObject *p; | 206 | ttypename(novariant(gch(o)->tt)), (void *)o, |
| 207 | for (p = g->allgc; p != o && p != NULL; p = gch(p)->next) i++; | ||
| 208 | if (p == NULL) { | ||
| 209 | i = 1; | ||
| 210 | for (p = g->finobj; p != o && p != NULL; p = gch(p)->next) i++; | ||
| 211 | if (p == NULL) i = 0; /* zero means 'not found' */ | ||
| 212 | else i = -i; /* negative means 'found in findobj list */ | ||
| 213 | } | ||
| 214 | printf("||%d:%s(%p)-%s-%c(%02X)||", | ||
| 215 | i, ttypename(novariant(gch(o)->tt)), (void *)o, | ||
| 216 | islocal(o)?"L":"NL", | 207 | islocal(o)?"L":"NL", |
| 217 | isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', gch(o)->marked); | 208 | isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', gch(o)->marked); |
| 218 | } | 209 | } |
| @@ -344,9 +335,10 @@ static void checkstack (global_State *g, lua_State *L1) { | |||
| 344 | 335 | ||
| 345 | static void checkobject (global_State *g, GCObject *o, int maybedead) { | 336 | static void checkobject (global_State *g, GCObject *o, int maybedead) { |
| 346 | if (isdead(g, o)) | 337 | if (isdead(g, o)) |
| 347 | lua_assert(maybedead); | 338 | lua_assert(maybedead && issweepphase(g)); |
| 348 | else { | 339 | else { |
| 349 | lua_assert(g->gcstate != GCSpause || iswhite(o)); | 340 | lua_assert(g->gcstate != GCSpause || iswhite(o)); |
| 341 | lua_assert(!islocal(o) || !testbit(gch(o)->marked, LOCALMARK)); | ||
| 350 | switch (gch(o)->tt) { | 342 | switch (gch(o)->tt) { |
| 351 | case LUA_TUSERDATA: { | 343 | case LUA_TUSERDATA: { |
| 352 | Table *mt = gco2u(o)->metatable; | 344 | Table *mt = gco2u(o)->metatable; |
| @@ -384,18 +376,18 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) { | |||
| 384 | 376 | ||
| 385 | #define TESTGRAYBIT 7 | 377 | #define TESTGRAYBIT 7 |
| 386 | 378 | ||
| 387 | static void checkgraylist (global_State *g, GCObject *l) { | 379 | static void checkgraylist (global_State *g, GCObject *o) { |
| 388 | UNUSED(g); /* better to keep it available if we need to print an object */ | 380 | ((void)g); /* better to keep it available if we need to print an object */ |
| 389 | while (l) { | 381 | while (o) { |
| 390 | lua_assert(isgray(l)); | 382 | lua_assert(isgray(o)); |
| 391 | lua_assert(!testbit(l->gch.marked, TESTGRAYBIT)); | 383 | lua_assert(!testbit(o->gch.marked, TESTGRAYBIT)); |
| 392 | l_setbit(l->gch.marked, TESTGRAYBIT); | 384 | l_setbit(o->gch.marked, TESTGRAYBIT); |
| 393 | switch (gch(l)->tt) { | 385 | switch (gch(o)->tt) { |
| 394 | case LUA_TTABLE: l = gco2t(l)->gclist; break; | 386 | case LUA_TTABLE: o = gco2t(o)->gclist; break; |
| 395 | case LUA_TLCL: l = gco2lcl(l)->gclist; break; | 387 | case LUA_TLCL: o = gco2lcl(o)->gclist; break; |
| 396 | case LUA_TCCL: l = gco2ccl(l)->gclist; break; | 388 | case LUA_TCCL: o = gco2ccl(o)->gclist; break; |
| 397 | case LUA_TTHREAD: l = gco2th(l)->gclist; break; | 389 | case LUA_TTHREAD: o = gco2th(o)->gclist; break; |
| 398 | case LUA_TPROTO: l = gco2p(l)->gclist; break; | 390 | case LUA_TPROTO: o = gco2p(o)->gclist; break; |
| 399 | default: lua_assert(0); /* other objects cannot be gray */ | 391 | default: lua_assert(0); /* other objects cannot be gray */ |
| 400 | } | 392 | } |
| 401 | } | 393 | } |
| @@ -451,30 +443,35 @@ int lua_checkmemory (lua_State *L) { | |||
| 451 | if (gch(o)->tt == LUA_TTHREAD) isthread = 1; /* now travesing threads... */ | 443 | if (gch(o)->tt == LUA_TTHREAD) isthread = 1; /* now travesing threads... */ |
| 452 | else lua_assert(!isthread); /* ... and only threads */ | 444 | else lua_assert(!isthread); /* ... and only threads */ |
| 453 | checkobject(g, o, maybedead); | 445 | checkobject(g, o, maybedead); |
| 454 | lua_assert(!tofinalize(o)); | 446 | lua_assert(!tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); |
| 455 | lua_assert(testbit(o->gch.marked, LOCALMARK)); | ||
| 456 | } | 447 | } |
| 457 | /* check 'finobj' list */ | 448 | /* check 'finobj' list */ |
| 458 | checkgray(g, g->finobj); | 449 | checkgray(g, g->finobj); |
| 459 | for (o = g->finobj; o != NULL; o = gch(o)->next) { | 450 | for (o = g->finobj; o != NULL; o = gch(o)->next) { |
| 460 | lua_assert(tofinalize(o)); | 451 | checkobject(g, o, 0); |
| 452 | lua_assert(tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); | ||
| 461 | lua_assert(gch(o)->tt == LUA_TUSERDATA || | 453 | lua_assert(gch(o)->tt == LUA_TUSERDATA || |
| 462 | gch(o)->tt == LUA_TTABLE); | 454 | gch(o)->tt == LUA_TTABLE); |
| 463 | checkobject(g, o, 0); | ||
| 464 | } | 455 | } |
| 465 | /* check 'tobefnz' list */ | 456 | /* check 'tobefnz' list */ |
| 466 | checkgray(g, g->tobefnz); | 457 | checkgray(g, g->tobefnz); |
| 467 | for (o = g->tobefnz; o != NULL; o = gch(o)->next) { | 458 | for (o = g->tobefnz; o != NULL; o = gch(o)->next) { |
| 468 | lua_assert(!iswhite(o) || g->gcstate == GCSpause); | 459 | lua_assert(!iswhite(o) || g->gcstate == GCSpause); |
| 469 | lua_assert(!isdead(g, o) && tofinalize(o)); | 460 | lua_assert(!isdead(g, o) && tofinalize(o)); |
| 470 | lua_assert(gch(o)->tt == LUA_TUSERDATA || | 461 | lua_assert(gch(o)->tt == LUA_TUSERDATA || gch(o)->tt == LUA_TTABLE); |
| 471 | gch(o)->tt == LUA_TTABLE); | ||
| 472 | } | 462 | } |
| 473 | /* check 'localgc' list */ | 463 | /* check 'localgc' list */ |
| 474 | checkgray(g, g->localgc); | 464 | checkgray(g, g->localgc); |
| 475 | for (o = g->localgc; o != NULL; o = gch(o)->next) { | 465 | for (o = g->localgc; o != NULL; o = gch(o)->next) { |
| 476 | checkobject(g, o, 1); | 466 | checkobject(g, o, 1); |
| 477 | lua_assert(!testbit(o->gch.marked, LOCALMARK)); | 467 | lua_assert(!tofinalize(o) && !testbit(o->gch.marked, LOCALMARK)); |
| 468 | } | ||
| 469 | /* check 'localfin' list */ | ||
| 470 | checkgray(g, g->localfin); | ||
| 471 | for (o = g->localfin; o != NULL; o = gch(o)->next) { | ||
| 472 | checkobject(g, o, 0); | ||
| 473 | lua_assert(tofinalize(o) && !testbit(o->gch.marked, LOCALMARK)); | ||
| 474 | lua_assert(gch(o)->tt == LUA_TUSERDATA || gch(o)->tt == LUA_TTABLE); | ||
| 478 | } | 475 | } |
| 479 | return 0; | 476 | return 0; |
| 480 | } | 477 | } |
| @@ -653,7 +650,7 @@ static int gc_local (lua_State *L) { | |||
| 653 | 650 | ||
| 654 | static int gc_state (lua_State *L) { | 651 | static int gc_state (lua_State *L) { |
| 655 | static const char *statenames[] = {"propagate", "atomic", | 652 | static const char *statenames[] = {"propagate", "atomic", |
| 656 | "sweeplocal", "sweepfin", "sweepall", "sweepmainth", | 653 | "sweeplocal", "sweeplocfin", "sweepfin", "sweepall", "sweepmainth", |
| 657 | "pause", ""}; | 654 | "pause", ""}; |
| 658 | int option = luaL_checkoption(L, 1, "", statenames); | 655 | int option = luaL_checkoption(L, 1, "", statenames); |
| 659 | if (option == GCSpause + 1) { | 656 | if (option == GCSpause + 1) { |
