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; |
