diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-08-23 10:34:54 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-08-23 10:34:54 -0300 |
commit | 50955e27f592441a223c6267956e470f98eeb3c0 (patch) | |
tree | 4543b70e04d293c4eb09955d064f3446eb3e64a9 /lgc.c | |
parent | 33c49f7fa03cf7e3bf7bb3aa697dc567d910c661 (diff) | |
download | lua-50955e27f592441a223c6267956e470f98eeb3c0.tar.gz lua-50955e27f592441a223c6267956e470f98eeb3c0.tar.bz2 lua-50955e27f592441a223c6267956e470f98eeb3c0.zip |
C functions and strings now go to the local list; first version
of the local collector
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 102 |
1 files changed, 94 insertions, 8 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.149 2013/08/21 19:21:16 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.150 2013/08/21 20:09:51 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 | */ |
@@ -25,6 +25,12 @@ | |||
25 | 25 | ||
26 | 26 | ||
27 | /* | 27 | /* |
28 | ** How memory to allocate before a new local collection | ||
29 | */ | ||
30 | #define GCLOCALPAUSE 8000 | ||
31 | |||
32 | |||
33 | /* | ||
28 | ** cost of sweeping one element (the size of a small object divided | 34 | ** cost of sweeping one element (the size of a small object divided |
29 | ** by some adjust for the sweep speed) | 35 | ** by some adjust for the sweep speed) |
30 | */ | 36 | */ |
@@ -191,9 +197,9 @@ void luaC_checkupvalcolor (global_State *g, UpVal *uv) { | |||
191 | 197 | ||
192 | void luaC_fix (lua_State *L, GCObject *o) { | 198 | void luaC_fix (lua_State *L, GCObject *o) { |
193 | global_State *g = G(L); | 199 | global_State *g = G(L); |
194 | lua_assert(g->allgc == o); | 200 | lua_assert(g->localgc == o); |
195 | white2gray(o); | 201 | white2gray(o); |
196 | g->allgc = o->gch.next; /* remove object from 'allgc' list */ | 202 | g->localgc = o->gch.next; /* remove object from 'localgc' list */ |
197 | o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */ | 203 | o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */ |
198 | g->fixedgc = o; | 204 | g->fixedgc = o; |
199 | } | 205 | } |
@@ -875,6 +881,72 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
875 | 881 | ||
876 | /* | 882 | /* |
877 | ** {====================================================== | 883 | ** {====================================================== |
884 | ** Local Collection | ||
885 | ** ======================================================= | ||
886 | */ | ||
887 | |||
888 | /* | ||
889 | ** Traverse a thread, local marking all its collectable objects | ||
890 | */ | ||
891 | static void localmarkthread (lua_State *l) { | ||
892 | StkId o = l->stack; | ||
893 | if (o == NULL) | ||
894 | return; /* stack not completely built yet */ | ||
895 | for (; o < l->top; o++) { /* mark live elements in the stack */ | ||
896 | if (iscollectable(o)) | ||
897 | l_setbit(gcvalue(o)->gch.marked, LOCALBLACK); | ||
898 | } | ||
899 | } | ||
900 | |||
901 | |||
902 | /* | ||
903 | ** Mark all that is locally accessible (accessible directly from | ||
904 | ** a thread) | ||
905 | */ | ||
906 | static void localmark (global_State *g) { | ||
907 | GCObject *thread = hvalue(&g->l_registry)->next; | ||
908 | for (; thread != NULL; thread = gch(thread)->next) /* traverse all threads */ | ||
909 | localmarkthread(gco2th(thread)); | ||
910 | localmarkthread(g->mainthread); | ||
911 | } | ||
912 | |||
913 | |||
914 | static void localsweep (lua_State *L, global_State *g) { | ||
915 | GCObject **p = &g->localgc; | ||
916 | while (*p != NULL) { | ||
917 | GCObject *curr = *p; | ||
918 | if (!islocal(curr)) { /* is 'curr' no more local? */ | ||
919 | *p = curr->gch.next; /* remove 'curr' from list */ | ||
920 | curr->gch.next = g->allgc; /* link 'curr' in 'allgc' list */ | ||
921 | g->allgc = curr; | ||
922 | } | ||
923 | else { /* still local */ | ||
924 | if (testbit(curr->gch.marked, LOCALBLACK)) { /* locally alive? */ | ||
925 | resetbit(curr->gch.marked, LOCALBLACK); | ||
926 | p = &curr->gch.next; /* go to next element */ | ||
927 | } | ||
928 | else { /* object is dead */ | ||
929 | *p = curr->gch.next; /* remove 'curr' from list */ | ||
930 | freeobj(L, curr); /* erase 'curr' */ | ||
931 | } | ||
932 | } | ||
933 | } | ||
934 | } | ||
935 | |||
936 | |||
937 | static void luaC_localcollection (lua_State *L) { | ||
938 | global_State *g = G(L); | ||
939 | lua_assert(g->gcstate == GCSpause); | ||
940 | localmark(g); | ||
941 | localsweep(L, g); | ||
942 | } | ||
943 | |||
944 | /* }====================================================== */ | ||
945 | |||
946 | |||
947 | |||
948 | /* | ||
949 | ** {====================================================== | ||
878 | ** GC control | 950 | ** GC control |
879 | ** ======================================================= | 951 | ** ======================================================= |
880 | */ | 952 | */ |
@@ -885,13 +957,13 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
885 | ** cycle will start when memory use hits threshold | 957 | ** cycle will start when memory use hits threshold |
886 | */ | 958 | */ |
887 | static void setpause (global_State *g, l_mem estimate) { | 959 | static void setpause (global_State *g, l_mem estimate) { |
888 | l_mem debt, threshold; | 960 | l_mem threshold; |
889 | estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ | 961 | estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ |
890 | threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ | 962 | threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ |
891 | ? estimate * g->gcpause /* no overflow */ | 963 | ? estimate * g->gcpause /* no overflow */ |
892 | : MAX_LMEM; /* overflow; truncate to maximum */ | 964 | : MAX_LMEM; /* overflow; truncate to maximum */ |
893 | debt = -cast(l_mem, threshold - gettotalbytes(g)); | 965 | g->GCthreshold = threshold; |
894 | luaE_setdebt(g, debt); | 966 | luaE_setdebt(g, -GCLOCALPAUSE); |
895 | } | 967 | } |
896 | 968 | ||
897 | 969 | ||
@@ -936,6 +1008,7 @@ void luaC_freeallobjects (lua_State *L) { | |||
936 | g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ | 1008 | g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ |
937 | g->gckind = KGC_NORMAL; | 1009 | g->gckind = KGC_NORMAL; |
938 | sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ | 1010 | sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ |
1011 | sweepwholelist(L, &g->localgc); | ||
939 | sweepwholelist(L, &g->allgc); | 1012 | sweepwholelist(L, &g->allgc); |
940 | sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ | 1013 | sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ |
941 | lua_assert(g->strt.nuse == 0); | 1014 | lua_assert(g->strt.nuse == 0); |
@@ -1017,8 +1090,9 @@ static lu_mem singlestep (lua_State *L) { | |||
1017 | return GCSWEEPMAX*GCSWEEPCOST; | 1090 | return GCSWEEPMAX*GCSWEEPCOST; |
1018 | } | 1091 | } |
1019 | else { | 1092 | else { |
1093 | sweepwholelist(L, &g->localgc); | ||
1020 | g->gcstate = GCSsweep; | 1094 | g->gcstate = GCSsweep; |
1021 | return 0; | 1095 | return GCLOCALPAUSE / 4; /* some magic for now */ |
1022 | } | 1096 | } |
1023 | } | 1097 | } |
1024 | case GCSsweep: { | 1098 | case GCSsweep: { |
@@ -1090,7 +1164,19 @@ void luaC_forcestep (lua_State *L) { | |||
1090 | */ | 1164 | */ |
1091 | void luaC_step (lua_State *L) { | 1165 | void luaC_step (lua_State *L) { |
1092 | global_State *g = G(L); | 1166 | global_State *g = G(L); |
1093 | if (g->gcrunning) luaC_forcestep(L); | 1167 | if (g->gcrunning) { |
1168 | if (g->gcstate != GCSpause) { | ||
1169 | luaC_forcestep(L); | ||
1170 | } | ||
1171 | else { | ||
1172 | luaC_localcollection(L); | ||
1173 | if (gettotalbytes(g) > g->GCthreshold) { | ||
1174 | luaC_forcestep(L); /* restart collection */ | ||
1175 | } | ||
1176 | else | ||
1177 | luaE_setdebt(g, -GCLOCALPAUSE); | ||
1178 | } | ||
1179 | } | ||
1094 | else luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */ | 1180 | else luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */ |
1095 | } | 1181 | } |
1096 | 1182 | ||