diff options
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 62 |
1 files changed, 40 insertions, 22 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.170 2014/02/11 12:28:47 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.171 2014/02/13 12:11:34 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 | */ |
@@ -33,8 +33,8 @@ | |||
33 | /* maximum number of elements to sweep in each single step */ | 33 | /* maximum number of elements to sweep in each single step */ |
34 | #define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) | 34 | #define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) |
35 | 35 | ||
36 | /* maximum number of finalizers to call in each GC step */ | 36 | /* cost of calling one finalizer */ |
37 | #define GCFINALIZENUM 4 | 37 | #define GCFINALIZECOST GCSWEEPCOST |
38 | 38 | ||
39 | 39 | ||
40 | /* | 40 | /* |
@@ -960,6 +960,7 @@ static l_mem atomic (lua_State *L) { | |||
960 | origweak = g->weak; origall = g->allweak; | 960 | origweak = g->weak; origall = g->allweak; |
961 | work += g->GCmemtrav; /* stop counting (objects being finalized) */ | 961 | work += g->GCmemtrav; /* stop counting (objects being finalized) */ |
962 | separatetobefnz(g, 0); /* separate objects to be finalized */ | 962 | separatetobefnz(g, 0); /* separate objects to be finalized */ |
963 | g->gcfinnum = 1; /* there may be objects to be finalized */ | ||
963 | markbeingfnz(g); /* mark objects that will be finalized */ | 964 | markbeingfnz(g); /* mark objects that will be finalized */ |
964 | propagateall(g); /* remark, to propagate 'resurrection' */ | 965 | propagateall(g); /* remark, to propagate 'resurrection' */ |
965 | work -= g->GCmemtrav; /* restart counting */ | 966 | work -= g->GCmemtrav; /* restart counting */ |
@@ -1014,7 +1015,7 @@ static lu_mem singlestep (lua_State *L) { | |||
1014 | int sw; | 1015 | int sw; |
1015 | propagateall(g); /* make sure gray list is empty */ | 1016 | propagateall(g); /* make sure gray list is empty */ |
1016 | g->GCestimate = g->GCmemtrav; /* save what was counted */; | 1017 | g->GCestimate = g->GCmemtrav; /* save what was counted */; |
1017 | work = atomic(L); /* add what was traversed by 'atomic' */ | 1018 | work = atomic(L); /* work is what was traversed by 'atomic' */ |
1018 | g->GCestimate += work; /* estimate of total memory traversed */ | 1019 | g->GCestimate += work; /* estimate of total memory traversed */ |
1019 | sw = entersweep(L); | 1020 | sw = entersweep(L); |
1020 | return work + sw * GCSWEEPCOST; | 1021 | return work + sw * GCSWEEPCOST; |
@@ -1034,8 +1035,13 @@ static lu_mem singlestep (lua_State *L) { | |||
1034 | case GCSswpend: { /* finish sweeps */ | 1035 | case GCSswpend: { /* finish sweeps */ |
1035 | makewhite(g, obj2gco(g->mainthread)); /* sweep main thread */ | 1036 | makewhite(g, obj2gco(g->mainthread)); /* sweep main thread */ |
1036 | checkSizes(L, g); | 1037 | checkSizes(L, g); |
1038 | g->gcstate = GCScallfin; | ||
1039 | return 0; | ||
1040 | } | ||
1041 | case GCScallfin: { /* state to finish calling finalizers */ | ||
1042 | /* do nothing here; should be handled by 'luaC_forcestep' */ | ||
1037 | g->gcstate = GCSpause; /* finish collection */ | 1043 | g->gcstate = GCSpause; /* finish collection */ |
1038 | return GCSWEEPCOST; | 1044 | return 0; |
1039 | } | 1045 | } |
1040 | default: lua_assert(0); return 0; | 1046 | default: lua_assert(0); return 0; |
1041 | } | 1047 | } |
@@ -1053,7 +1059,25 @@ void luaC_runtilstate (lua_State *L, int statesmask) { | |||
1053 | } | 1059 | } |
1054 | 1060 | ||
1055 | 1061 | ||
1056 | static void incstep (lua_State *L) { | 1062 | /* |
1063 | ** run a few finalizers | ||
1064 | */ | ||
1065 | static int dosomefinalization (lua_State *L) { | ||
1066 | global_State *g = G(L); | ||
1067 | unsigned int i; | ||
1068 | lua_assert(!g->tobefnz || g->gcfinnum > 0); | ||
1069 | for (i = 0; g->tobefnz && i < g->gcfinnum; i++) | ||
1070 | GCTM(L, 1); /* call one finalizer */ | ||
1071 | g->gcfinnum = (!g->tobefnz) ? 0 /* nothing more to finalize? */ | ||
1072 | : g->gcfinnum * 2; /* else call a few more next time */ | ||
1073 | return i; | ||
1074 | } | ||
1075 | |||
1076 | |||
1077 | /* | ||
1078 | ** performs a basic GC step | ||
1079 | */ | ||
1080 | void luaC_forcestep (lua_State *L) { | ||
1057 | global_State *g = G(L); | 1081 | global_State *g = G(L); |
1058 | l_mem debt = g->GCdebt; | 1082 | l_mem debt = g->GCdebt; |
1059 | int stepmul = g->gcstepmul; | 1083 | int stepmul = g->gcstepmul; |
@@ -1061,33 +1085,27 @@ static void incstep (lua_State *L) { | |||
1061 | /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */ | 1085 | /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */ |
1062 | debt = (debt / STEPMULADJ) + 1; | 1086 | debt = (debt / STEPMULADJ) + 1; |
1063 | debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; | 1087 | debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; |
1064 | do { /* always perform at least one single step */ | 1088 | do { |
1065 | lu_mem work = singlestep(L); /* do some work */ | 1089 | if (g->gcstate == GCScallfin && g->tobefnz) { |
1066 | debt -= work; | 1090 | unsigned int n = dosomefinalization(L); |
1091 | debt -= (n * GCFINALIZECOST); | ||
1092 | } | ||
1093 | else { /* perform one single step */ | ||
1094 | lu_mem work = singlestep(L); | ||
1095 | debt -= work; | ||
1096 | } | ||
1067 | } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); | 1097 | } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); |
1068 | if (g->gcstate == GCSpause) | 1098 | if (g->gcstate == GCSpause) |
1069 | setpause(g, g->GCestimate); /* pause until next cycle */ | 1099 | setpause(g, g->GCestimate); /* pause until next cycle */ |
1070 | else { | 1100 | else { |
1071 | debt = (debt / stepmul) * STEPMULADJ; /* convert 'work units' to Kb */ | 1101 | debt = (debt / stepmul) * STEPMULADJ; /* convert 'work units' to Kb */ |
1072 | luaE_setdebt(g, debt); | 1102 | luaE_setdebt(g, debt); |
1103 | dosomefinalization(L); | ||
1073 | } | 1104 | } |
1074 | } | 1105 | } |
1075 | 1106 | ||
1076 | 1107 | ||
1077 | /* | 1108 | /* |
1078 | ** performs a basic GC step | ||
1079 | */ | ||
1080 | void luaC_forcestep (lua_State *L) { | ||
1081 | global_State *g = G(L); | ||
1082 | int i; | ||
1083 | incstep(L); | ||
1084 | /* run a few finalizers (or all of them at the end of a collect cycle) */ | ||
1085 | for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++) | ||
1086 | GCTM(L, 1); /* call one finalizer */ | ||
1087 | } | ||
1088 | |||
1089 | |||
1090 | /* | ||
1091 | ** performs a basic GC step when collector is running | 1109 | ** performs a basic GC step when collector is running |
1092 | */ | 1110 | */ |
1093 | void luaC_step (lua_State *L) { | 1111 | void luaC_step (lua_State *L) { |