diff options
-rw-r--r-- | lfunc.c | 5 | ||||
-rw-r--r-- | lgc.c | 102 | ||||
-rw-r--r-- | lgc.h | 3 | ||||
-rw-r--r-- | lstate.c | 4 | ||||
-rw-r--r-- | lstate.h | 4 | ||||
-rw-r--r-- | lstring.c | 4 |
6 files changed, 107 insertions, 15 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lfunc.c,v 2.32 2013/08/07 12:18:11 roberto Exp roberto $ | 2 | ** $Id: lfunc.c,v 2.33 2013/08/16 18:55:49 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 | */ |
@@ -21,7 +21,8 @@ | |||
21 | 21 | ||
22 | 22 | ||
23 | Closure *luaF_newCclosure (lua_State *L, int n) { | 23 | Closure *luaF_newCclosure (lua_State *L, int n) { |
24 | Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n), NULL, 0)->cl; | 24 | Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n), |
25 | &G(L)->localgc, 0)->cl; | ||
25 | c->c.nupvalues = cast_byte(n); | 26 | c->c.nupvalues = cast_byte(n); |
26 | return c; | 27 | return c; |
27 | } | 28 | } |
@@ -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 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.h,v 2.64 2013/08/21 19:21:16 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.65 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 | */ |
@@ -77,6 +77,7 @@ | |||
77 | #define BLACKBIT 2 /* object is black */ | 77 | #define BLACKBIT 2 /* object is black */ |
78 | #define FINALIZEDBIT 3 /* object has been marked for finalization */ | 78 | #define FINALIZEDBIT 3 /* object has been marked for finalization */ |
79 | #define LOCALBIT 4 /* object is not local */ | 79 | #define LOCALBIT 4 /* object is not local */ |
80 | #define LOCALBLACK 5 /* object is 'locally black' */ | ||
80 | /* bit 7 is currently used by tests (luaL_checkmemory) */ | 81 | /* bit 7 is currently used by tests (luaL_checkmemory) */ |
81 | 82 | ||
82 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) | 83 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.103 2013/08/21 19:21:16 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.104 2013/08/21 20:09:51 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 | */ |
@@ -280,6 +280,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
280 | g->seed = makeseed(L); | 280 | g->seed = makeseed(L); |
281 | g->gcrunning = 0; /* no GC while building state */ | 281 | g->gcrunning = 0; /* no GC while building state */ |
282 | g->GCestimate = 0; | 282 | g->GCestimate = 0; |
283 | g->GCthreshold = 10000; | ||
283 | g->strt.size = g->strt.nuse = g->strt.empty = 0; | 284 | g->strt.size = g->strt.nuse = g->strt.empty = 0; |
284 | g->strt.hash = NULL; | 285 | g->strt.hash = NULL; |
285 | setnilvalue(&g->l_registry); | 286 | setnilvalue(&g->l_registry); |
@@ -288,6 +289,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
288 | g->version = lua_version(NULL); | 289 | g->version = lua_version(NULL); |
289 | g->gcstate = GCSpause; | 290 | g->gcstate = GCSpause; |
290 | g->allgc = NULL; | 291 | g->allgc = NULL; |
292 | g->localgc = NULL; | ||
291 | g->finobj = NULL; | 293 | g->finobj = NULL; |
292 | g->tobefnz = NULL; | 294 | g->tobefnz = NULL; |
293 | g->fixedgc = NULL; | 295 | g->fixedgc = NULL; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 2.87 2013/08/21 20:09:51 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.88 2013/08/22 15:21:48 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 | */ |
@@ -118,6 +118,7 @@ typedef struct global_State { | |||
118 | l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ | 118 | l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ |
119 | lu_mem GCmemtrav; /* memory traversed by the GC */ | 119 | lu_mem GCmemtrav; /* memory traversed by the GC */ |
120 | lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ | 120 | lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ |
121 | lu_mem GCthreshold; /* threshold to start a new GC cycle */ | ||
121 | stringtable strt; /* hash table for strings */ | 122 | stringtable strt; /* hash table for strings */ |
122 | TValue l_registry; | 123 | TValue l_registry; |
123 | unsigned int seed; /* randomized seed for hashes */ | 124 | unsigned int seed; /* randomized seed for hashes */ |
@@ -126,6 +127,7 @@ typedef struct global_State { | |||
126 | lu_byte gckind; /* kind of GC running */ | 127 | lu_byte gckind; /* kind of GC running */ |
127 | lu_byte gcrunning; /* true if GC is running */ | 128 | lu_byte gcrunning; /* true if GC is running */ |
128 | GCObject *allgc; /* list of all collectable objects */ | 129 | GCObject *allgc; /* list of all collectable objects */ |
130 | GCObject *localgc; /* list of local objects */ | ||
129 | GCObject *finobj; /* list of collectable objects with finalizers */ | 131 | GCObject *finobj; /* list of collectable objects with finalizers */ |
130 | GCObject **sweepgc; /* current position of sweep in list 'allgc' */ | 132 | GCObject **sweepgc; /* current position of sweep in list 'allgc' */ |
131 | GCObject **sweepfin; /* current position of sweep in list 'finobj' */ | 133 | GCObject **sweepfin; /* current position of sweep in list 'finobj' */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.c,v 2.29 2013/08/21 19:21:16 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 2.30 2013/08/22 15:21:48 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 | */ |
@@ -106,7 +106,7 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l, | |||
106 | TString *ts; | 106 | TString *ts; |
107 | size_t totalsize; /* total size of TString object */ | 107 | size_t totalsize; /* total size of TString object */ |
108 | totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); | 108 | totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); |
109 | ts = &luaC_newobj(L, tag, totalsize, NULL, 0)->ts; | 109 | ts = &luaC_newobj(L, tag, totalsize, &G(L)->localgc, 0)->ts; |
110 | ts->tsv.len = l; | 110 | ts->tsv.len = l; |
111 | ts->tsv.hash = h; | 111 | ts->tsv.hash = h; |
112 | ts->tsv.extra = 0; | 112 | ts->tsv.extra = 0; |