diff options
-rw-r--r-- | lapi.c | 35 | ||||
-rw-r--r-- | lbaselib.c | 8 | ||||
-rw-r--r-- | lfunc.c | 3 | ||||
-rw-r--r-- | lgc.c | 115 | ||||
-rw-r--r-- | lgc.h | 28 | ||||
-rw-r--r-- | lstate.c | 7 | ||||
-rw-r--r-- | lstate.h | 4 | ||||
-rw-r--r-- | lstring.c | 3 | ||||
-rw-r--r-- | ltests.c | 26 | ||||
-rw-r--r-- | lua.h | 7 |
10 files changed, 46 insertions, 190 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 2.184 2013/06/20 15:12:43 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.185 2013/07/05 14:29:51 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 | */ |
@@ -1068,19 +1068,13 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { | |||
1068 | break; | 1068 | break; |
1069 | } | 1069 | } |
1070 | case LUA_GCSTEP: { | 1070 | case LUA_GCSTEP: { |
1071 | if (g->gckind == KGC_GEN) { /* generational mode? */ | 1071 | lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE; |
1072 | res = (g->GCestimate == 0); /* true if it will do major collection */ | 1072 | if (g->gcrunning) |
1073 | luaC_forcestep(L); /* do a single step */ | 1073 | debt += g->GCdebt; /* include current debt */ |
1074 | } | 1074 | luaE_setdebt(g, debt); |
1075 | else { | 1075 | luaC_forcestep(L); |
1076 | lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE; | 1076 | if (g->gcstate == GCSpause) /* end of cycle? */ |
1077 | if (g->gcrunning) | 1077 | res = 1; /* signal it */ |
1078 | debt += g->GCdebt; /* include current debt */ | ||
1079 | luaE_setdebt(g, debt); | ||
1080 | luaC_forcestep(L); | ||
1081 | if (g->gcstate == GCSpause) /* end of cycle? */ | ||
1082 | res = 1; /* signal it */ | ||
1083 | } | ||
1084 | break; | 1078 | break; |
1085 | } | 1079 | } |
1086 | case LUA_GCSETPAUSE: { | 1080 | case LUA_GCSETPAUSE: { |
@@ -1088,11 +1082,6 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { | |||
1088 | g->gcpause = data; | 1082 | g->gcpause = data; |
1089 | break; | 1083 | break; |
1090 | } | 1084 | } |
1091 | case LUA_GCSETMAJORINC: { | ||
1092 | res = g->gcmajorinc; | ||
1093 | g->gcmajorinc = data; | ||
1094 | break; | ||
1095 | } | ||
1096 | case LUA_GCSETSTEPMUL: { | 1085 | case LUA_GCSETSTEPMUL: { |
1097 | res = g->gcstepmul; | 1086 | res = g->gcstepmul; |
1098 | g->gcstepmul = data; | 1087 | g->gcstepmul = data; |
@@ -1102,14 +1091,6 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { | |||
1102 | res = g->gcrunning; | 1091 | res = g->gcrunning; |
1103 | break; | 1092 | break; |
1104 | } | 1093 | } |
1105 | case LUA_GCGEN: { /* change collector to generational mode */ | ||
1106 | luaC_changemode(L, KGC_GEN); | ||
1107 | break; | ||
1108 | } | ||
1109 | case LUA_GCINC: { /* change collector to incremental mode */ | ||
1110 | luaC_changemode(L, KGC_NORMAL); | ||
1111 | break; | ||
1112 | } | ||
1113 | default: res = -1; /* invalid option */ | 1094 | default: res = -1; /* invalid option */ |
1114 | } | 1095 | } |
1115 | lua_unlock(L); | 1096 | lua_unlock(L); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.279 2013/07/05 14:39:15 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.280 2013/07/10 17:15:12 roberto Exp roberto $ |
3 | ** Basic library | 3 | ** Basic library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -174,11 +174,9 @@ static int luaB_rawset (lua_State *L) { | |||
174 | 174 | ||
175 | static int luaB_collectgarbage (lua_State *L) { | 175 | static int luaB_collectgarbage (lua_State *L) { |
176 | static const char *const opts[] = {"stop", "restart", "collect", | 176 | static const char *const opts[] = {"stop", "restart", "collect", |
177 | "count", "step", "setpause", "setstepmul", | 177 | "count", "step", "setpause", "setstepmul", "isrunning", NULL}; |
178 | "setmajorinc", "isrunning", "generational", "incremental", NULL}; | ||
179 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, | 178 | static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, |
180 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, | 179 | LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, LUA_GCISRUNNING}; |
181 | LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; | ||
182 | int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; | 180 | int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; |
183 | int ex = luaL_optint(L, 2, 0); | 181 | int ex = luaL_optint(L, 2, 0); |
184 | int res = lua_gc(L, o, ex); | 182 | int res = lua_gc(L, o, ex); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lfunc.c,v 2.29 2012/05/08 13:53:33 roberto Exp roberto $ | 2 | ** $Id: lfunc.c,v 2.30 2012/10/03 12:36:46 roberto Exp roberto $ |
3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -52,7 +52,6 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { | |||
52 | while (*pp != NULL && (p = gco2uv(*pp))->v >= level) { | 52 | while (*pp != NULL && (p = gco2uv(*pp))->v >= level) { |
53 | GCObject *o = obj2gco(p); | 53 | GCObject *o = obj2gco(p); |
54 | lua_assert(p->v != &p->u.value); | 54 | lua_assert(p->v != &p->u.value); |
55 | lua_assert(!isold(o) || isold(obj2gco(L))); | ||
56 | if (p->v == level) { /* found a corresponding upvalue? */ | 55 | if (p->v == level) { /* found a corresponding upvalue? */ |
57 | if (isdead(g, o)) /* is it dead? */ | 56 | if (isdead(g, o)) /* is it dead? */ |
58 | changewhite(o); /* resurrect it */ | 57 | changewhite(o); /* resurrect it */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.140.1.2 2013/04/26 18:22:05 roberto Exp $ | 2 | ** $Id: lgc.c,v 2.141 2013/04/26 18:26:49 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 | */ |
@@ -52,10 +52,10 @@ | |||
52 | 52 | ||
53 | 53 | ||
54 | /* | 54 | /* |
55 | ** 'makewhite' erases all color bits plus the old bit and then | 55 | ** 'makewhite' erases all color bits then sets only the current white |
56 | ** sets only the current white bit | 56 | ** bit |
57 | */ | 57 | */ |
58 | #define maskcolors (~(bit2mask(BLACKBIT, OLDBIT) | WHITEBITS)) | 58 | #define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS)) |
59 | #define makewhite(g,x) \ | 59 | #define makewhite(g,x) \ |
60 | (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) | 60 | (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) |
61 | 61 | ||
@@ -137,7 +137,7 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { | |||
137 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); | 137 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); |
138 | lua_assert(g->gcstate != GCSpause); | 138 | lua_assert(g->gcstate != GCSpause); |
139 | lua_assert(gch(o)->tt != LUA_TTABLE); | 139 | lua_assert(gch(o)->tt != LUA_TTABLE); |
140 | if (keepinvariantout(g)) /* must keep invariant? */ | 140 | if (keepinvariant(g)) /* must keep invariant? */ |
141 | reallymarkobject(g, v); /* restore invariant */ | 141 | reallymarkobject(g, v); /* restore invariant */ |
142 | else { /* sweep phase */ | 142 | else { /* sweep phase */ |
143 | lua_assert(issweepphase(g)); | 143 | lua_assert(issweepphase(g)); |
@@ -184,7 +184,7 @@ LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c) { | |||
184 | 184 | ||
185 | 185 | ||
186 | /* | 186 | /* |
187 | ** check color (and invariants) for an upvalue that was closed, | 187 | ** check color (and invariants) for an upvalue that is being closed, |
188 | ** i.e., moved into the 'allgc' list | 188 | ** i.e., moved into the 'allgc' list |
189 | */ | 189 | */ |
190 | void luaC_checkupvalcolor (global_State *g, UpVal *uv) { | 190 | void luaC_checkupvalcolor (global_State *g, UpVal *uv) { |
@@ -192,7 +192,6 @@ void luaC_checkupvalcolor (global_State *g, UpVal *uv) { | |||
192 | lua_assert(!isblack(o)); /* open upvalues are never black */ | 192 | lua_assert(!isblack(o)); /* open upvalues are never black */ |
193 | if (isgray(o)) { | 193 | if (isgray(o)) { |
194 | if (keepinvariant(g)) { | 194 | if (keepinvariant(g)) { |
195 | resetoldbit(o); /* see MOVE OLD rule */ | ||
196 | gray2black(o); /* it is being visited now */ | 195 | gray2black(o); /* it is being visited now */ |
197 | markvalue(g, uv->v); | 196 | markvalue(g, uv->v); |
198 | } | 197 | } |
@@ -331,8 +330,7 @@ static void remarkupvals (global_State *g) { | |||
331 | 330 | ||
332 | 331 | ||
333 | /* | 332 | /* |
334 | ** mark root set and reset all gray lists, to start a new | 333 | ** mark root set and reset all gray lists, to start a new collection |
335 | ** incremental (or full) collection | ||
336 | */ | 334 | */ |
337 | static void restartcollection (global_State *g) { | 335 | static void restartcollection (global_State *g) { |
338 | g->gray = g->grayagain = NULL; | 336 | g->gray = g->grayagain = NULL; |
@@ -708,29 +706,14 @@ static void sweepthread (lua_State *L, lua_State *L1) { | |||
708 | /* | 706 | /* |
709 | ** sweep at most 'count' elements from a list of GCObjects erasing dead | 707 | ** sweep at most 'count' elements from a list of GCObjects erasing dead |
710 | ** objects, where a dead (not alive) object is one marked with the "old" | 708 | ** objects, where a dead (not alive) object is one marked with the "old" |
711 | ** (non current) white and not fixed. | 709 | ** (non current) white and not fixed; change all non-dead objects back |
712 | ** In non-generational mode, change all non-dead objects back to white, | 710 | ** to white, preparing for next collection cycle. |
713 | ** preparing for next collection cycle. | ||
714 | ** In generational mode, keep black objects black, and also mark them as | ||
715 | ** old; stop when hitting an old object, as all objects after that | ||
716 | ** one will be old too. | ||
717 | ** When object is a thread, sweep its list of open upvalues too. | 711 | ** When object is a thread, sweep its list of open upvalues too. |
718 | */ | 712 | */ |
719 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | 713 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { |
720 | global_State *g = G(L); | 714 | global_State *g = G(L); |
721 | int ow = otherwhite(g); | 715 | int ow = otherwhite(g); |
722 | int toclear, toset; /* bits to clear and to set in all live objects */ | 716 | int white = luaC_white(g); /* current white */ |
723 | int tostop; /* stop sweep when this is true */ | ||
724 | if (isgenerational(g)) { /* generational mode? */ | ||
725 | toclear = ~0; /* clear nothing */ | ||
726 | toset = bitmask(OLDBIT); /* set the old bit of all surviving objects */ | ||
727 | tostop = bitmask(OLDBIT); /* do not sweep old generation */ | ||
728 | } | ||
729 | else { /* normal mode */ | ||
730 | toclear = maskcolors; /* clear all color bits + old bit */ | ||
731 | toset = luaC_white(g); /* make object white */ | ||
732 | tostop = 0; /* do not stop */ | ||
733 | } | ||
734 | while (*p != NULL && count-- > 0) { | 717 | while (*p != NULL && count-- > 0) { |
735 | GCObject *curr = *p; | 718 | GCObject *curr = *p; |
736 | int marked = gch(curr)->marked; | 719 | int marked = gch(curr)->marked; |
@@ -739,12 +722,10 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | |||
739 | freeobj(L, curr); /* erase 'curr' */ | 722 | freeobj(L, curr); /* erase 'curr' */ |
740 | } | 723 | } |
741 | else { | 724 | else { |
742 | if (testbits(marked, tostop)) | ||
743 | return NULL; /* stop sweeping this list */ | ||
744 | if (gch(curr)->tt == LUA_TTHREAD) | 725 | if (gch(curr)->tt == LUA_TTHREAD) |
745 | sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ | 726 | sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ |
746 | /* update marks */ | 727 | /* update marks */ |
747 | gch(curr)->marked = cast_byte((marked & toclear) | toset); | 728 | gch(curr)->marked = cast_byte((marked & maskcolors) | white); |
748 | p = &gch(curr)->next; /* go to next element */ | 729 | p = &gch(curr)->next; /* go to next element */ |
749 | } | 730 | } |
750 | } | 731 | } |
@@ -793,8 +774,7 @@ static GCObject *udata2finalize (global_State *g) { | |||
793 | gch(o)->next = g->allgc; /* return it to 'allgc' list */ | 774 | gch(o)->next = g->allgc; /* return it to 'allgc' list */ |
794 | g->allgc = o; | 775 | g->allgc = o; |
795 | resetbit(gch(o)->marked, SEPARATED); /* mark that it is not in 'tobefnz' */ | 776 | resetbit(gch(o)->marked, SEPARATED); /* mark that it is not in 'tobefnz' */ |
796 | lua_assert(!isold(o)); /* see MOVE OLD rule */ | 777 | if (!keepinvariant(g)) /* not keeping invariant? */ |
797 | if (!keepinvariantout(g)) /* not keeping invariant? */ | ||
798 | makewhite(g, o); /* "sweep" object */ | 778 | makewhite(g, o); /* "sweep" object */ |
799 | return o; | 779 | return o; |
800 | } | 780 | } |
@@ -889,10 +869,8 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
889 | ho->next = g->finobj; /* link it in list 'finobj' */ | 869 | ho->next = g->finobj; /* link it in list 'finobj' */ |
890 | g->finobj = o; | 870 | g->finobj = o; |
891 | l_setbit(ho->marked, SEPARATED); /* mark it as such */ | 871 | l_setbit(ho->marked, SEPARATED); /* mark it as such */ |
892 | if (!keepinvariantout(g)) /* not keeping invariant? */ | 872 | if (!keepinvariant(g)) /* not keeping invariant? */ |
893 | makewhite(g, o); /* "sweep" object */ | 873 | makewhite(g, o); /* "sweep" object */ |
894 | else | ||
895 | resetoldbit(o); /* see MOVE OLD rule */ | ||
896 | } | 874 | } |
897 | } | 875 | } |
898 | 876 | ||
@@ -947,36 +925,12 @@ static int entersweep (lua_State *L) { | |||
947 | 925 | ||
948 | 926 | ||
949 | /* | 927 | /* |
950 | ** change GC mode | ||
951 | */ | ||
952 | void luaC_changemode (lua_State *L, int mode) { | ||
953 | global_State *g = G(L); | ||
954 | if (mode == g->gckind) return; /* nothing to change */ | ||
955 | if (mode == KGC_GEN) { /* change to generational mode */ | ||
956 | /* make sure gray lists are consistent */ | ||
957 | luaC_runtilstate(L, bitmask(GCSpropagate)); | ||
958 | g->GCestimate = gettotalbytes(g); | ||
959 | g->gckind = KGC_GEN; | ||
960 | } | ||
961 | else { /* change to incremental mode */ | ||
962 | /* sweep all objects to turn them back to white | ||
963 | (as white has not changed, nothing extra will be collected) */ | ||
964 | g->gckind = KGC_NORMAL; | ||
965 | entersweep(L); | ||
966 | luaC_runtilstate(L, ~sweepphases); | ||
967 | } | ||
968 | } | ||
969 | |||
970 | |||
971 | /* | ||
972 | ** call all pending finalizers | 928 | ** call all pending finalizers |
973 | */ | 929 | */ |
974 | static void callallpendingfinalizers (lua_State *L, int propagateerrors) { | 930 | static void callallpendingfinalizers (lua_State *L, int propagateerrors) { |
975 | global_State *g = G(L); | 931 | global_State *g = G(L); |
976 | while (g->tobefnz) { | 932 | while (g->tobefnz) |
977 | resetoldbit(g->tobefnz); | ||
978 | GCTM(L, propagateerrors); | 933 | GCTM(L, propagateerrors); |
979 | } | ||
980 | } | 934 | } |
981 | 935 | ||
982 | 936 | ||
@@ -1014,7 +968,7 @@ static l_mem atomic (lua_State *L) { | |||
1014 | work -= g->GCmemtrav; /* restart counting */ | 968 | work -= g->GCmemtrav; /* restart counting */ |
1015 | convergeephemerons(g); | 969 | convergeephemerons(g); |
1016 | /* at this point, all strongly accessible objects are marked. */ | 970 | /* at this point, all strongly accessible objects are marked. */ |
1017 | /* clear values from weak tables, before checking finalizers */ | 971 | /* Clear values from weak tables, before checking finalizers */ |
1018 | clearvalues(g, g->weak, NULL); | 972 | clearvalues(g, g->weak, NULL); |
1019 | clearvalues(g, g->allweak, NULL); | 973 | clearvalues(g, g->allweak, NULL); |
1020 | origweak = g->weak; origall = g->allweak; | 974 | origweak = g->weak; origall = g->allweak; |
@@ -1043,7 +997,6 @@ static lu_mem singlestep (lua_State *L) { | |||
1043 | case GCSpause: { | 997 | case GCSpause: { |
1044 | /* start to count memory traversed */ | 998 | /* start to count memory traversed */ |
1045 | g->GCmemtrav = g->strt.size * sizeof(GCObject*); | 999 | g->GCmemtrav = g->strt.size * sizeof(GCObject*); |
1046 | lua_assert(!isgenerational(g)); | ||
1047 | restartcollection(g); | 1000 | restartcollection(g); |
1048 | g->gcstate = GCSpropagate; | 1001 | g->gcstate = GCSpropagate; |
1049 | return g->GCmemtrav; | 1002 | return g->GCmemtrav; |
@@ -1114,28 +1067,6 @@ void luaC_runtilstate (lua_State *L, int statesmask) { | |||
1114 | } | 1067 | } |
1115 | 1068 | ||
1116 | 1069 | ||
1117 | static void generationalcollection (lua_State *L) { | ||
1118 | global_State *g = G(L); | ||
1119 | lua_assert(g->gcstate == GCSpropagate); | ||
1120 | if (g->GCestimate == 0) { /* signal for another major collection? */ | ||
1121 | luaC_fullgc(L, 0); /* perform a full regular collection */ | ||
1122 | g->GCestimate = gettotalbytes(g); /* update control */ | ||
1123 | } | ||
1124 | else { | ||
1125 | lu_mem estimate = g->GCestimate; | ||
1126 | luaC_runtilstate(L, bitmask(GCSpause)); /* run complete (minor) cycle */ | ||
1127 | g->gcstate = GCSpropagate; /* skip restart */ | ||
1128 | if (gettotalbytes(g) > (estimate / 100) * g->gcmajorinc) | ||
1129 | g->GCestimate = 0; /* signal for a major collection */ | ||
1130 | else | ||
1131 | g->GCestimate = estimate; /* keep estimate from last major coll. */ | ||
1132 | |||
1133 | } | ||
1134 | setpause(g, gettotalbytes(g)); | ||
1135 | lua_assert(g->gcstate == GCSpropagate); | ||
1136 | } | ||
1137 | |||
1138 | |||
1139 | static void incstep (lua_State *L) { | 1070 | static void incstep (lua_State *L) { |
1140 | global_State *g = G(L); | 1071 | global_State *g = G(L); |
1141 | l_mem debt = g->GCdebt; | 1072 | l_mem debt = g->GCdebt; |
@@ -1163,8 +1094,7 @@ static void incstep (lua_State *L) { | |||
1163 | void luaC_forcestep (lua_State *L) { | 1094 | void luaC_forcestep (lua_State *L) { |
1164 | global_State *g = G(L); | 1095 | global_State *g = G(L); |
1165 | int i; | 1096 | int i; |
1166 | if (isgenerational(g)) generationalcollection(L); | 1097 | incstep(L); |
1167 | else incstep(L); | ||
1168 | /* run a few finalizers (or all of them at the end of a collect cycle) */ | 1098 | /* run a few finalizers (or all of them at the end of a collect cycle) */ |
1169 | for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++) | 1099 | for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++) |
1170 | GCTM(L, 1); /* call one finalizer */ | 1100 | GCTM(L, 1); /* call one finalizer */ |
@@ -1188,14 +1118,11 @@ void luaC_step (lua_State *L) { | |||
1188 | */ | 1118 | */ |
1189 | void luaC_fullgc (lua_State *L, int isemergency) { | 1119 | void luaC_fullgc (lua_State *L, int isemergency) { |
1190 | global_State *g = G(L); | 1120 | global_State *g = G(L); |
1191 | int origkind = g->gckind; | 1121 | lua_assert(g->gckind == KGC_NORMAL); |
1192 | lua_assert(origkind != KGC_EMERGENCY); | ||
1193 | if (isemergency) /* do not run finalizers during emergency GC */ | 1122 | if (isemergency) /* do not run finalizers during emergency GC */ |
1194 | g->gckind = KGC_EMERGENCY; | 1123 | g->gckind = KGC_EMERGENCY; |
1195 | else { | 1124 | else |
1196 | g->gckind = KGC_NORMAL; | ||
1197 | callallpendingfinalizers(L, 1); | 1125 | callallpendingfinalizers(L, 1); |
1198 | } | ||
1199 | if (keepinvariant(g)) { /* may there be some black objects? */ | 1126 | if (keepinvariant(g)) { /* may there be some black objects? */ |
1200 | /* must sweep all objects to turn them back to white | 1127 | /* must sweep all objects to turn them back to white |
1201 | (as white has not changed, nothing will be collected) */ | 1128 | (as white has not changed, nothing will be collected) */ |
@@ -1205,11 +1132,7 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
1205 | luaC_runtilstate(L, bitmask(GCSpause)); | 1132 | luaC_runtilstate(L, bitmask(GCSpause)); |
1206 | luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ | 1133 | luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ |
1207 | luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */ | 1134 | luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */ |
1208 | if (origkind == KGC_GEN) { /* generational mode? */ | 1135 | g->gckind = KGC_NORMAL; |
1209 | /* generational mode must be kept in propagate phase */ | ||
1210 | luaC_runtilstate(L, bitmask(GCSpropagate)); | ||
1211 | } | ||
1212 | g->gckind = origkind; | ||
1213 | setpause(g, gettotalbytes(g)); | 1136 | setpause(g, gettotalbytes(g)); |
1214 | if (!isemergency) /* do not run finalizers during emergency GC */ | 1137 | if (!isemergency) /* do not run finalizers during emergency GC */ |
1215 | callallpendingfinalizers(L, 1); | 1138 | callallpendingfinalizers(L, 1); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.h,v 2.57 2012/07/04 15:52:38 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.58 2012/09/11 12:53:08 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 | */ |
@@ -47,27 +47,16 @@ | |||
47 | #define issweepphase(g) \ | 47 | #define issweepphase(g) \ |
48 | (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) | 48 | (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) |
49 | 49 | ||
50 | #define isgenerational(g) ((g)->gckind == KGC_GEN) | ||
51 | 50 | ||
52 | /* | 51 | /* |
53 | ** macros to tell when main invariant (white objects cannot point to black | 52 | ** macro to tell when main invariant (white objects cannot point to black |
54 | ** ones) must be kept. During a non-generational collection, the sweep | 53 | ** ones) must be kept. During a collection, the sweep |
55 | ** phase may break the invariant, as objects turned white may point to | 54 | ** phase may break the invariant, as objects turned white may point to |
56 | ** still-black objects. The invariant is restored when sweep ends and | 55 | ** still-black objects. The invariant is restored when sweep ends and |
57 | ** all objects are white again. During a generational collection, the | 56 | ** all objects are white again. |
58 | ** invariant must be kept all times. | ||
59 | */ | 57 | */ |
60 | 58 | ||
61 | #define keepinvariant(g) (isgenerational(g) || g->gcstate <= GCSatomic) | 59 | #define keepinvariant(g) (g->gcstate <= GCSatomic) |
62 | |||
63 | |||
64 | /* | ||
65 | ** Outside the collector, the state in generational mode is kept in | ||
66 | ** 'propagate', so 'keepinvariant' is always true. | ||
67 | */ | ||
68 | #define keepinvariantout(g) \ | ||
69 | check_exp(g->gcstate == GCSpropagate || !isgenerational(g), \ | ||
70 | g->gcstate <= GCSatomic) | ||
71 | 60 | ||
72 | 61 | ||
73 | /* | 62 | /* |
@@ -90,7 +79,6 @@ | |||
90 | #define FINALIZEDBIT 3 /* object has been separated for finalization */ | 79 | #define FINALIZEDBIT 3 /* object has been separated for finalization */ |
91 | #define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */ | 80 | #define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */ |
92 | #define FIXEDBIT 5 /* object is fixed (should not be collected) */ | 81 | #define FIXEDBIT 5 /* object is fixed (should not be collected) */ |
93 | #define OLDBIT 6 /* object is old (only in generational mode) */ | ||
94 | /* bit 7 is currently used by tests (luaL_checkmemory) */ | 82 | /* bit 7 is currently used by tests (luaL_checkmemory) */ |
95 | 83 | ||
96 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) | 84 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) |
@@ -101,11 +89,6 @@ | |||
101 | #define isgray(x) /* neither white nor black */ \ | 89 | #define isgray(x) /* neither white nor black */ \ |
102 | (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) | 90 | (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) |
103 | 91 | ||
104 | #define isold(x) testbit((x)->gch.marked, OLDBIT) | ||
105 | |||
106 | /* MOVE OLD rule: whenever an object is moved to the beginning of | ||
107 | a GC list, its old bit must be cleared */ | ||
108 | #define resetoldbit(o) resetbit((o)->gch.marked, OLDBIT) | ||
109 | 92 | ||
110 | #define otherwhite(g) (g->currentwhite ^ WHITEBITS) | 93 | #define otherwhite(g) (g->currentwhite ^ WHITEBITS) |
111 | #define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) | 94 | #define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) |
@@ -152,6 +135,5 @@ LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); | |||
152 | LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); | 135 | LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); |
153 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); | 136 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); |
154 | LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); | 137 | LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); |
155 | LUAI_FUNC void luaC_changemode (lua_State *L, int mode); | ||
156 | 138 | ||
157 | #endif | 139 | #endif |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.98 2012/05/30 12:33:44 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.99 2012/10/02 17:40:53 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 | */ |
@@ -30,10 +30,6 @@ | |||
30 | #define LUAI_GCPAUSE 200 /* 200% */ | 30 | #define LUAI_GCPAUSE 200 /* 200% */ |
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | #if !defined(LUAI_GCMAJOR) | ||
34 | #define LUAI_GCMAJOR 200 /* 200% */ | ||
35 | #endif | ||
36 | |||
37 | #if !defined(LUAI_GCMUL) | 33 | #if !defined(LUAI_GCMUL) |
38 | #define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ | 34 | #define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ |
39 | #endif | 35 | #endif |
@@ -298,7 +294,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
298 | g->totalbytes = sizeof(LG); | 294 | g->totalbytes = sizeof(LG); |
299 | g->GCdebt = 0; | 295 | g->GCdebt = 0; |
300 | g->gcpause = LUAI_GCPAUSE; | 296 | g->gcpause = LUAI_GCPAUSE; |
301 | g->gcmajorinc = LUAI_GCMAJOR; | ||
302 | g->gcstepmul = LUAI_GCMUL; | 297 | g->gcstepmul = LUAI_GCMUL; |
303 | for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; | 298 | for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; |
304 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { | 299 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 2.81 2012/06/08 15:14:04 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.82 2012/07/02 13:37:04 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 | */ |
@@ -53,7 +53,6 @@ struct lua_longjmp; /* defined in ldo.c */ | |||
53 | /* kinds of Garbage Collection */ | 53 | /* kinds of Garbage Collection */ |
54 | #define KGC_NORMAL 0 | 54 | #define KGC_NORMAL 0 |
55 | #define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ | 55 | #define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ |
56 | #define KGC_GEN 2 /* generational collection */ | ||
57 | 56 | ||
58 | 57 | ||
59 | typedef struct stringtable { | 58 | typedef struct stringtable { |
@@ -137,7 +136,6 @@ typedef struct global_State { | |||
137 | UpVal uvhead; /* head of double-linked list of all open upvalues */ | 136 | UpVal uvhead; /* head of double-linked list of all open upvalues */ |
138 | Mbuffer buff; /* temporary buffer for string concatenation */ | 137 | Mbuffer buff; /* temporary buffer for string concatenation */ |
139 | int gcpause; /* size of pause between successive GCs */ | 138 | int gcpause; /* size of pause between successive GCs */ |
140 | int gcmajorinc; /* pause between major collections (only in gen. mode) */ | ||
141 | int gcstepmul; /* GC `granularity' */ | 139 | int gcstepmul; /* GC `granularity' */ |
142 | lua_CFunction panic; /* to be called in unprotected errors */ | 140 | lua_CFunction panic; /* to be called in unprotected errors */ |
143 | struct lua_State *mainthread; | 141 | struct lua_State *mainthread; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.c,v 2.26 2013/01/08 13:50:10 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 2.27 2013/06/19 14:27:00 roberto Exp roberto $ |
3 | ** String table (keeps all strings handled by Lua) | 3 | ** String table (keeps all strings handled by Lua) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -79,7 +79,6 @@ void luaS_resize (lua_State *L, int newsize) { | |||
79 | unsigned int h = lmod(gco2ts(p)->hash, newsize); /* new position */ | 79 | unsigned int h = lmod(gco2ts(p)->hash, newsize); /* new position */ |
80 | gch(p)->next = tb->hash[h]; /* chain it */ | 80 | gch(p)->next = tb->hash[h]; /* chain it */ |
81 | tb->hash[h] = p; | 81 | tb->hash[h] = p; |
82 | resetoldbit(p); /* see MOVE OLD rule */ | ||
83 | p = next; | 82 | p = next; |
84 | } | 83 | } |
85 | } | 84 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltests.c,v 2.138 2013/05/07 19:01:16 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.139 2013/06/20 21:59:13 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 | */ |
@@ -405,15 +405,8 @@ static void markgrays (global_State *g) { | |||
405 | } | 405 | } |
406 | 406 | ||
407 | 407 | ||
408 | static void checkold (global_State *g, GCObject *o) { | 408 | static void checkgray (global_State *g, GCObject *o) { |
409 | int isold = 0; | ||
410 | for (; o != NULL; o = gch(o)->next) { | 409 | for (; o != NULL; o = gch(o)->next) { |
411 | if (isold(o)) { /* old generation? */ | ||
412 | lua_assert(isgenerational(g)); | ||
413 | if (!issweepphase(g)) | ||
414 | isold = 1; | ||
415 | } | ||
416 | else lua_assert(!isold); /* non-old object cannot be after an old one */ | ||
417 | if (isgray(o)) { | 410 | if (isgray(o)) { |
418 | lua_assert(!keepinvariant(g) || testbit(o->gch.marked, TESTGRAYBIT)); | 411 | lua_assert(!keepinvariant(g) || testbit(o->gch.marked, TESTGRAYBIT)); |
419 | resetbit(o->gch.marked, TESTGRAYBIT); | 412 | resetbit(o->gch.marked, TESTGRAYBIT); |
@@ -432,14 +425,12 @@ int lua_checkmemory (lua_State *L) { | |||
432 | lua_assert(!iswhite(obj2gco(g->mainthread))); | 425 | lua_assert(!iswhite(obj2gco(g->mainthread))); |
433 | lua_assert(!iswhite(gcvalue(&g->l_registry))); | 426 | lua_assert(!iswhite(gcvalue(&g->l_registry))); |
434 | } | 427 | } |
435 | else /* generational mode keeps collector in 'propagate' state */ | ||
436 | lua_assert(!isgenerational(g)); | ||
437 | lua_assert(!isdead(g, gcvalue(&g->l_registry))); | 428 | lua_assert(!isdead(g, gcvalue(&g->l_registry))); |
438 | checkstack(g, g->mainthread); | 429 | checkstack(g, g->mainthread); |
439 | resetbit(g->mainthread->marked, TESTGRAYBIT); | 430 | resetbit(g->mainthread->marked, TESTGRAYBIT); |
440 | /* check 'allgc' list */ | 431 | /* check 'allgc' list */ |
441 | markgrays(g); | 432 | markgrays(g); |
442 | checkold(g, g->allgc); | 433 | checkgray(g, g->allgc); |
443 | lua_assert(g->sweepgc == NULL || issweepphase(g)); | 434 | lua_assert(g->sweepgc == NULL || issweepphase(g)); |
444 | maybedead = 0; | 435 | maybedead = 0; |
445 | for (o = g->allgc; o != NULL; o = gch(o)->next) { | 436 | for (o = g->allgc; o != NULL; o = gch(o)->next) { |
@@ -449,7 +440,7 @@ int lua_checkmemory (lua_State *L) { | |||
449 | lua_assert(!testbit(o->gch.marked, SEPARATED)); | 440 | lua_assert(!testbit(o->gch.marked, SEPARATED)); |
450 | } | 441 | } |
451 | /* check 'finobj' list */ | 442 | /* check 'finobj' list */ |
452 | checkold(g, g->finobj); | 443 | checkgray(g, g->finobj); |
453 | for (o = g->finobj; o != NULL; o = gch(o)->next) { | 444 | for (o = g->finobj; o != NULL; o = gch(o)->next) { |
454 | lua_assert(testbit(o->gch.marked, SEPARATED)); | 445 | lua_assert(testbit(o->gch.marked, SEPARATED)); |
455 | lua_assert(gch(o)->tt == LUA_TUSERDATA || | 446 | lua_assert(gch(o)->tt == LUA_TUSERDATA || |
@@ -457,7 +448,7 @@ int lua_checkmemory (lua_State *L) { | |||
457 | checkobject(g, o, 0); | 448 | checkobject(g, o, 0); |
458 | } | 449 | } |
459 | /* check 'tobefnz' list */ | 450 | /* check 'tobefnz' list */ |
460 | checkold(g, g->tobefnz); | 451 | checkgray(g, g->tobefnz); |
461 | for (o = g->tobefnz; o != NULL; o = gch(o)->next) { | 452 | for (o = g->tobefnz; o != NULL; o = gch(o)->next) { |
462 | lua_assert(!iswhite(o) || g->gcstate == GCSpause); | 453 | lua_assert(!iswhite(o) || g->gcstate == GCSpause); |
463 | lua_assert(!isdead(g, o) && testbit(o->gch.marked, SEPARATED)); | 454 | lua_assert(!isdead(g, o) && testbit(o->gch.marked, SEPARATED)); |
@@ -645,9 +636,6 @@ static int get_gccolor (lua_State *L) { | |||
645 | if (testbit(marked, FIXEDBIT)) { | 636 | if (testbit(marked, FIXEDBIT)) { |
646 | lua_pushliteral(L, "/fixed"); n++; | 637 | lua_pushliteral(L, "/fixed"); n++; |
647 | } | 638 | } |
648 | if (testbit(marked, OLDBIT)) { | ||
649 | lua_pushliteral(L, "/old"); n++; | ||
650 | } | ||
651 | lua_concat(L, n); | 639 | lua_concat(L, n); |
652 | } | 640 | } |
653 | return 1; | 641 | return 1; |
@@ -664,13 +652,9 @@ static int gc_state (lua_State *L) { | |||
664 | } | 652 | } |
665 | else { | 653 | else { |
666 | global_State *g = G(L); | 654 | global_State *g = G(L); |
667 | if (g->gckind == KGC_GEN && option == GCSpause) | ||
668 | luaL_error(L, "cannot go to 'pause' state in generational mode"); | ||
669 | lua_lock(L); | 655 | lua_lock(L); |
670 | if (option < g->gcstate) { /* must cross 'pause'? */ | 656 | if (option < g->gcstate) { /* must cross 'pause'? */ |
671 | luaC_runtilstate(L, bitmask(GCSpause)); /* run until pause */ | 657 | luaC_runtilstate(L, bitmask(GCSpause)); /* run until pause */ |
672 | if (g->gckind == KGC_GEN) | ||
673 | g->gcstate = GCSpropagate; /* skip pause in gen. mode */ | ||
674 | } | 658 | } |
675 | luaC_runtilstate(L, bitmask(option)); | 659 | luaC_runtilstate(L, bitmask(option)); |
676 | lua_assert(G(L)->gcstate == option); | 660 | lua_assert(G(L)->gcstate == option); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lua.h,v 1.291 2013/06/07 19:01:50 roberto Exp roberto $ | 2 | ** $Id: lua.h,v 1.292 2013/07/05 14:29:51 roberto Exp roberto $ |
3 | ** Lua - A Scripting Language | 3 | ** Lua - A Scripting Language |
4 | ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) | 4 | ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) |
5 | ** See Copyright Notice at the end of this file | 5 | ** See Copyright Notice at the end of this file |
@@ -288,10 +288,7 @@ LUA_API int (lua_status) (lua_State *L); | |||
288 | #define LUA_GCSTEP 5 | 288 | #define LUA_GCSTEP 5 |
289 | #define LUA_GCSETPAUSE 6 | 289 | #define LUA_GCSETPAUSE 6 |
290 | #define LUA_GCSETSTEPMUL 7 | 290 | #define LUA_GCSETSTEPMUL 7 |
291 | #define LUA_GCSETMAJORINC 8 | 291 | #define LUA_GCISRUNNING 8 |
292 | #define LUA_GCISRUNNING 9 | ||
293 | #define LUA_GCGEN 10 | ||
294 | #define LUA_GCINC 11 | ||
295 | 292 | ||
296 | LUA_API int (lua_gc) (lua_State *L, int what, int data); | 293 | LUA_API int (lua_gc) (lua_State *L, int what, int data); |
297 | 294 | ||