aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lgc.c104
1 files changed, 47 insertions, 57 deletions
diff --git a/lgc.c b/lgc.c
index fb7bc456..e2195c0d 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.181 2014/04/02 16:44:42 roberto Exp roberto $ 2** $Id: lgc.c,v 2.182 2014/04/04 17:01:04 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*/
@@ -495,8 +495,7 @@ static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
495} 495}
496 496
497 497
498static lu_mem traversestack (global_State *g, lua_State *th) { 498static lu_mem traversethread (global_State *g, lua_State *th) {
499 int n = 0;
500 StkId o = th->stack; 499 StkId o = th->stack;
501 if (o == NULL) 500 if (o == NULL)
502 return 1; /* stack not completely built yet */ 501 return 1; /* stack not completely built yet */
@@ -514,16 +513,9 @@ static lu_mem traversestack (global_State *g, lua_State *th) {
514 g->twups = th; 513 g->twups = th;
515 } 514 }
516 } 515 }
517 else { 516 else if (g->gckind != KGC_EMERGENCY)
518 CallInfo *ci; 517 luaD_shrinkstack(th); /* do not change stack in emergency cycle */
519 for (ci = &th->base_ci; ci != th->ci; ci = ci->next) 518 return (sizeof(lua_State) + sizeof(TValue) * th->stacksize);
520 n++; /* count call infos to compute size */
521 /* should not change the stack during an emergency gc cycle */
522 if (g->gckind != KGC_EMERGENCY)
523 luaD_shrinkstack(th);
524 }
525 return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
526 sizeof(CallInfo) * n;
527} 519}
528 520
529 521
@@ -561,7 +553,7 @@ static void propagatemark (global_State *g) {
561 th->gclist = g->grayagain; 553 th->gclist = g->grayagain;
562 g->grayagain = o; /* insert into 'grayagain' list */ 554 g->grayagain = o; /* insert into 'grayagain' list */
563 black2gray(o); 555 black2gray(o);
564 size = traversestack(g, th); 556 size = traversethread(g, th);
565 break; 557 break;
566 } 558 }
567 case LUA_TPROTO: { 559 case LUA_TPROTO: {
@@ -838,6 +830,21 @@ static void GCTM (lua_State *L, int propagateerrors) {
838 830
839 831
840/* 832/*
833** call a few (up to 'g->gcfinnum') finalizers
834*/
835static int runafewfinalizers (lua_State *L) {
836 global_State *g = G(L);
837 unsigned int i;
838 lua_assert(!g->tobefnz || g->gcfinnum > 0);
839 for (i = 0; g->tobefnz && i < g->gcfinnum; i++)
840 GCTM(L, 1); /* call one finalizer */
841 g->gcfinnum = (!g->tobefnz) ? 0 /* nothing more to finalize? */
842 : g->gcfinnum * 2; /* else call a few more next time */
843 return i;
844}
845
846
847/*
841** call all pending finalizers 848** call all pending finalizers
842*/ 849*/
843static void callallpendingfinalizers (lua_State *L, int propagateerrors) { 850static void callallpendingfinalizers (lua_State *L, int propagateerrors) {
@@ -1064,10 +1071,15 @@ static lu_mem singlestep (lua_State *L) {
1064 g->gcstate = GCScallfin; 1071 g->gcstate = GCScallfin;
1065 return 0; 1072 return 0;
1066 } 1073 }
1067 case GCScallfin: { /* state to finish calling finalizers */ 1074 case GCScallfin: { /* call remaining finalizers */
1068 /* do nothing here; this state is handled by 'luaC_step' */ 1075 if (g->tobefnz && g->gckind != KGC_EMERGENCY) {
1069 g->gcstate = GCSpause; /* finish collection */ 1076 int n = runafewfinalizers(L);
1070 return 0; 1077 return (n * GCFINALIZECOST);
1078 }
1079 else { /* emergency mode or no more finalizers */
1080 g->gcstate = GCSpause; /* finish collection */
1081 return 0;
1082 }
1071 } 1083 }
1072 default: lua_assert(0); return 0; 1084 default: lua_assert(0); return 0;
1073 } 1085 }
@@ -1086,21 +1098,6 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
1086 1098
1087 1099
1088/* 1100/*
1089** run a few (up to 'g->gcfinnum') finalizers
1090*/
1091static int runafewfinalizers (lua_State *L) {
1092 global_State *g = G(L);
1093 unsigned int i;
1094 lua_assert(!g->tobefnz || g->gcfinnum > 0);
1095 for (i = 0; g->tobefnz && i < g->gcfinnum; i++)
1096 GCTM(L, 1); /* call one finalizer */
1097 g->gcfinnum = (!g->tobefnz) ? 0 /* nothing more to finalize? */
1098 : g->gcfinnum * 2; /* else call a few more next time */
1099 return i;
1100}
1101
1102
1103/*
1104** get GC debt and convert it from Kb to 'work units' (avoid zero debt 1101** get GC debt and convert it from Kb to 'work units' (avoid zero debt
1105** and overflows) 1102** and overflows)
1106*/ 1103*/
@@ -1117,20 +1114,14 @@ static l_mem getdebt (global_State *g) {
1117*/ 1114*/
1118void luaC_step (lua_State *L) { 1115void luaC_step (lua_State *L) {
1119 global_State *g = G(L); 1116 global_State *g = G(L);
1120 l_mem debt = getdebt(g); 1117 l_mem debt = getdebt(g); /* GC deficit (be paid now) */
1121 if (!g->gcrunning) { /* not running? */ 1118 if (!g->gcrunning) { /* not running? */
1122 luaE_setdebt(g, -GCSTEPSIZE * 10); /* avoid being called too often */ 1119 luaE_setdebt(g, -GCSTEPSIZE * 10); /* avoid being called too often */
1123 return; 1120 return;
1124 } 1121 }
1125 do { 1122 do { /* repeat until pause or enough "credit" (negative debt) */
1126 if (g->gcstate == GCScallfin && g->tobefnz) { 1123 lu_mem work = singlestep(L); /* perform one single step */
1127 unsigned int n = runafewfinalizers(L); 1124 debt -= work;
1128 debt -= (n * GCFINALIZECOST);
1129 }
1130 else { /* perform one single step */
1131 lu_mem work = singlestep(L);
1132 debt -= work;
1133 }
1134 } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); 1125 } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause);
1135 if (g->gcstate == GCSpause) 1126 if (g->gcstate == GCSpause)
1136 setpause(g); /* pause until next cycle */ 1127 setpause(g); /* pause until next cycle */
@@ -1143,31 +1134,30 @@ void luaC_step (lua_State *L) {
1143 1134
1144 1135
1145/* 1136/*
1146** performs a full GC cycle; if "isemergency", does not call 1137** Performs a full GC cycle; if "isemergency", set a flag to avoid
1147** finalizers (which could change stack positions) 1138** some operations which could change the interpreter state in some
1139** unexpected ways (running finalizers and shrinking some structures).
1140** Before running the collection, check 'keepinvariant'; if it is true,
1141** there may be some objects marked as black, so the collector has
1142** to sweep all objects to turn them back to white (as white has not
1143** changed, nothing will be collected).
1148*/ 1144*/
1149void luaC_fullgc (lua_State *L, int isemergency) { 1145void luaC_fullgc (lua_State *L, int isemergency) {
1150 global_State *g = G(L); 1146 global_State *g = G(L);
1151 lua_assert(g->gckind == KGC_NORMAL); 1147 lua_assert(g->gckind == KGC_NORMAL);
1152 if (isemergency) /* do not run finalizers during emergency GC */ 1148 if (isemergency) g->gckind = KGC_EMERGENCY; /* set flag */
1153 g->gckind = KGC_EMERGENCY; 1149 if (keepinvariant(g)) { /* black objects? */
1154 else 1150 entersweep(L); /* sweep everything to turn them back to white */
1155 callallpendingfinalizers(L, 1);
1156 if (keepinvariant(g)) { /* may there be some black objects? */
1157 /* must sweep all objects to turn them back to white
1158 (as white has not changed, nothing will be collected) */
1159 entersweep(L);
1160 } 1151 }
1161 /* finish any pending sweep phase to start a new cycle */ 1152 /* finish any pending sweep phase to start a new cycle */
1162 luaC_runtilstate(L, bitmask(GCSpause)); 1153 luaC_runtilstate(L, bitmask(GCSpause));
1163 luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ 1154 luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */
1164 luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */ 1155 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */
1165 /* estimate must be correct after full GC cycles */ 1156 /* estimate must be correct after a full GC cycle */
1166 lua_assert(g->GCestimate == gettotalbytes(g)); 1157 lua_assert(g->GCestimate == gettotalbytes(g));
1158 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
1167 g->gckind = KGC_NORMAL; 1159 g->gckind = KGC_NORMAL;
1168 setpause(g); 1160 setpause(g);
1169 if (!isemergency) /* do not run finalizers during emergency GC */
1170 callallpendingfinalizers(L, 1);
1171} 1161}
1172 1162
1173/* }====================================================== */ 1163/* }====================================================== */