diff options
| -rw-r--r-- | lgc.c | 62 | ||||
| -rw-r--r-- | lstate.c | 3 | ||||
| -rw-r--r-- | lstate.h | 5 |
3 files changed, 43 insertions, 27 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 2.123 2012/05/20 20:36:44 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.124 2012/05/21 13:18:10 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 | */ |
| @@ -49,6 +49,7 @@ | |||
| 49 | #define workrate(x,mul) \ | 49 | #define workrate(x,mul) \ |
| 50 | ((x) < MAX_INT/80 ? ((x) * 80) / mul : ((x) / mul) * 80) | 50 | ((x) < MAX_INT/80 ? ((x) * 80) / mul : ((x) / mul) * 80) |
| 51 | 51 | ||
| 52 | |||
| 52 | /* | 53 | /* |
| 53 | ** standard negative debt for GC; a reasonable "time" to wait before | 54 | ** standard negative debt for GC; a reasonable "time" to wait before |
| 54 | ** starting a new cycle | 55 | ** starting a new cycle |
| @@ -738,19 +739,16 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | |||
| 738 | freeobj(L, curr); /* erase 'curr' */ | 739 | freeobj(L, curr); /* erase 'curr' */ |
| 739 | } | 740 | } |
| 740 | else { | 741 | else { |
| 742 | if (testbits(marked, tostop)) | ||
| 743 | return NULL; /* stop sweeping this list */ | ||
| 741 | if (gch(curr)->tt == LUA_TTHREAD) | 744 | if (gch(curr)->tt == LUA_TTHREAD) |
| 742 | sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ | 745 | sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ |
| 743 | if (testbits(marked, tostop)) { | ||
| 744 | static GCObject *nullp = NULL; | ||
| 745 | p = &nullp; /* stop sweeping this list */ | ||
| 746 | break; | ||
| 747 | } | ||
| 748 | /* update marks */ | 746 | /* update marks */ |
| 749 | gch(curr)->marked = cast_byte((marked & toclear) | toset); | 747 | gch(curr)->marked = cast_byte((marked & toclear) | toset); |
| 750 | p = &gch(curr)->next; /* go to next element */ | 748 | p = &gch(curr)->next; /* go to next element */ |
| 751 | } | 749 | } |
| 752 | } | 750 | } |
| 753 | return p; | 751 | return (*p == NULL) ? NULL : p; |
| 754 | } | 752 | } |
| 755 | 753 | ||
| 756 | /* }====================================================== */ | 754 | /* }====================================================== */ |
| @@ -865,7 +863,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
| 865 | GCObject **p; | 863 | GCObject **p; |
| 866 | GCheader *ho = gch(o); | 864 | GCheader *ho = gch(o); |
| 867 | /* avoid removing current sweep object */ | 865 | /* avoid removing current sweep object */ |
| 868 | if (g->gcstate == GCSsweep && g->sweepgc == &ho->next) { | 866 | if (g->sweepgc == &ho->next) { |
| 869 | /* step to next object in the list */ | 867 | /* step to next object in the list */ |
| 870 | g->sweepgc = (ho->next == NULL) ? NULL : &gch(ho->next)->next; | 868 | g->sweepgc = (ho->next == NULL) ? NULL : &gch(ho->next)->next; |
| 871 | } | 869 | } |
| @@ -892,6 +890,24 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
| 892 | #define sweepphases \ | 890 | #define sweepphases \ |
| 893 | (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) | 891 | (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) |
| 894 | 892 | ||
| 893 | |||
| 894 | /* | ||
| 895 | ** enter first sweep phase (strings) and prepare pointers for other | ||
| 896 | ** sweep phases. The calls to 'sweeplist' attempt to make pointers | ||
| 897 | ** point to an object inside the list (instead of to the header), so | ||
| 898 | ** that the real sweep do not need to skip objects created between "now" | ||
| 899 | ** and the start of the real sweep. | ||
| 900 | */ | ||
| 901 | static void entersweep (lua_State *L) { | ||
| 902 | global_State *g = G(L); | ||
| 903 | g->gcstate = GCSsweepstring; | ||
| 904 | lua_assert(g->sweepgc == NULL && g->sweepfin == NULL); | ||
| 905 | g->sweepstrgc = 0; /* prepare to sweep strings, ... */ | ||
| 906 | g->sweepfin = sweeplist(L, &g->finobj, 1); /* finalizable objects, ... */ | ||
| 907 | g->sweepgc = sweeplist(L, &g->allgc, 1); /* and regular objects */ | ||
| 908 | } | ||
| 909 | |||
| 910 | |||
| 895 | /* | 911 | /* |
| 896 | ** change GC mode | 912 | ** change GC mode |
| 897 | */ | 913 | */ |
| @@ -907,9 +923,8 @@ void luaC_changemode (lua_State *L, int mode) { | |||
| 907 | else { /* change to incremental mode */ | 923 | else { /* change to incremental mode */ |
| 908 | /* sweep all objects to turn them back to white | 924 | /* sweep all objects to turn them back to white |
| 909 | (as white has not changed, nothing extra will be collected) */ | 925 | (as white has not changed, nothing extra will be collected) */ |
| 910 | g->sweepstrgc = 0; | ||
| 911 | g->gcstate = GCSsweepstring; | ||
| 912 | g->gckind = KGC_NORMAL; | 926 | g->gckind = KGC_NORMAL; |
| 927 | entersweep(L); | ||
| 913 | luaC_runtilstate(L, ~sweepphases); | 928 | luaC_runtilstate(L, ~sweepphases); |
| 914 | } | 929 | } |
| 915 | } | 930 | } |
| @@ -972,9 +987,8 @@ static void atomic (lua_State *L) { | |||
| 972 | /* clear values from resurrected weak tables */ | 987 | /* clear values from resurrected weak tables */ |
| 973 | clearvalues(g, g->weak, origweak); | 988 | clearvalues(g, g->weak, origweak); |
| 974 | clearvalues(g, g->allweak, origall); | 989 | clearvalues(g, g->allweak, origall); |
| 975 | g->sweepstrgc = 0; /* prepare to sweep strings */ | ||
| 976 | g->gcstate = GCSsweepstring; | ||
| 977 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ | 990 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ |
| 991 | entersweep(L); /* prepare to sweep strings */ | ||
| 978 | /*lua_checkmemory(L);*/ | 992 | /*lua_checkmemory(L);*/ |
| 979 | } | 993 | } |
| 980 | 994 | ||
| @@ -1010,25 +1024,22 @@ static lu_mem singlestep (lua_State *L) { | |||
| 1010 | for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++) | 1024 | for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++) |
| 1011 | sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]); | 1025 | sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]); |
| 1012 | g->sweepstrgc += i; | 1026 | g->sweepstrgc += i; |
| 1013 | if (g->sweepstrgc >= g->strt.size) { /* no more strings to sweep? */ | 1027 | if (g->sweepstrgc >= g->strt.size) /* no more strings to sweep? */ |
| 1014 | g->sweepgc = &g->finobj; /* prepare to sweep finalizable objects */ | ||
| 1015 | g->gcstate = GCSsweepudata; | 1028 | g->gcstate = GCSsweepudata; |
| 1016 | } | ||
| 1017 | return i * GCSWEEPCOST; | 1029 | return i * GCSWEEPCOST; |
| 1018 | } | 1030 | } |
| 1019 | case GCSsweepudata: { | 1031 | case GCSsweepudata: { |
| 1020 | if (*g->sweepgc) { | 1032 | if (g->sweepfin) { |
| 1021 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); | 1033 | g->sweepfin = sweeplist(L, g->sweepfin, GCSWEEPMAX); |
| 1022 | return GCSWEEPMAX*GCSWEEPCOST; | 1034 | return GCSWEEPMAX*GCSWEEPCOST; |
| 1023 | } | 1035 | } |
| 1024 | else { | 1036 | else { |
| 1025 | g->sweepgc = &g->allgc; /* go to next phase */ | ||
| 1026 | g->gcstate = GCSsweep; | 1037 | g->gcstate = GCSsweep; |
| 1027 | return 0; | 1038 | return 0; |
| 1028 | } | 1039 | } |
| 1029 | } | 1040 | } |
| 1030 | case GCSsweep: { | 1041 | case GCSsweep: { |
| 1031 | if (*g->sweepgc) { | 1042 | if (g->sweepgc) { |
| 1032 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); | 1043 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); |
| 1033 | return GCSWEEPMAX*GCSWEEPCOST; | 1044 | return GCSWEEPMAX*GCSWEEPCOST; |
| 1034 | } | 1045 | } |
| @@ -1121,16 +1132,19 @@ void luaC_step (lua_State *L) { | |||
| 1121 | void luaC_fullgc (lua_State *L, int isemergency) { | 1132 | void luaC_fullgc (lua_State *L, int isemergency) { |
| 1122 | global_State *g = G(L); | 1133 | global_State *g = G(L); |
| 1123 | int origkind = g->gckind; | 1134 | int origkind = g->gckind; |
| 1135 | int someblack = keepinvariant(g); | ||
| 1124 | lua_assert(origkind != KGC_EMERGENCY); | 1136 | lua_assert(origkind != KGC_EMERGENCY); |
| 1125 | if (!isemergency) /* do not run finalizers during emergency GC */ | 1137 | if (isemergency) /* do not run finalizers during emergency GC */ |
| 1138 | g->gckind = KGC_EMERGENCY; | ||
| 1139 | else { | ||
| 1140 | g->gckind = KGC_NORMAL; | ||
| 1126 | callallpendingfinalizers(L, 1); | 1141 | callallpendingfinalizers(L, 1); |
| 1127 | if (keepinvariant(g)) { /* marking phase? */ | 1142 | } |
| 1143 | if (someblack) { /* may there be some black objects? */ | ||
| 1128 | /* must sweep all objects to turn them back to white | 1144 | /* must sweep all objects to turn them back to white |
| 1129 | (as white has not changed, nothing will be collected) */ | 1145 | (as white has not changed, nothing will be collected) */ |
| 1130 | g->sweepstrgc = 0; | 1146 | entersweep(L); |
| 1131 | g->gcstate = GCSsweepstring; | ||
| 1132 | } | 1147 | } |
| 1133 | g->gckind = isemergency ? KGC_EMERGENCY : KGC_NORMAL; | ||
| 1134 | /* finish any pending sweep phase to start a new cycle */ | 1148 | /* finish any pending sweep phase to start a new cycle */ |
| 1135 | luaC_runtilstate(L, bitmask(GCSpause)); | 1149 | luaC_runtilstate(L, bitmask(GCSpause)); |
| 1136 | /* run entire collector */ | 1150 | /* run entire collector */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.c,v 2.93 2012/02/01 21:57:15 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.94 2012/05/11 14:06:07 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 | */ |
| @@ -292,6 +292,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
| 292 | g->allgc = NULL; | 292 | g->allgc = NULL; |
| 293 | g->finobj = NULL; | 293 | g->finobj = NULL; |
| 294 | g->tobefnz = NULL; | 294 | g->tobefnz = NULL; |
| 295 | g->sweepgc = g->sweepfin = NULL; | ||
| 295 | g->gray = g->grayagain = NULL; | 296 | g->gray = g->grayagain = NULL; |
| 296 | g->weak = g->ephemeron = g->allweak = NULL; | 297 | g->weak = g->ephemeron = g->allweak = NULL; |
| 297 | g->totalbytes = sizeof(LG); | 298 | g->totalbytes = sizeof(LG); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.h,v 2.77 2012/02/01 21:57:15 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.78 2012/05/20 20:36:44 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 | */ |
| @@ -126,7 +126,8 @@ typedef struct global_State { | |||
| 126 | int sweepstrgc; /* position of sweep in `strt' */ | 126 | int sweepstrgc; /* position of sweep in `strt' */ |
| 127 | GCObject *allgc; /* list of all collectable objects */ | 127 | GCObject *allgc; /* list of all collectable objects */ |
| 128 | GCObject *finobj; /* list of collectable objects with finalizers */ | 128 | GCObject *finobj; /* list of collectable objects with finalizers */ |
| 129 | GCObject **sweepgc; /* current position of sweep */ | 129 | GCObject **sweepgc; /* current position of sweep in list 'allgc' */ |
| 130 | GCObject **sweepfin; /* current position of sweep in list 'finobj' */ | ||
| 130 | GCObject *gray; /* list of gray objects */ | 131 | GCObject *gray; /* list of gray objects */ |
| 131 | GCObject *grayagain; /* list of objects to be traversed atomically */ | 132 | GCObject *grayagain; /* list of objects to be traversed atomically */ |
| 132 | GCObject *weak; /* list of tables with weak values */ | 133 | GCObject *weak; /* list of tables with weak values */ |
